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
+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);
}
}