diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..a41e61d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+[*.{cs,vb}]
+
+# IDE0003: Remove qualification
+dotnet_style_qualification_for_event = false:none
+
+# IDE0003: Remove qualification
+dotnet_style_qualification_for_field = false:none
+
+# IDE0003: Remove qualification
+dotnet_style_qualification_for_method = false:none
+
+# IDE0003: Remove qualification
+dotnet_style_qualification_for_property = false:none
+
+# IDE0060: Remove unused parameter
+dotnet_code_quality_unused_parameters = non_public:suggestion
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..2ce9ff1
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,31 @@
+name: .NET
+
+on:
+ push:
+ branches: [ main, master ]
+ pull_request:
+ branches: [ main, master ]
+
+jobs:
+ build_and_test:
+
+ runs-on: windows-latest
+
+ steps:
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 5.0.x
+ - name: Download latest Dalamud build
+ run: |
+ cd ..
+ curl -O https://goatcorp.github.io/dalamud-distrib/latest.zip
+ mkdir Dalamud
+ unzip latest.zip -d ./Dalamud/bin
+ - uses: actions/checkout@v2
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --no-restore
+ - name: Test
+ run: dotnet test --no-build --verbosity normal
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4ce6fdd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,340 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- Backup*.rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
\ No newline at end of file
diff --git a/Attributes/AliasesAttribute.cs b/Attributes/AliasesAttribute.cs
new file mode 100644
index 0000000..0045e63
--- /dev/null
+++ b/Attributes/AliasesAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace DiademCalculator.Attributes
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class AliasesAttribute : Attribute
+ {
+ public string[] Aliases { get; }
+
+ public AliasesAttribute(params string[] aliases)
+ {
+ Aliases = aliases;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Attributes/CommandAttribute.cs b/Attributes/CommandAttribute.cs
new file mode 100644
index 0000000..5ffa49f
--- /dev/null
+++ b/Attributes/CommandAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace DiademCalculator.Attributes
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class CommandAttribute : Attribute
+ {
+ public string Command { get; }
+
+ public CommandAttribute(string command)
+ {
+ Command = command;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Attributes/DoNotShowInHelpAttribute.cs b/Attributes/DoNotShowInHelpAttribute.cs
new file mode 100644
index 0000000..219adfd
--- /dev/null
+++ b/Attributes/DoNotShowInHelpAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace DiademCalculator
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class DoNotShowInHelpAttribute : Attribute
+ {
+ }
+}
\ No newline at end of file
diff --git a/Attributes/HelpMessageAttribute.cs b/Attributes/HelpMessageAttribute.cs
new file mode 100644
index 0000000..cc6f977
--- /dev/null
+++ b/Attributes/HelpMessageAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace DiademCalculator.Attributes
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class HelpMessageAttribute : Attribute
+ {
+ public string HelpMessage { get; }
+
+ public HelpMessageAttribute(string helpMessage)
+ {
+ HelpMessage = helpMessage;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DalamudPackager.targets b/DalamudPackager.targets
new file mode 100644
index 0000000..789e0da
--- /dev/null
+++ b/DalamudPackager.targets
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DiademCalculator.csproj b/DiademCalculator.csproj
new file mode 100644
index 0000000..1e9723c
--- /dev/null
+++ b/DiademCalculator.csproj
@@ -0,0 +1,60 @@
+
+
+
+ net5.0-windows7.0
+ 9.0
+ 1.0.0.0
+
+
+
+ false
+ x64
+ DiademCalculator
+ DiademCalculator
+
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\devPlugins\
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\Dalamud.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\FFXIVClientStructs.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\ImGui.NET.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\ImGuiScene.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\Lumina.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\Lumina.Excel.dll
+ false
+
+
+ C:\Users\User\AppData\Roaming\XIVLauncher\addon\Hooks\6.3.0.6\Newtonsoft.Json.dll
+ false
+
+
+
+
diff --git a/DiademCalculator.json b/DiademCalculator.json
new file mode 100644
index 0000000..4598fa7
--- /dev/null
+++ b/DiademCalculator.json
@@ -0,0 +1,7 @@
+{
+ "Name": "",
+ "Author": "",
+ "Description": "",
+ "RepoUrl": "",
+ "Tags": []
+}
\ No newline at end of file
diff --git a/DiademCalculator.sln b/DiademCalculator.sln
new file mode 100644
index 0000000..a7e8798
--- /dev/null
+++ b/DiademCalculator.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30011.22
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiademCalculator", "DiademCalculator.csproj", "{517A4352-7F10-48B9-B332-BB592157E377}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {517A4352-7F10-48B9-B332-BB592157E377}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {517A4352-7F10-48B9-B332-BB592157E377}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {517A4352-7F10-48B9-B332-BB592157E377}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {517A4352-7F10-48B9-B332-BB592157E377}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {737C58B1-7FE2-4A03-8D02-B0E137667789}
+ EndGlobalSection
+EndGlobal
diff --git a/DownloadGithubActions.sh b/DownloadGithubActions.sh
new file mode 100644
index 0000000..5aa23ce
--- /dev/null
+++ b/DownloadGithubActions.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+curl -O https://raw.githubusercontent.com/karashiiro/DalamudPluginProjectTemplate/master/.github/workflows/dotnet.yml
+mkdir .github
+mkdir .github/workflows
+mv dotnet.yml .github/workflows
\ No newline at end of file
diff --git a/README.md b/README.md
index c917e0f..4494021 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
# DiademCalculator
-xiv diadem points calculator addon
+xiv diadem points calculator plugin
diff --git a/Source/Configuration.cs b/Source/Configuration.cs
new file mode 100644
index 0000000..e7d5b37
--- /dev/null
+++ b/Source/Configuration.cs
@@ -0,0 +1,24 @@
+using Dalamud.Configuration;
+using Dalamud.Plugin;
+using Newtonsoft.Json;
+
+namespace DiademCalculator
+{
+ public class Configuration : IPluginConfiguration
+ {
+ public int Version { get; set; }
+
+ // Add any other properties or methods here.
+ [JsonIgnore] private DalamudPluginInterface pluginInterface;
+
+ public void Initialize(DalamudPluginInterface pluginInterface)
+ {
+ this.pluginInterface = pluginInterface;
+ }
+
+ public void Save()
+ {
+ this.pluginInterface.SavePluginConfig(this);
+ }
+ }
+}
diff --git a/Source/DiademResourceInfo.cs b/Source/DiademResourceInfo.cs
new file mode 100644
index 0000000..9273c9d
--- /dev/null
+++ b/Source/DiademResourceInfo.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DiademCalculator
+{
+ public struct DiademResourceInfo
+ {
+ public readonly uint Id;
+ public readonly int Set;
+ public readonly int ScripsReward;
+ public readonly int PointsReward;
+
+ public DiademResourceInfo(uint id, int set, int scripsReward, int pointsReward)
+ {
+ Id = id;
+ Set = set;
+ ScripsReward = scripsReward;
+ PointsReward = pointsReward;
+ }
+ }
+}
diff --git a/Source/IconsManager.cs b/Source/IconsManager.cs
new file mode 100644
index 0000000..1e704d4
--- /dev/null
+++ b/Source/IconsManager.cs
@@ -0,0 +1,48 @@
+using Dalamud.Utility;
+using ImGuiScene;
+using Lumina.Data.Files;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DiademCalculator
+{
+ public class IconsManager
+ {
+ private readonly Plugin plugin;
+ private readonly Dictionary cache = new Dictionary();
+
+ public IconsManager(Plugin plugin)
+ {
+ this.plugin = plugin;
+ }
+
+ public void LoadIcon(int id)
+ {
+ var path = $"ui/icon/{id / 1000 * 1000:000000}/{id:000000}.tex";
+ try
+ {
+ TexFile? iconFile = plugin.DataManager.GetFile(path);
+ if (iconFile != null)
+ {
+ var icon = plugin.PluginInterface.UiBuilder.LoadImageRaw(iconFile.GetRgbaImageData(), iconFile.Header.Width, iconFile.Header.Height, 4);
+ cache[id] = icon;
+ }
+ }
+ catch(Exception e)
+ {
+ plugin.Chat.Print(e.ToString());
+ }
+ }
+
+ public TextureWrap GetIcon(int id)
+ {
+ if (cache.TryGetValue(id, out var tex))
+ return tex;
+
+ return null;
+ }
+ }
+}
diff --git a/Source/Plugin.cs b/Source/Plugin.cs
new file mode 100644
index 0000000..d96db25
--- /dev/null
+++ b/Source/Plugin.cs
@@ -0,0 +1,255 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using Dalamud.Data;
+using Dalamud.Game;
+using Dalamud.Game.ClientState;
+using Dalamud.Game.ClientState.JobGauge;
+using Dalamud.Game.Command;
+using Dalamud.Game.Gui;
+using Dalamud.Interface;
+using Dalamud.IoC;
+using Dalamud.Logging;
+using Dalamud.Plugin;
+using Dalamud.Utility;
+using DiademCalculator.Attributes;
+using FFXIVClientStructs.FFXIV.Client.Game;
+using ImGuiNET;
+using ImGuiScene;
+using Lumina.Data.Files;
+
+namespace DiademCalculator
+{
+ public unsafe class Plugin : IDalamudPlugin
+ {
+ static readonly List _minerPreset = new List()
+ {
+ new DiademResourceInfo(29939, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Cloudstone
+ new DiademResourceInfo(29940, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Rock Salt
+ new DiademResourceInfo(29941, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Spring Water
+ new DiademResourceInfo(29942, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Aurum Regis Sand
+ new DiademResourceInfo(29943, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Jade
+ new DiademResourceInfo(29946, 10, 0, 4), //Grade 2 Skybuilders' Umbral Flarestone
+ new DiademResourceInfo(29947, 10, 0, 4), //Grade 2 Skybuilders' Umbral Levinshard
+
+ new DiademResourceInfo(31311, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Cloudstone
+ new DiademResourceInfo(31312, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Basilisk Egg
+ new DiademResourceInfo(31313, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Alumen
+ new DiademResourceInfo(31314, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Clay
+ new DiademResourceInfo(31315, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Granite
+ new DiademResourceInfo(31318, 5, 0, 2), //Grade 3 Skybuilders' Umbral Magma Shard
+ new DiademResourceInfo(31319, 5, 0, 2), //Grade 3 Skybuilders' Umbral Levinite
+
+ new DiademResourceInfo(32007, 5, 1, 0), //Grade 4 Skybuilders' Iron Ore
+ new DiademResourceInfo(32008, 5, 1, 0), //Grade 4 Skybuilders' Iron Sand
+ new DiademResourceInfo(32012, 5, 1, 0), //Grade 4 Skybuilders' Ore
+ new DiademResourceInfo(32013, 5, 1, 0), //Grade 4 Skybuilders' Rock Salt
+ new DiademResourceInfo(32014, 5, 1, 0), //Grade 4 Skybuilders' Mythrite Sand
+ new DiademResourceInfo(32020, 5, 2, 0), //Grade 4 Skybuilders' Electrum Ore
+ new DiademResourceInfo(32021, 5, 2, 0), //Grade 4 Skybuilders' Alumen
+ new DiademResourceInfo(32022, 5, 2, 0), //Grade 4 Skybuilders' Spring Water
+ new DiademResourceInfo(32023, 5, 2, 0), //Grade 4 Skybuilders' Gold Sand
+ new DiademResourceInfo(32024, 5, 2, 0), //Grade 4 Skybuilders' Ragstone
+ new DiademResourceInfo(32030, 5, 3, 13), //Grade 4 Skybuilders' Gold Ore
+ new DiademResourceInfo(32031, 5, 3, 13), //Grade 4 Skybuilders' Finest Rock Salt
+ new DiademResourceInfo(32032, 5, 3, 13), //Grade 4 Skybuilders' Truespring Water
+ new DiademResourceInfo(32033, 5, 3, 13), //Grade 4 Skybuilders' Mineral Sand
+ new DiademResourceInfo(32034, 5, 3, 13), //Grade 4 Skybuilders' Bluespirit Ore
+ new DiademResourceInfo(32040, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Cloudstone
+ new DiademResourceInfo(32041, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Spring Water
+ new DiademResourceInfo(32042, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Ice Stalagmite
+ new DiademResourceInfo(32043, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Silex
+ new DiademResourceInfo(32044, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Prismstone
+ new DiademResourceInfo(32047, 5, 5, 15), //Grade 4 Skybuilders' Umbral Flarerock
+ new DiademResourceInfo(32048, 5, 5, 15), //Grade 4 Skybuilders' Umbral Levinsand
+ };
+
+ static readonly List _botanistPreset = new List()
+ {
+ new DiademResourceInfo(29934, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Log
+ new DiademResourceInfo(29935, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Hardened Sap
+ new DiademResourceInfo(29936, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Wheat
+ new DiademResourceInfo(29937, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Cotton Boll
+ new DiademResourceInfo(29938, 10, 0, 3), //Grade 2 Artisanal Skybuilders' Dawn Lizard
+ new DiademResourceInfo(29944, 10, 0, 4), //Grade 2 Skybuilders' Umbral Galewood Log
+ new DiademResourceInfo(29945, 10, 0, 4), //Grade 2 Skybuilders' Umbral Earthcap
+
+ new DiademResourceInfo(31306, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Log
+ new DiademResourceInfo(31307, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Amber
+ new DiademResourceInfo(31308, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Cotton Boll
+ new DiademResourceInfo(31309, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Rice
+ new DiademResourceInfo(31310, 5, 0, 2), //Grade 3 Artisanal Skybuilders' Vine
+ new DiademResourceInfo(31316, 5, 0, 2), //Grade 3 Skybuilders' Umbral Galewood Sap
+ new DiademResourceInfo(31317, 5, 0, 2), //Grade 3 Skybuilders' Umbral Tortoise
+
+ new DiademResourceInfo(32005, 5, 1, 0), //Grade 4 Skybuilders' Switch
+ new DiademResourceInfo(32006, 5, 1, 0), //Grade 4 Skybuilders' Hemp
+ new DiademResourceInfo(32009, 5, 1, 0), //Grade 4 Skybuilders' Mahogany Log
+ new DiademResourceInfo(32010, 5, 1, 0), //Grade 4 Skybuilders' Sesame
+ new DiademResourceInfo(32011, 5, 1, 0), //Grade 4 Skybuilders' Cotton Boll
+ new DiademResourceInfo(32015, 5, 2, 0), //Grade 4 Skybuilders' Spruce Log
+ new DiademResourceInfo(32016, 5, 2, 0), //Grade 4 Skybuilders' Mistletoe
+ new DiademResourceInfo(32017, 5, 2, 0), //Grade 4 Skybuilders' Toad
+ new DiademResourceInfo(32018, 5, 2, 0), //Grade 4 Skybuilders' Vine
+ new DiademResourceInfo(32019, 5, 2, 0), //Grade 4 Skybuilders' Tea Leaves
+
+ new DiademResourceInfo(32025, 5, 3, 13), //Grade 4 Skybuilders' White Cedar Log
+ new DiademResourceInfo(32026, 5, 3, 13), //Grade 4 Skybuilders' Primordial Resin
+ new DiademResourceInfo(32027, 5, 3, 13), //Grade 4 Skybuilders' Wheat
+ new DiademResourceInfo(32028, 5, 3, 13), //Grade 4 Skybuilders' Gossamer Cotton Boll
+ new DiademResourceInfo(32029, 5, 3, 13), //Grade 4 Skybuilders' Tortoise
+ new DiademResourceInfo(32035, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Log
+ new DiademResourceInfo(32036, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Raspberry
+ new DiademResourceInfo(32037, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Caiman
+ new DiademResourceInfo(32038, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Cocoon
+ new DiademResourceInfo(32039, 5, 3, 13), //Grade 4 Artisanal Skybuilders' Barbgrass
+ new DiademResourceInfo(32045, 5, 5, 15), //Grade 4 Skybuilders' Umbral Galewood Branch
+ new DiademResourceInfo(32046, 5, 5, 15), //Grade 4 Skybuilders' Umbral Dirtleaf
+ };
+
+
+ static readonly List _fisherPreset = new List()
+ {
+
+ };
+
+
+ const int Scrip_Icon = 65073;
+ const int MIN_Icon = 62116;
+ const int BTN_Icon = 62117;
+ const int FSH_Icon = 62118;
+
+ public string Name => "Diadem Calculator";
+
+
+ [PluginService]
+ public DalamudPluginInterface PluginInterface { get; init; }
+
+ [PluginService]
+ public CommandManager Commands { get; init; }
+
+ [PluginService]
+ public ChatGui Chat { get; init; }
+
+ [PluginService]
+ public DataManager DataManager { get; private set; }
+
+ private readonly PluginCommandManager commandManager;
+ private readonly Configuration config;
+ private readonly IconsManager iconsManager;
+
+
+ private DateTime lastUpdate;
+ private int minPoints, btnPoints, fshPoints;
+ private int minScrips, btnScrips, fshScrips;
+
+
+ public Plugin()
+ {
+ this.config = (Configuration)PluginInterface.GetPluginConfig() ?? new Configuration();
+ this.config.Initialize(PluginInterface);
+
+ PluginInterface.UiBuilder.Draw += this.Draw;
+
+ commandManager = new PluginCommandManager(this, Commands);
+ iconsManager = new IconsManager(this);
+
+ iconsManager.LoadIcon(Scrip_Icon);
+ iconsManager.LoadIcon(FSH_Icon);
+ iconsManager.LoadIcon(BTN_Icon);
+ iconsManager.LoadIcon(MIN_Icon);
+ }
+
+ [Command("/diadem")]
+ public void Settings(string command, string args)
+ {
+
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+
+ this.commandManager.Dispose();
+
+ PluginInterface.SavePluginConfig(this.config);
+ PluginInterface.UiBuilder.Draw -= this.Draw;
+ }
+
+ public void Draw()
+ {
+ DrawStats();
+ }
+
+ void DrawStats()
+ {
+ ImGui.SetNextWindowPos(new Vector2(350, 185), ImGuiCond.FirstUseEver);
+ ImGui.SetNextWindowSize(new Vector2(100, 175), ImGuiCond.Always);
+ ImGui.SetNextWindowBgAlpha(1);
+
+ ImGui.Begin("DiademInspector", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize);
+
+ if ((DateTime.Now - lastUpdate).TotalMilliseconds > 50)
+ {
+ CalculatePoints(_minerPreset, out minPoints, out minScrips);
+ CalculatePoints(_botanistPreset, out btnPoints, out btnScrips);
+ CalculatePoints(_fisherPreset, out fshPoints, out fshScrips);
+ lastUpdate = DateTime.Now;
+ }
+
+ DrawIcon(iconsManager.GetIcon(BTN_Icon), new Vector2(5, 5));
+ DrawPoints(new Vector2(50, 10), btnPoints);
+
+ DrawIcon(iconsManager.GetIcon(MIN_Icon), new Vector2(5, 45));
+ DrawPoints(new Vector2(50, 50), minPoints);
+
+ DrawIcon(iconsManager.GetIcon(FSH_Icon), new Vector2(5, 85));
+ DrawPoints(new Vector2(50, 90), fshPoints);
+
+ DrawIcon(iconsManager.GetIcon(Scrip_Icon), new Vector2(5, 135));
+ DrawPoints(new Vector2(50, 140), minScrips + btnScrips + fshScrips);
+
+ ImGui.End();
+ }
+
+ void DrawIcon(TextureWrap iconTex, Vector2 localPos)
+ {
+ if (iconTex == null)
+ return;
+
+ var windowPos = ImGui.GetWindowPos();
+ var size = new Vector2(iconTex.Width, iconTex.Height);
+
+ var drawList = ImGui.GetWindowDrawList();
+ drawList.AddImage(iconTex.ImGuiHandle, windowPos + localPos, windowPos + localPos + size);
+ }
+
+ void DrawPoints(Vector2 localPos, int count)
+ {
+ ImGui.SetCursorPos(localPos);
+ ImGui.Text(count.ToString());
+ }
+
+ void CalculatePoints(List preset, out int points, out int scrips)
+ {
+ points = scrips = 0;
+
+ var manager = InventoryManager.Instance();
+ if (manager == null)
+ return;
+
+ foreach (var item in preset)
+ {
+ var count = manager->GetInventoryItemCount(item.Id, false, false, false) / item.Set;
+ points += count * item.PointsReward;
+ scrips += count * item.ScripsReward;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/Source/PluginCommandManager.cs b/Source/PluginCommandManager.cs
new file mode 100644
index 0000000..909150c
--- /dev/null
+++ b/Source/PluginCommandManager.cs
@@ -0,0 +1,88 @@
+using Dalamud.Game.Command;
+using Dalamud.Plugin;
+using DiademCalculator.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using static Dalamud.Game.Command.CommandInfo;
+
+namespace DiademCalculator
+{
+ public class PluginCommandManager : IDisposable
+ {
+ private readonly CommandManager commandManager;
+ private readonly (string, CommandInfo)[] pluginCommands;
+ private readonly THost host;
+
+ public PluginCommandManager(THost host, CommandManager commandManager)
+ {
+ this.commandManager = commandManager;
+ this.host = host;
+
+ this.pluginCommands = host.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)
+ .Where(method => method.GetCustomAttribute() != null)
+ .SelectMany(GetCommandInfoTuple)
+ .ToArray();
+
+ AddCommandHandlers();
+ }
+
+ // http://codebetter.com/patricksmacchia/2008/11/19/an-easy-and-efficient-way-to-improve-net-code-performances/
+ // Benchmarking this myself gave similar results, so I'm doing this to somewhat counteract using reflection to access command attributes.
+ // I like the convenience of attributes, but in principle it's a bit slower to use them as opposed to just initializing CommandInfos directly.
+ // It's usually sub-1 millisecond anyways, though. It probably doesn't matter at all.
+ private void AddCommandHandlers()
+ {
+ for (var i = 0; i < this.pluginCommands.Length; i++)
+ {
+ var (command, commandInfo) = this.pluginCommands[i];
+ this.commandManager.AddHandler(command, commandInfo);
+ }
+ }
+
+ private void RemoveCommandHandlers()
+ {
+ for (var i = 0; i < this.pluginCommands.Length; i++)
+ {
+ var (command, _) = this.pluginCommands[i];
+ this.commandManager.RemoveHandler(command);
+ }
+ }
+
+ private IEnumerable<(string, CommandInfo)> GetCommandInfoTuple(MethodInfo method)
+ {
+ var handlerDelegate = (HandlerDelegate)Delegate.CreateDelegate(typeof(HandlerDelegate), this.host, method);
+
+ var command = handlerDelegate.Method.GetCustomAttribute();
+ var aliases = handlerDelegate.Method.GetCustomAttribute();
+ var helpMessage = handlerDelegate.Method.GetCustomAttribute();
+ var doNotShowInHelp = handlerDelegate.Method.GetCustomAttribute();
+
+ var commandInfo = new CommandInfo(handlerDelegate)
+ {
+ HelpMessage = helpMessage?.HelpMessage ?? string.Empty,
+ ShowInHelp = doNotShowInHelp == null,
+ };
+
+ // Create list of tuples that will be filled with one tuple per alias, in addition to the base command tuple.
+ var commandInfoTuples = new List<(string, CommandInfo)> { (command.Command, commandInfo) };
+ if (aliases != null)
+ {
+ // ReSharper disable once LoopCanBeConvertedToQuery
+ for (var i = 0; i < aliases.Aliases.Length; i++)
+ {
+ commandInfoTuples.Add((aliases.Aliases[i], commandInfo));
+ }
+ }
+
+ return commandInfoTuples;
+ }
+
+ public void Dispose()
+ {
+ RemoveCommandHandlers();
+ GC.SuppressFinalize(this);
+ }
+ }
+}