Add crafting actions and plugin stuff and everything

This commit is contained in:
Asriel Camora
2023-06-13 11:54:49 -07:00
parent bea568013c
commit f75220bc36
47 changed files with 965 additions and 43 deletions
+10 -11
View File
@@ -1,25 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.33530.505 VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Craftimizer", "Craftimizer\Craftimizer.csproj", "{80C60B1F-5A36-4C9E-99AF-85C536803ED5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Craftimizer", "Craftimizer\Craftimizer.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{80C60B1F-5A36-4C9E-99AF-85C536803ED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.ActiveCfg = Debug|x64
{80C60B1F-5A36-4C9E-99AF-85C536803ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64
{80C60B1F-5A36-4C9E-99AF-85C536803ED5}.Release|Any CPU.ActiveCfg = Release|Any CPU {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64
{80C60B1F-5A36-4C9E-99AF-85C536803ED5}.Release|Any CPU.Build.0 = Release|Any CPU {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {264E77E3-4028-4EA7-A3E7-9B84BDFEA6B9} SolutionGuid = {B17E85B1-5F60-4440-9F9A-3DDE877E8CDF}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal
+62 -5
View File
@@ -1,14 +1,71 @@
<Project Sdk="Microsoft.NET.Sdk"> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Authors></Authors>
<Company></Company>
<Version>0.0.0.1</Version>
<Description>A sample plugin.</Description>
<Copyright></Copyright>
<PackageProjectUrl>https://github.com/goatcorp/SamplePlugin</PackageProjectUrl>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <TargetFramework>net7.0-windows</TargetFramework>
<TargetFramework>net7.0</TargetFramework> <Platforms>x64</Platforms>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.11" /> <Content Include="..\Data\goat.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
<PropertyGroup>
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<DalamudLibPath>$(DALAMUD_HOME)/</DalamudLibPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.10" />
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Dalamud">
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="ImGuiScene">
<HintPath>$(DalamudLibPath)ImGuiScene.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>
+12
View File
@@ -0,0 +1,12 @@
{
"Author": "WorkingRobot",
"Name": "Craftimizer",
"Punchline": "Craft stuff xd",
"Description": "In-game craftiming optimizer",
"InternalName": "craftimizer",
"ApplicableVersion": "any",
"Tags": [
"crafting",
"simulator"
]
}
+15
View File
@@ -0,0 +1,15 @@
using Dalamud.Configuration;
using System;
namespace Craftimizer.Plugin;
[Serializable]
public class Configuration : IPluginConfiguration
{
public int Version { get; set; } = 0;
public void Save()
{
Service.PluginInterface.SavePluginConfig(this);
}
}
+11
View File
@@ -0,0 +1,11 @@
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
namespace Craftimizer.Plugin;
public static class LuminaSheets
{
public static readonly ExcelSheet<Recipe> RecipeSheet = Service.DataManager.GetExcelSheet<Recipe>()!;
public static readonly ExcelSheet<RecipeLevelTable> RecipeLevelTableSheet = Service.DataManager.GetExcelSheet<RecipeLevelTable>()!;
public static readonly ExcelSheet<ParamGrow> ParamGrowSheet = Service.DataManager.GetExcelSheet<ParamGrow>()!;
}
+38
View File
@@ -0,0 +1,38 @@
using Dalamud.Game.Command;
using Dalamud.IoC;
using Dalamud.Plugin;
namespace Craftimizer.Plugin;
public sealed class Plugin : IDalamudPlugin
{
public string Name => "Craftimizer";
public Configuration Configuration { get; }
public Plugin(
[RequiredVersion("1.0")] DalamudPluginInterface pluginInterface)
{
pluginInterface.Create<Service>();
Configuration = pluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
Service.CommandManager.AddHandler("/craft", new CommandInfo(OnCommand)
{
HelpMessage = "A useful message to display in /xlhelp"
});
//PluginInterface.UiBuilder.OpenConfigUi += () { };
}
public void Dispose()
{
Service.CommandManager.RemoveHandler("/craft");
}
private void OnCommand(string command, string args)
{
if (command != "/craft")
return;
}
}
+26
View File
@@ -0,0 +1,26 @@
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Dalamud.Game;
using Dalamud.IoC;
using Dalamud.Plugin;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.Command;
namespace Craftimizer.Plugin;
public sealed class Service
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
[PluginService] public static DalamudPluginInterface PluginInterface { get; private set; }
[PluginService] public static CommandManager CommandManager { get; private set; }
[PluginService] public static ObjectTable Objects { get; private set; }
[PluginService] public static SigScanner SigScanner { get; private set; }
[PluginService] public static GameGui GameGui { get; private set; }
[PluginService] public static ClientState ClientState { get; private set; }
[PluginService] public static DataManager DataManager { get; private set; }
[PluginService] public static TargetManager TargetManager { get; private set; }
[PluginService] public static Condition Condition { get; private set; }
#pragma warning restore CS8618
}
-9
View File
@@ -1,9 +0,0 @@
namespace Craftimizer;
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
-18
View File
@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Craftimizer;
internal record Recipe
{
public int Difficulty { get; init; }
public int Durability { get; init; }
public int Quality { get; init; }
public int Progress { get; init; }
public int Level { get; init; }
public int MaxLevel { get; init; }
public int ID { get; init; }
}
+11
View File
@@ -0,0 +1,11 @@
namespace Craftimizer.Simulator;
internal enum ActionCategory
{
FirstTurn,
Synthesis,
Quality,
Durability,
Buffs,
Other
}
@@ -0,0 +1,15 @@
namespace Craftimizer.Simulator.Actions;
internal class AdvancedTouch : BaseAction
{
public AdvancedTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 84;
public override int CPCost => Simulation.GetPreviousAction() is StandardTouch && Simulation.GetPreviousAction(2) is BasicTouch ? 18 : 46;
public override float Efficiency => 1.50f;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,33 @@
namespace Craftimizer.Simulator.Actions;
internal abstract class BaseAction
{
protected Simulation Simulation { get; }
public BaseAction(Simulation simulation)
{
Simulation = simulation;
}
public abstract ActionCategory Category { get; }
public abstract int Level { get; }
public abstract int CPCost { get; }
public abstract float Efficiency { get; }
public virtual float SuccessRate => 1f;
public virtual int DurabilityCost => 10;
public virtual bool CanUse =>
Simulation.Stats.Level >= Level && Simulation.CP >= CPCost;
public virtual void Use()
{
Simulation.ReduceCP(CPCost);
Simulation.ReduceDurability(DurabilityCost);
if (Simulation.RollSuccess(SuccessRate))
UseSuccess();
}
public abstract void UseSuccess();
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class BasicSynthesis : BaseAction
{
public BasicSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 1;
public override int CPCost => 0;
// Basic Synthesis Mastery Trait
public override float Efficiency => Simulation.Stats.Level >= 31 ? 1.20f : 1.00f;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,15 @@
namespace Craftimizer.Simulator.Actions;
internal class BasicTouch : BaseAction
{
public BasicTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 5;
public override int CPCost => 18;
public override float Efficiency => 1.00f;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,17 @@
namespace Craftimizer.Simulator.Actions;
internal class ByregotsBlessing : BaseAction
{
public ByregotsBlessing(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 50;
public override int CPCost => 24;
public override float Efficiency => 1.00f + 0.20f * (Simulation.GetEffect(Effect.InnerQuiet)?.Strength ?? 0);
public override bool CanUse => Simulation.HasEffect(Effect.InnerQuiet) && base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class CarefulSynthesis : BaseAction
{
public CarefulSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 62;
public override int CPCost => 7;
// Careful Synthesis Mastery Trait
public override float Efficiency => Simulation.Stats.Level >= 82 ? 1.80f : 1.50f;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,18 @@
namespace Craftimizer.Simulator.Actions;
internal class DelicateSynthesis : BaseAction
{
public DelicateSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 76;
public override int CPCost => 32;
public override float Efficiency => 1.00f;
public override void UseSuccess()
{
Simulation.IncreaseQuality(Efficiency);
Simulation.IncreaseProgress(Efficiency);
}
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class FinalAppraisal : BaseAction
{
public FinalAppraisal(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 42;
public override int CPCost => 1;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.AddEffect(Effect.FinalAppraisal, 5);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class FocusedSynthesis : BaseAction
{
public FocusedSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 67;
public override int CPCost => 5;
public override float Efficiency => 2.00f;
public override float SuccessRate => Simulation.GetPreviousAction() is Observe ? 1.00f : 0.50f;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class FocusedTouch : BaseAction
{
public FocusedTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 68;
public override int CPCost => 18;
public override float Efficiency => 1.50f;
public override float SuccessRate => Simulation.GetPreviousAction() is Observe ? 1.00f : 0.50f;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class GreatStrides : BaseAction
{
public GreatStrides(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Buffs;
public override int Level => 21;
public override int CPCost => 32;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.AddEffect(Effect.GreatStrides, 3);
}
@@ -0,0 +1,17 @@
namespace Craftimizer.Simulator.Actions;
internal class Groundwork : BaseAction
{
public Groundwork(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 72;
public override int CPCost => 18;
// Groundwork Mastery Trait
public override float Efficiency => Simulation.Stats.Level >= 86 ? 3.60f : 3.00f;
public override int DurabilityCost => 20;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class HastyTouch : BaseAction
{
public HastyTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 9;
public override int CPCost => 0;
public override float Efficiency => 1.00f;
public override float SuccessRate => 0.60f;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class Innovation : BaseAction
{
public Innovation(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Buffs;
public override int Level => 26;
public override int CPCost => 18;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.AddEffect(Effect.Innovation, 4);
}
@@ -0,0 +1,19 @@
namespace Craftimizer.Simulator.Actions;
internal class IntensiveSynthesis : BaseAction
{
public IntensiveSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 78;
public override int CPCost => 6;
public override float Efficiency => 4.00f;
public override bool CanUse =>
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
&& base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class Manipulation : BaseAction
{
public Manipulation(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Durability;
public override int Level => 65;
public override int CPCost => 96;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.AddEffect(Effect.Manipulation, 8);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class MastersMend : BaseAction
{
public MastersMend(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Durability;
public override int Level => 7;
public override int CPCost => 88;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.RestoreDurability(30);
}
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class MuscleMemory : BaseAction
{
public MuscleMemory(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.FirstTurn;
public override int Level => 54;
public override int CPCost => 6;
public override float Efficiency => 3.00f;
public override bool CanUse => Simulation.IsFirstStep && base.CanUse;
public override void UseSuccess()
{
Simulation.IncreaseProgress(Efficiency);
Simulation.AddEffect(Effect.MuscleMemory, 5);
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace Craftimizer.Simulator.Actions;
internal class Observe : BaseAction
{
public Observe(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Other;
public override int Level => 13;
public override int CPCost => 7;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() { }
}
@@ -0,0 +1,22 @@
namespace Craftimizer.Simulator.Actions;
internal class PreciseTouch : BaseAction
{
public PreciseTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 53;
public override int CPCost => 18;
public override float Efficiency => 1.50f;
public override bool CanUse =>
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
&& base.CanUse;
public override void UseSuccess()
{
Simulation.IncreaseQuality(Efficiency);
Simulation.StrengthenEffect(Effect.InnerQuiet);
}
}
@@ -0,0 +1,19 @@
namespace Craftimizer.Simulator.Actions;
internal class PreparatoryTouch : BaseAction
{
public PreparatoryTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 71;
public override int CPCost => 40;
public override float Efficiency => 2.00f;
public override int DurabilityCost => 20;
public override void UseSuccess()
{
Simulation.IncreaseQuality(Efficiency);
Simulation.StrengthenEffect(Effect.InnerQuiet);
}
}
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class PrudentSynthesis : BaseAction
{
public PrudentSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 88;
public override int CPCost => 18;
public override float Efficiency => 1.80f;
public override int DurabilityCost => base.DurabilityCost / 2;
public override bool CanUse =>
!(Simulation.HasEffect(Effect.WasteNot) || Simulation.HasEffect(Effect.WasteNot2))
&& base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class PrudentTouch : BaseAction
{
public PrudentTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 66;
public override int CPCost => 25;
public override float Efficiency => 1.00f;
public override int DurabilityCost => base.DurabilityCost / 2;
public override bool CanUse =>
!(Simulation.HasEffect(Effect.WasteNot) || Simulation.HasEffect(Effect.WasteNot2))
&& base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,17 @@
namespace Craftimizer.Simulator.Actions;
internal class RapidSynthesis : BaseAction
{
public RapidSynthesis(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Synthesis;
public override int Level => 9;
public override int CPCost => 0;
// Rapid Synthesis Mastery Trait
public override float Efficiency => Simulation.Stats.Level >= 63 ? 5.00f : 2.50f;
public override float SuccessRate => 0.50f;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
+20
View File
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class Reflect : BaseAction
{
public Reflect(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.FirstTurn;
public override int Level => 69;
public override int CPCost => 6;
public override float Efficiency => 1.00f;
public override bool CanUse => Simulation.IsFirstStep && base.CanUse;
public override void UseSuccess()
{
Simulation.IncreaseQuality(Efficiency);
Simulation.StrengthenEffect(Effect.InnerQuiet);
}
}
@@ -0,0 +1,15 @@
namespace Craftimizer.Simulator.Actions;
internal class StandardTouch : BaseAction
{
public StandardTouch(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 18;
public override int CPCost => Simulation.GetPreviousAction() is BasicTouch ? 18 : 32;
public override float Efficiency => 1.25f;
public override void UseSuccess() =>
Simulation.IncreaseQuality(Efficiency);
}
@@ -0,0 +1,17 @@
namespace Craftimizer.Simulator.Actions;
internal class TrainedEye : BaseAction
{
public TrainedEye(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.FirstTurn;
public override int Level => 80;
public override int CPCost => 250;
public override float Efficiency => 0f;
public override bool CanUse => Simulation.IsFirstStep && base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseQuality(float.PositiveInfinity);
}
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class TrainedFinesse : BaseAction
{
public TrainedFinesse(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Quality;
public override int Level => 90;
public override int CPCost => 32;
public override float Efficiency => 1.00f;
public override int DurabilityCost => 0;
public override bool CanUse =>
(Simulation.GetEffect(Effect.InnerQuiet)?.Strength ?? 0) == 10
&& base.CanUse;
public override void UseSuccess() =>
Simulation.IncreaseProgress(Efficiency);
}
@@ -0,0 +1,20 @@
namespace Craftimizer.Simulator.Actions;
internal class TricksOfTheTrade : BaseAction
{
public TricksOfTheTrade(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Other;
public override int Level => 13;
public override int CPCost => 0;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override bool CanUse =>
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
&& base.CanUse;
public override void UseSuccess() =>
Simulation.RestoreCP(20);
}
@@ -0,0 +1,16 @@
namespace Craftimizer.Simulator.Actions;
internal class Veneration : BaseAction
{
public Veneration(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Buffs;
public override int Level => 15;
public override int CPCost => 18;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess() =>
Simulation.AddEffect(Effect.Veneration, 4);
}
+19
View File
@@ -0,0 +1,19 @@
namespace Craftimizer.Simulator.Actions;
internal class WasteNot : BaseAction
{
public WasteNot(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Durability;
public override int Level => 15;
public override int CPCost => 56;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess()
{
Simulation.RemoveEffect(Effect.WasteNot2);
Simulation.AddEffect(Effect.WasteNot, 4);
}
}
@@ -0,0 +1,19 @@
namespace Craftimizer.Simulator.Actions;
internal class WasteNot2 : BaseAction
{
public WasteNot2(Simulation simulation) : base(simulation) { }
public override ActionCategory Category => ActionCategory.Durability;
public override int Level => 47;
public override int CPCost => 98;
public override float Efficiency => 0f;
public override int DurabilityCost => 0;
public override void UseSuccess()
{
Simulation.RemoveEffect(Effect.WasteNot);
Simulation.AddEffect(Effect.WasteNot2, 8);
}
}
+16
View File
@@ -0,0 +1,16 @@
using System.Linq;
using Craftimizer.Plugin;
namespace Craftimizer.Simulator;
internal record CharacterStats
{
public int Craftsmanship { get; }
public int Control { get; }
public int CP { get; }
public int Level { get; }
public int CLvl => Level <= 80
? LuminaSheets.ParamGrowSheet.GetRow((uint)Level)!.CraftingLevel
: (int)LuminaSheets.RecipeLevelTableSheet.First(r => r.ClassJobLevel == Level).RowId;
}
+15
View File
@@ -0,0 +1,15 @@
namespace Craftimizer.Simulator;
internal enum Condition
{
Poor,
Normal,
Good,
Excellent,
//Centered,
//Sturdy,
//Pliant,
//Malleable,
//Primed
}
+14
View File
@@ -0,0 +1,14 @@
namespace Craftimizer.Simulator;
internal enum Effect
{
InnerQuiet,
WasteNot,
Veneration,
GreatStrides,
Innovation,
FinalAppraisal,
WasteNot2,
MuscleMemory,
Manipulation,
}
+149
View File
@@ -0,0 +1,149 @@
using Craftimizer.Simulator.Actions;
using Lumina.Excel.GeneratedSheets;
using System;
using System.Collections.Generic;
namespace Craftimizer.Simulator;
internal class Simulation
{
public CharacterStats Stats { get; }
public Recipe Recipe { get; }
public RecipeLevelTable RecipeTable => Recipe.RecipeLevelTable.Value!;
public int RLvl => (int)RecipeTable.RowId;
public int StepCount => ActionHistory.Count;
public int Progress { get; private set; }
public int Quality { get; private set; }
public int Durability { get; private set; }
public int CP { get; private set; }
public Condition Condition { get; private set; }
public List<(Effect effect, int strength, int stepsLeft)> ActiveEffects { get; } = new();
public List<BaseAction> ActionHistory { get; } = new();
public bool IsFirstStep => StepCount == 0;
private Random Random { get; } = new();
public Simulation(CharacterStats stats, Recipe recipe)
{
Stats = stats;
Recipe = recipe;
}
public (int Strength, int Duration)? GetEffect(Effect effect)
{
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
if (idx == -1)
return null;
var (_, strength, duration) = ActiveEffects[idx];
return (strength, duration);
}
public void AddEffect(Effect effect, int duration, int strength = 1)
{
// Duration will be decreased in the next step, so we need to add 1
duration += 1;
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
if (idx == -1)
ActiveEffects.Add((effect, strength, duration));
else
ActiveEffects[idx] = (effect, strength, duration);
}
public void StrengthenEffect(Effect effect, int duration = -1)
{
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
if (idx == -1)
ActiveEffects.Add((effect, 1, duration));
else
ActiveEffects[idx] = (effect, ActiveEffects[idx].strength + 1, duration);
}
public void RemoveEffect(Effect effect)
{
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
if (idx != -1)
ActiveEffects.RemoveAt(idx);
}
public bool HasEffect(Effect effect) => GetEffect(effect) != null;
public BaseAction? GetPreviousAction(int stepsBack = 1)
{
return StepCount < stepsBack ? null : ActionHistory[^stepsBack];
}
public bool RollSuccess(float successRate) =>
successRate >= Random.NextSingle();
public void ReduceDurability(int amount)
{
if (HasEffect(Effect.WasteNot) || HasEffect(Effect.WasteNot2))
amount /= 2;
Durability -= amount;
}
public void RestoreDurability(int amount)
{
Durability += amount;
}
public void ReduceCP(int amount)
{
CP -= amount;
}
public void RestoreCP(int amount)
{
CP += amount;
}
public void IncreaseProgress(float efficiency)
{
if (HasEffect(Effect.MuscleMemory))
{
efficiency += 1.00f;
RemoveEffect(Effect.MuscleMemory);
}
if (HasEffect(Effect.Veneration))
efficiency += 0.50f;
// https://github.com/NotRanged/NotRanged.github.io/blob/0f4aee074f969fb05aad34feaba605057c08ffd1/app/js/ffxivcraftmodel.js#L88
var baseIncrease = Stats.Craftsmanship * 10 / RecipeTable.ProgressDivider + 2;
if (Stats.CLvl <= RLvl)
baseIncrease *= RecipeTable.ProgressModifier / 100;
Progress += (int)(baseIncrease * efficiency);
}
public void IncreaseQuality(float efficiency)
{
efficiency += (GetEffect(Effect.InnerQuiet)?.Strength ?? 0) * 0.10f;
if (HasEffect(Effect.GreatStrides))
{
efficiency += 1.00f;
RemoveEffect(Effect.GreatStrides);
}
if (HasEffect(Effect.Innovation))
efficiency += 0.50f;
var conditionModifier = Condition switch
{
Condition.Poor => 0.50f,
Condition.Good => 1.50f, // 1.75f if relic tool
Condition.Excellent => 4.00f,
_ => 1.00f,
};
var baseIncrease = Stats.Craftsmanship * 10 / RecipeTable.ProgressDivider + 2;
if (Stats.CLvl <= RLvl)
baseIncrease *= RecipeTable.ProgressModifier / 100;
Quality += (int)(baseIncrease * efficiency * conditionModifier);
if (Stats.Level >= 11)
StrengthenEffect(Effect.InnerQuiet);
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"version": 1,
"dependencies": {
"net7.0-windows7.0": {
"DalamudPackager": {
"type": "Direct",
"requested": "[2.1.10, )",
"resolved": "2.1.10",
"contentHash": "S6NrvvOnLgT4GDdgwuKVJjbFo+8ZEj+JsEYk9ojjOR/MMfv1dIFpT8aRJQfI24rtDcw1uF+GnSSMN4WW1yt7fw=="
}
}
}
}