biiiig changes
This commit is contained in:
@@ -11,4 +11,5 @@ public static class LuminaSheets
|
||||
public static readonly ExcelSheet<Action> ActionSheet = Service.DataManager.GetExcelSheet<Action>()!;
|
||||
public static readonly ExcelSheet<CraftAction> CraftActionSheet = Service.DataManager.GetExcelSheet<CraftAction>()!;
|
||||
public static readonly ExcelSheet<Status> StatusSheet = Service.DataManager.GetExcelSheet<Status>()!;
|
||||
public static readonly ExcelSheet<Addon> AddonSheet = Service.DataManager.GetExcelSheet<Addon>()!;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ using Craftimizer.Simulator;
|
||||
using Craftimizer.Simulator.Actions;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using System;
|
||||
using System.Linq;
|
||||
@@ -14,6 +16,8 @@ public class SimulatorWindow : Window
|
||||
public Simulation Simulation { get; }
|
||||
public BaseAction[] AvailableActions { get; }
|
||||
|
||||
private bool showOnlyGuaranteedActions = true;
|
||||
|
||||
public SimulatorWindow() : base("Craftimizer")
|
||||
{
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
@@ -22,7 +26,7 @@ public class SimulatorWindow : Window
|
||||
MaximumSize = new Vector2(float.MaxValue, float.MaxValue)
|
||||
};
|
||||
|
||||
Simulation = new(new CharacterStats { Craftsmanship = 4041, Control = 3905, CP = 609, Level = 90 }, LuminaSheets.RecipeSheet.GetRow(35573)!);
|
||||
Simulation = new(new CharacterStats { Craftsmanship = 4041, Control = 3905, CP = 609, Level = 90 }, LuminaSheets.RecipeSheet.GetRow(35499)!);
|
||||
AvailableActions = BaseAction.Actions.Select(a => (Activator.CreateInstance(a, Simulation)! as BaseAction)!).ToArray();
|
||||
}
|
||||
|
||||
@@ -32,18 +36,22 @@ public class SimulatorWindow : Window
|
||||
ImGui.TableSetupColumn("CraftimizerActionsColumn", ImGuiTableColumnFlags.WidthFixed, 300);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.BeginChild("CraftimizerActions", Vector2.Zero, true, ImGuiWindowFlags.NoDecoration);
|
||||
ImGui.Checkbox("Show only guaranteed actions", ref showOnlyGuaranteedActions);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
foreach(var category in AvailableActions.GroupBy(a=>a.Category))
|
||||
foreach(var category in AvailableActions.GroupBy(a => a.Category))
|
||||
{
|
||||
var i = 0;
|
||||
ImGuiUtils.BeginGroupPanel(category.Key.ToString());
|
||||
foreach (var action in category)
|
||||
ImGuiUtils.BeginGroupPanel(category.Key.GetDisplayName());
|
||||
foreach (var action in category.OrderBy(a => a.Level))
|
||||
{
|
||||
if (showOnlyGuaranteedActions && !action.IsGuaranteedAction)
|
||||
continue;
|
||||
|
||||
ImGui.BeginDisabled(!action.CanUse);
|
||||
if (ImGui.ImageButton(action.GetIcon(ClassJob.Carpenter).ImGuiHandle, new Vector2(ImGui.GetFontSize() * 2)))
|
||||
Simulation.Execute(action);
|
||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||
ImGui.SetTooltip(action.Tooltip);
|
||||
ImGui.SetTooltip(action.GetTooltip(true));
|
||||
ImGui.EndDisabled();
|
||||
if (++i % 5 != 0)
|
||||
ImGui.SameLine();
|
||||
@@ -55,6 +63,9 @@ public class SimulatorWindow : Window
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.BeginChild("CraftimizerSimulator", Vector2.Zero, true, ImGuiWindowFlags.NoDecoration);
|
||||
ImGui.Text($"Step {Simulation.StepCount + 1}");
|
||||
ImGui.Text(Simulation.Condition.Name());
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(Simulation.Condition.Description(Simulation.Stats.HasRelic));
|
||||
ImGui.Text($"{Simulation.HQPercent}%% HQ");
|
||||
ImGui.PushStyleColor(ImGuiCol.PlotHistogram, new Vector4(.2f, 1f, .2f, 1f));
|
||||
ImGui.ProgressBar(Math.Min((float)Simulation.Progress / Simulation.MaxProgress, 1f), new Vector2(200, 20), $"{Simulation.Progress} / {Simulation.MaxProgress}");
|
||||
@@ -70,20 +81,14 @@ public class SimulatorWindow : Window
|
||||
ImGui.PopStyleColor();
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
ImGui.Text($"Effects:");
|
||||
foreach (var (effect, strength, stepsLeft) in Simulation.ActiveEffects)
|
||||
foreach (var effect in Simulation.ActiveEffects)
|
||||
{
|
||||
var status = effect.Status();
|
||||
var icon = Icons.GetIconFromId((ushort)status.Icon);
|
||||
var icon = effect.Icon;
|
||||
var h = ImGui.GetFontSize() * 1.25f;
|
||||
var w = icon.Width * h / icon.Height;
|
||||
ImGui.Image(icon.ImGuiHandle, new Vector2(w, h));
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(status.Name.ToString());
|
||||
ImGui.SameLine();
|
||||
if (stepsLeft < 0)
|
||||
ImGui.Text($"{strength}");
|
||||
else
|
||||
ImGui.Text($"> {stepsLeft}");
|
||||
ImGui.Text(effect.Tooltip);
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
{
|
||||
@@ -92,7 +97,7 @@ public class SimulatorWindow : Window
|
||||
{
|
||||
ImGui.Image(action.GetIcon(ClassJob.Carpenter).ImGuiHandle, new Vector2(ImGui.GetFontSize() * 2f));
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(action.GetName(ClassJob.Carpenter));
|
||||
ImGui.SetTooltip(action.GetTooltip(false));
|
||||
if (++i % 5 != 0)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
@@ -9,3 +9,18 @@ public enum ActionCategory
|
||||
Buffs,
|
||||
Other
|
||||
}
|
||||
|
||||
internal static class ActionCategoryUtils
|
||||
{
|
||||
public static string GetDisplayName(this ActionCategory category) =>
|
||||
category switch
|
||||
{
|
||||
ActionCategory.FirstTurn => "First Turn",
|
||||
ActionCategory.Synthesis => "Synthesis",
|
||||
ActionCategory.Quality => "Quality",
|
||||
ActionCategory.Durability => "Durability",
|
||||
ActionCategory.Buffs => "Buffs",
|
||||
ActionCategory.Other => "Other",
|
||||
_ => category.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ internal class AdvancedTouch : BaseAction
|
||||
public override int Level => 84;
|
||||
public override int ActionId => 100411;
|
||||
|
||||
public override int CPCost => Simulation.GetPreviousAction() is StandardTouch && Simulation.GetPreviousAction(2) is BasicTouch ? 18 : 46;
|
||||
public override int CPCost => Simulation.IsPreviousAction<StandardTouch>() && Simulation.IsPreviousAction<BasicTouch>(2) ? 18 : 46;
|
||||
public override float Efficiency => 1.50f;
|
||||
public override bool IncreasesQuality => true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Craftimizer.Plugin;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiScene;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System;
|
||||
@@ -32,6 +33,7 @@ public abstract class BaseAction
|
||||
public virtual float SuccessRate => 1f;
|
||||
public virtual int DurabilityCost => 10;
|
||||
public virtual bool IncreasesStepCount => true;
|
||||
public virtual bool IsGuaranteedAction => SuccessRate == 1f;
|
||||
|
||||
private (CraftAction? CraftAction, Action? Action) GetActionRow(ClassJob classJob)
|
||||
{
|
||||
@@ -67,9 +69,9 @@ public abstract class BaseAction
|
||||
{
|
||||
var (craftAction, action) = GetActionRow(classJob);
|
||||
if (craftAction != null)
|
||||
return craftAction.Name;
|
||||
return craftAction.Name.ToDalamudString().TextValue;
|
||||
else if (action != null)
|
||||
return action.Name;
|
||||
return action.Name.ToDalamudString().TextValue;
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ public abstract class BaseAction
|
||||
Simulation.ReduceCP(CPCost);
|
||||
Simulation.ReduceDurability(DurabilityCost);
|
||||
|
||||
if (Simulation.HasEffect(Effect.Manipulation))
|
||||
if (Simulation.HasEffect(EffectType.Manipulation))
|
||||
Simulation.RestoreDurability(5);
|
||||
|
||||
if (Simulation.RollSuccess(SuccessRate))
|
||||
@@ -113,18 +115,17 @@ public abstract class BaseAction
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string Tooltip
|
||||
{
|
||||
get
|
||||
public virtual string GetTooltip(bool addUsability)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine(GetName(ClassJob.Carpenter));
|
||||
if (!CanUse)
|
||||
if (addUsability && !CanUse)
|
||||
builder.AppendLine($"Cannot Use");
|
||||
builder.AppendLine($"Level {Level}");
|
||||
builder.AppendLine($"CP Cost: {CPCost}");
|
||||
if (CPCost != 0)
|
||||
builder.AppendLine($"-{Simulation.CalculateCPCost(CPCost)} CP");
|
||||
if (DurabilityCost != 0)
|
||||
builder.AppendLine($"Durability Cost: {DurabilityCost}");
|
||||
builder.AppendLine($"-{Simulation.CalculateDurabilityCost(DurabilityCost)} Durability");
|
||||
if (Efficiency != 0)
|
||||
{
|
||||
if (IncreasesProgress)
|
||||
@@ -135,8 +136,7 @@ public abstract class BaseAction
|
||||
if (!IncreasesStepCount)
|
||||
builder.AppendLine($"Does Not Increase Step Count");
|
||||
if (SuccessRate != 1f)
|
||||
builder.AppendLine($"{SuccessRate * 100}%% Success Rate");
|
||||
builder.AppendLine($"{Simulation.CalculateSuccessRate(SuccessRate) * 100}%% Success Rate");
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@ public abstract class BaseBuffAction : BaseAction
|
||||
public BaseBuffAction(Simulation simulation) : base(simulation) { }
|
||||
|
||||
public abstract Effect Effect { get; }
|
||||
public abstract int EffectDuration { get; }
|
||||
public virtual Effect[] ConflictingEffects => Array.Empty<Effect>();
|
||||
public virtual EffectType[] ConflictingEffects => Array.Empty<EffectType>();
|
||||
|
||||
public override int DurabilityCost => 0;
|
||||
|
||||
@@ -18,18 +17,13 @@ public abstract class BaseBuffAction : BaseAction
|
||||
if (ConflictingEffects.Length != 0)
|
||||
foreach(var effect in ConflictingEffects)
|
||||
Simulation.RemoveEffect(effect);
|
||||
Simulation.AddEffect(Effect, EffectDuration);
|
||||
Simulation.AddEffect(Effect.Type, Effect.Duration, Effect.Strength);
|
||||
}
|
||||
|
||||
public override string Tooltip {
|
||||
get
|
||||
public override string GetTooltip(bool addUsability)
|
||||
{
|
||||
var builder = new StringBuilder(base.Tooltip);
|
||||
builder.AppendLine($"Effect: {Effect.Status().Name}");
|
||||
builder.AppendLine($"Duration: {EffectDuration} steps");
|
||||
foreach(var effect in ConflictingEffects)
|
||||
builder.AppendLine($"Conflicts with: {effect.Status().Name}");
|
||||
var builder = new StringBuilder(base.GetTooltip(addUsability));
|
||||
builder.AppendLine($"Effect: {Effect.Tooltip}");
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ internal class ByregotsBlessing : BaseAction
|
||||
public override int ActionId => 100339;
|
||||
|
||||
public override int CPCost => 24;
|
||||
public override float Efficiency => 1.00f + (0.20f * (Simulation.GetEffect(Effect.InnerQuiet)?.Strength ?? 0));
|
||||
public override float Efficiency => 1.00f + (0.20f * (Simulation.GetEffect(EffectType.InnerQuiet)?.Strength ?? 0));
|
||||
public override bool IncreasesQuality => true;
|
||||
|
||||
public override bool CanUse => Simulation.HasEffect(Effect.InnerQuiet) && base.CanUse;
|
||||
public override bool CanUse => Simulation.HasEffect(EffectType.InnerQuiet) && base.CanUse;
|
||||
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
Simulation.RemoveEffect(Effect.InnerQuiet);
|
||||
Simulation.RemoveEffect(EffectType.InnerQuiet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Craftimizer.Simulator.Actions;
|
||||
|
||||
internal class CarefulObservation : BaseAction
|
||||
{
|
||||
public CarefulObservation(Simulation simulation) : base(simulation) { }
|
||||
|
||||
public override ActionCategory Category => ActionCategory.Other;
|
||||
public override int Level => 55;
|
||||
public override int ActionId => 100395;
|
||||
|
||||
public override int CPCost => 0;
|
||||
public override int DurabilityCost => 0;
|
||||
public override bool IncreasesStepCount => false;
|
||||
|
||||
public override bool CanUse => Simulation.Stats.IsSpecialist && Simulation.CountPreviousAction<CarefulObservation>() < 3;
|
||||
|
||||
public override void UseSuccess() =>
|
||||
Simulation.StepCondition();
|
||||
}
|
||||
@@ -11,6 +11,5 @@ internal class FinalAppraisal : BaseBuffAction
|
||||
public override int CPCost => 1;
|
||||
public override bool IncreasesStepCount => false;
|
||||
|
||||
public override Effect Effect => Effect.FinalAppraisal;
|
||||
public override int EffectDuration => 5;
|
||||
public override Effect Effect => new() { Type = EffectType.FinalAppraisal, Duration = 5 };
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ internal class FocusedSynthesis : BaseAction
|
||||
public override int CPCost => 5;
|
||||
public override float Efficiency => 2.00f;
|
||||
public override bool IncreasesProgress => true;
|
||||
public override float SuccessRate => Simulation.GetPreviousAction() is Observe ? 1.00f : 0.50f;
|
||||
public override float SuccessRate => Simulation.IsPreviousAction<Observe>() ? 1.00f : 0.50f;
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ internal class FocusedTouch : BaseAction
|
||||
public override int CPCost => 18;
|
||||
public override float Efficiency => 1.50f;
|
||||
public override bool IncreasesQuality => true;
|
||||
public override float SuccessRate => Simulation.GetPreviousAction() is Observe ? 1.00f : 0.50f;
|
||||
public override float SuccessRate => Simulation.IsPreviousAction<Observe>() ? 1.00f : 0.50f;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,5 @@ internal class GreatStrides : BaseBuffAction
|
||||
|
||||
public override int CPCost => 32;
|
||||
|
||||
public override Effect Effect => Effect.GreatStrides;
|
||||
public override int EffectDuration => 3;
|
||||
public override Effect Effect => new() { Type = EffectType.GreatStrides, Duration = 3 };
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ internal class Groundwork : BaseAction
|
||||
get
|
||||
{
|
||||
var ret = Simulation.Stats.Level >= 86 ? 3.60f : 3.00f;
|
||||
// TODO: does not account for waste not
|
||||
return Simulation.Durability < DurabilityCost ? ret / 2 : ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Craftimizer.Simulator.Actions;
|
||||
|
||||
internal class HeartAndSoul : BaseBuffAction
|
||||
{
|
||||
public HeartAndSoul(Simulation simulation) : base(simulation) { }
|
||||
|
||||
public override ActionCategory Category => ActionCategory.Other;
|
||||
public override int Level => 86;
|
||||
public override int ActionId => 100419;
|
||||
|
||||
public override int CPCost => 0;
|
||||
public override bool IncreasesStepCount => false;
|
||||
|
||||
public override Effect Effect => new() { Type = EffectType.HeartAndSoul };
|
||||
|
||||
public override bool CanUse => Simulation.Stats.IsSpecialist && Simulation.CountPreviousAction<HeartAndSoul>() == 0;
|
||||
}
|
||||
@@ -10,6 +10,5 @@ internal class Innovation : BaseBuffAction
|
||||
|
||||
public override int CPCost => 18;
|
||||
|
||||
public override Effect Effect => Effect.Innovation;
|
||||
public override int EffectDuration => 4;
|
||||
public override Effect Effect => new() { Type = EffectType.Innovation, Duration = 4 };
|
||||
}
|
||||
|
||||
@@ -11,8 +11,16 @@ internal class IntensiveSynthesis : BaseAction
|
||||
public override int CPCost => 6;
|
||||
public override float Efficiency => 4.00f;
|
||||
public override bool IncreasesProgress => true;
|
||||
public override bool IsGuaranteedAction => false;
|
||||
|
||||
public override bool CanUse =>
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent || Simulation.HasEffect(EffectType.HeartAndSoul))
|
||||
&& base.CanUse;
|
||||
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
if (Simulation.Condition != Condition.Good && Simulation.Condition != Condition.Excellent)
|
||||
Simulation.RemoveEffect(EffectType.HeartAndSoul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,5 @@ internal class Manipulation : BaseBuffAction
|
||||
|
||||
public override int CPCost => 96;
|
||||
|
||||
public override Effect Effect => Effect.Manipulation;
|
||||
public override int EffectDuration => 8;
|
||||
public override Effect Effect => new() { Type = EffectType.Manipulation, Duration = 8 };
|
||||
}
|
||||
|
||||
@@ -17,6 +17,6 @@ internal class MuscleMemory : BaseAction
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
Simulation.AddEffect(Effect.MuscleMemory, 5);
|
||||
Simulation.AddEffect(EffectType.MuscleMemory, 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,17 @@ internal class PreciseTouch : BaseAction
|
||||
public override int CPCost => 18;
|
||||
public override float Efficiency => 1.50f;
|
||||
public override bool IncreasesQuality => true;
|
||||
public override bool IsGuaranteedAction => false;
|
||||
|
||||
public override bool CanUse =>
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent || Simulation.HasEffect(EffectType.HeartAndSoul))
|
||||
&& base.CanUse;
|
||||
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
Simulation.StrengthenEffect(Effect.InnerQuiet);
|
||||
Simulation.StrengthenEffect(EffectType.InnerQuiet);
|
||||
if (Simulation.Condition != Condition.Good && Simulation.Condition != Condition.Excellent)
|
||||
Simulation.RemoveEffect(EffectType.HeartAndSoul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ internal class PreparatoryTouch : BaseAction
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
Simulation.StrengthenEffect(Effect.InnerQuiet);
|
||||
Simulation.StrengthenEffect(EffectType.InnerQuiet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ internal class PrudentSynthesis : BaseAction
|
||||
public override int DurabilityCost => base.DurabilityCost / 2;
|
||||
|
||||
public override bool CanUse =>
|
||||
!(Simulation.HasEffect(Effect.WasteNot) || Simulation.HasEffect(Effect.WasteNot2))
|
||||
!(Simulation.HasEffect(EffectType.WasteNot) || Simulation.HasEffect(EffectType.WasteNot2))
|
||||
&& base.CanUse;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ internal class PrudentTouch : BaseAction
|
||||
public override int DurabilityCost => base.DurabilityCost / 2;
|
||||
|
||||
public override bool CanUse =>
|
||||
!(Simulation.HasEffect(Effect.WasteNot) || Simulation.HasEffect(Effect.WasteNot2))
|
||||
!(Simulation.HasEffect(EffectType.WasteNot) || Simulation.HasEffect(EffectType.WasteNot2))
|
||||
&& base.CanUse;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,6 @@ internal class Reflect : BaseAction
|
||||
public override void UseSuccess()
|
||||
{
|
||||
base.UseSuccess();
|
||||
Simulation.StrengthenEffect(Effect.InnerQuiet);
|
||||
Simulation.StrengthenEffect(EffectType.InnerQuiet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ internal class StandardTouch : BaseAction
|
||||
public override int Level => 18;
|
||||
public override int ActionId => 100004;
|
||||
|
||||
public override int CPCost => Simulation.GetPreviousAction() is BasicTouch ? 18 : 32;
|
||||
public override int CPCost => Simulation.IsPreviousAction<BasicTouch>() ? 18 : 32;
|
||||
public override float Efficiency => 1.25f;
|
||||
public override bool IncreasesQuality => true;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ internal class TrainedFinesse : BaseAction
|
||||
public override int DurabilityCost => 0;
|
||||
|
||||
public override bool CanUse =>
|
||||
(Simulation.GetEffect(Effect.InnerQuiet)?.Strength ?? 0) == 10
|
||||
(Simulation.GetEffect(EffectType.InnerQuiet)?.Strength ?? 0) == 10
|
||||
&& base.CanUse;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,16 @@ internal class TricksOfTheTrade : BaseAction
|
||||
|
||||
public override int CPCost => 0;
|
||||
public override int DurabilityCost => 0;
|
||||
public override bool IsGuaranteedAction => false;
|
||||
|
||||
public override bool CanUse =>
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent)
|
||||
(Simulation.Condition == Condition.Good || Simulation.Condition == Condition.Excellent || Simulation.HasEffect(EffectType.HeartAndSoul))
|
||||
&& base.CanUse;
|
||||
|
||||
public override void UseSuccess() =>
|
||||
public override void UseSuccess()
|
||||
{
|
||||
Simulation.RestoreCP(20);
|
||||
if (Simulation.Condition != Condition.Good && Simulation.Condition != Condition.Excellent)
|
||||
Simulation.RemoveEffect(EffectType.HeartAndSoul);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,5 @@ internal class Veneration : BaseBuffAction
|
||||
public override int CPCost => 18;
|
||||
public override int DurabilityCost => 0;
|
||||
|
||||
public override Effect Effect => Effect.Veneration;
|
||||
public override int EffectDuration => 4;
|
||||
public override Effect Effect => new() { Type = EffectType.Veneration, Duration = 4 };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ internal class WasteNot : BaseBuffAction
|
||||
|
||||
public override int CPCost => 56;
|
||||
|
||||
public override Effect Effect => Effect.WasteNot;
|
||||
public override int EffectDuration => 4;
|
||||
public override Effect[] ConflictingEffects => new[] { Effect.WasteNot2 };
|
||||
public override Effect Effect => new() { Type = EffectType.WasteNot, Duration = 4 };
|
||||
public override EffectType[] ConflictingEffects => new[] { EffectType.WasteNot2 };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ internal class WasteNot2 : BaseBuffAction
|
||||
|
||||
public override int CPCost => 98;
|
||||
|
||||
public override Effect Effect => Effect.WasteNot2;
|
||||
public override int EffectDuration => 8;
|
||||
public override Effect[] ConflictingEffects => new[] { Effect.WasteNot };
|
||||
public override Effect Effect => new() { Type = EffectType.WasteNot2, Duration = 8 };
|
||||
public override EffectType[] ConflictingEffects => new[] { EffectType.WasteNot };
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ public record CharacterStats
|
||||
public int Control { get; init; }
|
||||
public int CP { get; init; }
|
||||
public int Level { get; init; }
|
||||
public bool HasRelic { get; init; }
|
||||
public bool IsSpecialist { get; init; }
|
||||
|
||||
public int CLvl => Level <= 80
|
||||
? LuminaSheets.ParamGrowSheet.GetRow((uint)Level)!.CraftingLevel
|
||||
|
||||
@@ -1,15 +1,60 @@
|
||||
using Craftimizer.Plugin;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Craftimizer.Simulator;
|
||||
|
||||
public enum Condition
|
||||
public enum Condition : ushort
|
||||
{
|
||||
Poor,
|
||||
Normal,
|
||||
Good,
|
||||
Excellent,
|
||||
Poor = 0x0008,
|
||||
Normal = 0x0001,
|
||||
Good = 0x0002,
|
||||
Excellent = 0x0004,
|
||||
|
||||
Centered = 0x0010,
|
||||
Sturdy = 0x0020,
|
||||
Pliant = 0x0040,
|
||||
Malleable = 0x0080,
|
||||
Primed = 0x0100,
|
||||
GoodOmen = 0x0200,
|
||||
}
|
||||
|
||||
internal static class ConditionUtils
|
||||
{
|
||||
public static Condition[] GetPossibleConditions(ushort conditionsFlag) =>
|
||||
Enum.GetValues<Condition>().Where(c => ((Condition)conditionsFlag).HasFlag(c)).ToArray();
|
||||
|
||||
public static (uint Name, uint Description) AddonIds(this Condition me) =>
|
||||
me switch
|
||||
{
|
||||
Condition.Poor => (229, 14203),
|
||||
Condition.Normal => (226, 14200),
|
||||
Condition.Good => (227, 14201),
|
||||
Condition.Excellent => (228, 14202),
|
||||
Condition.Centered => (239, 14204),
|
||||
Condition.Sturdy => (240, 14205),
|
||||
Condition.Pliant => (241, 14206),
|
||||
Condition.Malleable => (13455, 14208),
|
||||
Condition.Primed => (13454, 14207),
|
||||
Condition.GoodOmen => (14214, 14215),
|
||||
_ => (226, 14200) // Unknown
|
||||
};
|
||||
|
||||
public static string Name(this Condition me) =>
|
||||
LuminaSheets.AddonSheet.GetRow(me.AddonIds().Name)!.Text.ToDalamudString().TextValue;
|
||||
|
||||
public static string Description(this Condition me, bool isRelic)
|
||||
{
|
||||
var text = LuminaSheets.AddonSheet.GetRow(me.AddonIds().Description)!.Text.ToDalamudString();
|
||||
for (var i = 0; i < text.Payloads.Count; ++i)
|
||||
if (text.Payloads[i] is RawPayload)
|
||||
text.Payloads[i] = new TextPayload(isRelic ? "1.75" : "1.5");
|
||||
return text.TextValue;
|
||||
}
|
||||
|
||||
//Centered,
|
||||
//Sturdy,
|
||||
//Pliant,
|
||||
//Malleable,
|
||||
//Primed
|
||||
}
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
using Craftimizer.Plugin;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiScene;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Craftimizer.Simulator;
|
||||
|
||||
public enum Effect
|
||||
public record Effect
|
||||
{
|
||||
InnerQuiet,
|
||||
WasteNot,
|
||||
Veneration,
|
||||
GreatStrides,
|
||||
Innovation,
|
||||
FinalAppraisal,
|
||||
WasteNot2,
|
||||
MuscleMemory,
|
||||
Manipulation,
|
||||
}
|
||||
public EffectType Type { get; init; }
|
||||
public int? Duration { get; set; }
|
||||
public int? Strength { get; set; }
|
||||
|
||||
internal static class EffectExtensions
|
||||
{
|
||||
public static uint StatusId(this Effect me) =>
|
||||
me switch
|
||||
public ushort IconId { get
|
||||
{
|
||||
Effect.InnerQuiet => 251,
|
||||
Effect.WasteNot => 252,
|
||||
Effect.Veneration => 2226,
|
||||
Effect.GreatStrides => 254,
|
||||
Effect.Innovation => 2189,
|
||||
Effect.FinalAppraisal => 2190,
|
||||
Effect.WasteNot2 => 257,
|
||||
Effect.MuscleMemory => 2191,
|
||||
Effect.Manipulation => 258,
|
||||
_ => 3412,
|
||||
};
|
||||
var status = Type.Status();
|
||||
var iconId = status.Icon;
|
||||
if (status.MaxStacks != 0 && Strength != null)
|
||||
iconId += (uint)Math.Clamp(Strength.Value, 1, status.MaxStacks) - 1;
|
||||
return (ushort)iconId;
|
||||
}
|
||||
}
|
||||
|
||||
public static Status Status(this Effect me) =>
|
||||
LuminaSheets.StatusSheet.GetRow(me.StatusId())!;
|
||||
public TextureWrap Icon => Icons.GetIconFromId(IconId);
|
||||
|
||||
public string Tooltip { get
|
||||
{
|
||||
var status = Type.Status();
|
||||
var name = new StringBuilder();
|
||||
name.Append(status.Name.ToDalamudString().TextValue);
|
||||
if (status.MaxStacks != 0 && Strength != null)
|
||||
name.Append($" {Strength}");
|
||||
if (!status.IsPermanent && Duration != null)
|
||||
name.Append($" > {Duration}");
|
||||
return name.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using Craftimizer.Plugin;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace Craftimizer.Simulator;
|
||||
|
||||
public enum EffectType
|
||||
{
|
||||
InnerQuiet,
|
||||
WasteNot,
|
||||
Veneration,
|
||||
GreatStrides,
|
||||
Innovation,
|
||||
FinalAppraisal,
|
||||
WasteNot2,
|
||||
MuscleMemory,
|
||||
Manipulation,
|
||||
HeartAndSoul,
|
||||
}
|
||||
|
||||
internal static class EffectExtensions
|
||||
{
|
||||
public static uint StatusId(this EffectType me) =>
|
||||
me switch
|
||||
{
|
||||
EffectType.InnerQuiet => 251,
|
||||
EffectType.WasteNot => 252,
|
||||
EffectType.Veneration => 2226,
|
||||
EffectType.GreatStrides => 254,
|
||||
EffectType.Innovation => 2189,
|
||||
EffectType.FinalAppraisal => 2190,
|
||||
EffectType.WasteNot2 => 257,
|
||||
EffectType.MuscleMemory => 2191,
|
||||
EffectType.Manipulation => 258,
|
||||
EffectType.HeartAndSoul => 2665,
|
||||
_ => 3412,
|
||||
};
|
||||
|
||||
public static Status Status(this EffectType me) =>
|
||||
LuminaSheets.StatusSheet.GetRow(me.StatusId())!;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Dalamud.Logging;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Craftimizer.Simulator;
|
||||
|
||||
@@ -12,6 +13,7 @@ public class Simulation
|
||||
public Recipe Recipe { get; }
|
||||
public RecipeLevelTable RecipeTable => Recipe.RecipeLevelTable.Value!;
|
||||
public int RLvl => (int)RecipeTable.RowId;
|
||||
public readonly Condition[] AvailableConditions;
|
||||
|
||||
public int MaxDurability => RecipeTable.Durability * Recipe.DurabilityFactor / 100;
|
||||
public int MaxQuality => (int)RecipeTable.Quality * Recipe.QualityFactor / 100;
|
||||
@@ -24,7 +26,7 @@ public class Simulation
|
||||
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<Effect> ActiveEffects { get; } = new();
|
||||
public List<BaseAction> ActionHistory { get; } = new();
|
||||
|
||||
// https://github.com/ffxiv-teamcraft/simulator/blob/0682dfa76043ff4ccb38832c184d046ceaff0733/src/model/tables.ts#L2
|
||||
@@ -51,6 +53,7 @@ public class Simulation
|
||||
Durability = MaxDurability;
|
||||
CP = Stats.CP;
|
||||
Condition = Condition.Normal;
|
||||
AvailableConditions = ConditionUtils.GetPossibleConditions(RecipeTable.ConditionsFlag);
|
||||
}
|
||||
|
||||
public ActionResponse Execute(BaseAction action)
|
||||
@@ -72,14 +75,13 @@ public class Simulation
|
||||
|
||||
for (var i = 0; i < ActiveEffects.Count; ++i)
|
||||
{
|
||||
var (effect, strength, stepsLeft) = ActiveEffects[i];
|
||||
if (stepsLeft == 1)
|
||||
var effect = ActiveEffects[i];
|
||||
effect.Duration--;
|
||||
if (effect.Duration == 0)
|
||||
{
|
||||
ActiveEffects.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
else
|
||||
ActiveEffects[i] = (effect, strength, stepsLeft - 1);
|
||||
}
|
||||
|
||||
if (Progress >= MaxProgress)
|
||||
@@ -99,59 +101,91 @@ public class Simulation
|
||||
public ActionResponse Execute<T>() where T : BaseAction =>
|
||||
Execute((T)Activator.CreateInstance(typeof(T), this)!);
|
||||
|
||||
public (int Strength, int Duration)? GetEffect(Effect effect)
|
||||
public Effect? GetEffect(EffectType effect) =>
|
||||
ActiveEffects.FirstOrDefault(e => e.Type == effect);
|
||||
|
||||
public void AddEffect(EffectType effect, int? duration = null, int? strength = null)
|
||||
{
|
||||
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
|
||||
if (idx == -1)
|
||||
return null;
|
||||
var (_, strength, duration) = ActiveEffects[idx];
|
||||
return (strength, duration);
|
||||
if (Condition == Condition.Primed && duration != null)
|
||||
duration += 2;
|
||||
|
||||
// Duration will be decreased in the next step, so we need to add 1
|
||||
if (duration != null)
|
||||
duration++;
|
||||
|
||||
var currentEffect = GetEffect(effect);
|
||||
if (currentEffect != null) {
|
||||
currentEffect.Duration = duration;
|
||||
currentEffect.Strength = strength;
|
||||
}
|
||||
else
|
||||
ActiveEffects.Add(new Effect { Type = effect, Duration = duration, Strength = strength });
|
||||
}
|
||||
|
||||
public void AddEffect(Effect effect, int duration, int strength = 1)
|
||||
public void StrengthenEffect(EffectType effect, int? duration = null)
|
||||
{
|
||||
// Duration will be decreased in the next step, so we need to add 1
|
||||
if (duration != null)
|
||||
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 currentEffect = GetEffect(effect);
|
||||
if (currentEffect != null)
|
||||
{
|
||||
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
|
||||
if (idx == -1)
|
||||
ActiveEffects.Add((effect, 1, duration));
|
||||
if (effect.Status().MaxStacks > currentEffect.Strength)
|
||||
currentEffect.Strength++;
|
||||
}
|
||||
else
|
||||
ActiveEffects[idx] = (effect, ActiveEffects[idx].strength + 1, duration);
|
||||
AddEffect(effect, duration, 1);
|
||||
}
|
||||
|
||||
public void RemoveEffect(Effect effect)
|
||||
{
|
||||
var idx = ActiveEffects.FindIndex(x => x.effect == effect);
|
||||
if (idx != -1)
|
||||
ActiveEffects.RemoveAt(idx);
|
||||
}
|
||||
public void RemoveEffect(EffectType effect) =>
|
||||
ActiveEffects.RemoveAll(e => e.Type == effect);
|
||||
|
||||
public bool HasEffect(Effect effect) => GetEffect(effect) != null;
|
||||
public bool HasEffect(EffectType effect) =>
|
||||
ActiveEffects.Any(e => e.Type == effect);
|
||||
|
||||
public BaseAction? GetPreviousAction(int stepsBack = 1) =>
|
||||
ActionHistory.Count < stepsBack ? null : ActionHistory[^stepsBack];
|
||||
public bool IsPreviousAction<T>(int stepsBack = 1) where T : BaseAction =>
|
||||
ActionHistory.Count >= stepsBack && ActionHistory[^stepsBack] is T;
|
||||
|
||||
public bool RollSuccess(float successRate) =>
|
||||
public int CountPreviousAction<T>() where T : BaseAction =>
|
||||
ActionHistory.Count(x => x is T);
|
||||
|
||||
public bool RollSuccessRaw(float successRate) =>
|
||||
successRate >= Random.NextSingle();
|
||||
|
||||
public void IncreaseStepCount() =>
|
||||
StepCount++;
|
||||
public bool RollSuccess(float successRate) =>
|
||||
RollSuccessRaw(CalculateSuccessRate(successRate));
|
||||
|
||||
public void ReduceDurability(int amount)
|
||||
public void IncreaseStepCount()
|
||||
{
|
||||
if (HasEffect(Effect.WasteNot) || HasEffect(Effect.WasteNot2))
|
||||
amount /= 2;
|
||||
Durability -= amount;
|
||||
StepCount++;
|
||||
StepCondition();
|
||||
}
|
||||
|
||||
private float GetConditionChance(Condition condition) =>
|
||||
condition switch
|
||||
{
|
||||
Condition.Good => Recipe.IsExpert ? 0.12f : (Stats.Level >= 63 ? 0.15f : 0.18f),
|
||||
Condition.Excellent => 0.04f,
|
||||
Condition.Centered => 0.15f,
|
||||
Condition.Sturdy => 0.15f,
|
||||
Condition.Pliant => 0.10f,
|
||||
Condition.Malleable => 0.13f,
|
||||
Condition.Primed => 0.15f,
|
||||
Condition.GoodOmen => 0.12f, // https://github.com/ffxiv-teamcraft/simulator/issues/77
|
||||
_ => 0.00f
|
||||
};
|
||||
|
||||
public void StepCondition()
|
||||
{
|
||||
var conditionChance = Random.NextSingle();
|
||||
|
||||
Condition = Condition switch {
|
||||
Condition.Poor => Condition.Normal,
|
||||
Condition.Good => Condition.Normal,
|
||||
Condition.Excellent => Condition.Poor,
|
||||
Condition.GoodOmen => Condition.Good,
|
||||
_ => AvailableConditions.FirstOrDefault(c => (conditionChance -= GetConditionChance(c)) < 0, Condition.Normal)
|
||||
};
|
||||
}
|
||||
|
||||
public void RestoreDurability(int amount)
|
||||
@@ -162,11 +196,6 @@ public class Simulation
|
||||
Durability = MaxDurability;
|
||||
}
|
||||
|
||||
public void ReduceCP(int amount)
|
||||
{
|
||||
CP -= amount;
|
||||
}
|
||||
|
||||
public void RestoreCP(int amount)
|
||||
{
|
||||
CP += amount;
|
||||
@@ -175,82 +204,104 @@ public class Simulation
|
||||
CP = Stats.CP;
|
||||
}
|
||||
|
||||
public int CalculateProgressGain(float efficiency)
|
||||
public float CalculateSuccessRate(float successRate)
|
||||
{
|
||||
if (Condition == Condition.Centered)
|
||||
successRate += 0.25f;
|
||||
return Math.Clamp(successRate, 0, 1);
|
||||
}
|
||||
|
||||
public int CalculateDurabilityCost(int amount)
|
||||
{
|
||||
var amt = (double)amount;
|
||||
if (HasEffect(EffectType.WasteNot) || HasEffect(EffectType.WasteNot2))
|
||||
amt /= 2;
|
||||
if (Condition == Condition.Sturdy)
|
||||
amt /= 2;
|
||||
return (int)Math.Ceiling(amt);
|
||||
}
|
||||
|
||||
public int CalculateCPCost(int amount)
|
||||
{
|
||||
var amt = (double)amount;
|
||||
if (Condition == Condition.Pliant)
|
||||
amt /= 2;
|
||||
return (int)Math.Ceiling(amt);
|
||||
}
|
||||
|
||||
public int CalculateProgressGain(float efficiency, bool dryRun = true)
|
||||
{
|
||||
var buffModifier = 1.00f;
|
||||
if (HasEffect(Effect.MuscleMemory))
|
||||
if (HasEffect(EffectType.MuscleMemory))
|
||||
{
|
||||
buffModifier += 1.00f;
|
||||
RemoveEffect(Effect.MuscleMemory);
|
||||
if (!dryRun)
|
||||
RemoveEffect(EffectType.MuscleMemory);
|
||||
}
|
||||
if (HasEffect(Effect.Veneration))
|
||||
if (HasEffect(EffectType.Veneration))
|
||||
buffModifier += 0.50f;
|
||||
|
||||
// https://github.com/NotRanged/NotRanged.github.io/blob/0f4aee074f969fb05aad34feaba605057c08ffd1/app/js/ffxivcraftmodel.js#L88
|
||||
PluginLog.LogDebug($"Efficiency: {efficiency}");
|
||||
PluginLog.LogDebug($"Buff Modifier: {buffModifier}");
|
||||
var baseIncrease = (Stats.Craftsmanship * 10f / RecipeTable.ProgressDivider) + 2;
|
||||
PluginLog.LogDebug($"Increase: {baseIncrease}");
|
||||
if (Stats.CLvl <= RLvl)
|
||||
var conditionModifier = Condition switch
|
||||
{
|
||||
baseIncrease *= RecipeTable.ProgressModifier / 100f;
|
||||
PluginLog.LogDebug($"Boosted Increase: {baseIncrease}");
|
||||
}
|
||||
baseIncrease = MathF.Floor(baseIncrease);
|
||||
PluginLog.LogDebug($"Adj. Increase: {baseIncrease}");
|
||||
Condition.Malleable => 1.50f,
|
||||
_ => 1.00f
|
||||
};
|
||||
|
||||
var progressGain = (int)(baseIncrease * efficiency * buffModifier);
|
||||
PluginLog.LogDebug($"Progress Gain: {progressGain}");
|
||||
// https://github.com/NotRanged/NotRanged.github.io/blob/0f4aee074f969fb05aad34feaba605057c08ffd1/app/js/ffxivcraftmodel.js#L88
|
||||
var baseIncrease = (Stats.Craftsmanship * 10f / RecipeTable.ProgressDivider) + 2;
|
||||
if (Stats.CLvl <= RLvl)
|
||||
baseIncrease *= RecipeTable.ProgressModifier / 100f;
|
||||
baseIncrease = MathF.Floor(baseIncrease);
|
||||
|
||||
var progressGain = (int)(baseIncrease * efficiency * conditionModifier * buffModifier);
|
||||
return progressGain;
|
||||
}
|
||||
|
||||
public int CalculateQualityGain(float efficiency)
|
||||
public int CalculateQualityGain(float efficiency, bool dryRun = true)
|
||||
{
|
||||
var buffModifier = 1.00f;
|
||||
if (HasEffect(Effect.GreatStrides))
|
||||
if (HasEffect(EffectType.GreatStrides))
|
||||
{
|
||||
buffModifier += 1.00f;
|
||||
RemoveEffect(Effect.GreatStrides);
|
||||
if (!dryRun)
|
||||
RemoveEffect(EffectType.GreatStrides);
|
||||
}
|
||||
if (HasEffect(Effect.Innovation))
|
||||
if (HasEffect(EffectType.Innovation))
|
||||
buffModifier += 0.50f;
|
||||
|
||||
buffModifier *= 1 + ((GetEffect(Effect.InnerQuiet)?.Strength ?? 0) * 0.10f);
|
||||
buffModifier *= 1 + ((GetEffect(EffectType.InnerQuiet)?.Strength ?? 0) * 0.10f);
|
||||
|
||||
var conditionModifier = Condition switch
|
||||
{
|
||||
Condition.Poor => 0.50f,
|
||||
Condition.Good => 1.50f, // 1.75f if relic tool
|
||||
Condition.Good => Stats.HasRelic ? 1.75f : 1.50f,
|
||||
Condition.Excellent => 4.00f,
|
||||
_ => 1.00f,
|
||||
};
|
||||
|
||||
PluginLog.LogDebug($"Efficiency: {efficiency}");
|
||||
PluginLog.LogDebug($"Buff Modifier: {buffModifier}");
|
||||
PluginLog.LogDebug($"Cond Modifier: {conditionModifier}");
|
||||
var baseIncrease = (Stats.Control * 10f / RecipeTable.QualityDivider) + 35;
|
||||
PluginLog.LogDebug($"Increase: {baseIncrease}");
|
||||
if (Stats.CLvl <= RLvl)
|
||||
{
|
||||
baseIncrease *= RecipeTable.QualityModifier / 100f;
|
||||
PluginLog.LogDebug($"Boosted Increase: {baseIncrease}");
|
||||
}
|
||||
baseIncrease = MathF.Floor(baseIncrease);
|
||||
PluginLog.LogDebug($"Adj. Increase: {baseIncrease}");
|
||||
|
||||
var qualityGain = (int)(baseIncrease * efficiency * conditionModifier * buffModifier);
|
||||
PluginLog.LogDebug($"Quality Gain: {qualityGain}");
|
||||
return qualityGain;
|
||||
}
|
||||
|
||||
public void ReduceDurabilityRaw(int amount) =>
|
||||
Durability -= amount;
|
||||
|
||||
public void ReduceCPRaw(int amount) =>
|
||||
CP -= amount;
|
||||
|
||||
public void IncreaseProgressRaw(int progressGain)
|
||||
{
|
||||
Progress += progressGain;
|
||||
|
||||
if (HasEffect(Effect.FinalAppraisal) && Progress >= MaxProgress)
|
||||
if (HasEffect(EffectType.FinalAppraisal) && Progress >= MaxProgress)
|
||||
{
|
||||
Progress = MaxProgress - 1;
|
||||
RemoveEffect(Effect.FinalAppraisal);
|
||||
RemoveEffect(EffectType.FinalAppraisal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,12 +310,18 @@ public class Simulation
|
||||
Quality += qualityGain;
|
||||
|
||||
if (Stats.Level >= 11)
|
||||
StrengthenEffect(Effect.InnerQuiet);
|
||||
StrengthenEffect(EffectType.InnerQuiet);
|
||||
}
|
||||
|
||||
public void ReduceDurability(int amount) =>
|
||||
ReduceDurabilityRaw(CalculateDurabilityCost(amount));
|
||||
|
||||
public void ReduceCP(int amount) =>
|
||||
ReduceCPRaw(CalculateCPCost(amount));
|
||||
|
||||
public void IncreaseProgress(float efficiency) =>
|
||||
IncreaseProgressRaw(CalculateProgressGain(efficiency));
|
||||
IncreaseProgressRaw(CalculateProgressGain(efficiency, false));
|
||||
|
||||
public void IncreaseQuality(float efficiency) =>
|
||||
IncreaseQualityRaw(CalculateQualityGain(efficiency));
|
||||
IncreaseQualityRaw(CalculateQualityGain(efficiency, false));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user