Skip to content

Commit

Permalink
Added Variance and Quantisation as options. Embedded fastJson. Expand…
Browse files Browse the repository at this point in the history
…ed on quantisation mechanics.
  • Loading branch information
AnnanFay committed Oct 6, 2021
1 parent 152446c commit 533219a
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 116 deletions.
14 changes: 8 additions & 6 deletions CraftingSkill/CraftingConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ namespace CraftingSkill
{
public class CraftingConfig
{
// public int NEXUS_ID = 0;
private ConfigVariable<bool> __QuantisedQuality = new ConfigVariable<bool>("General", "QuantisedQuality", false);
private ConfigVariable<float> __StochasticVariance = new ConfigVariable<float>("General", "StochasticVariance", 0.0f);

// Experience for crafting

private ConfigVariable<float> __ExpScapeTier = new ConfigVariable<float>("ExpGain", "ExpScapeTier", 1.0f);
private ConfigVariable<float> __ExpScapePower = new ConfigVariable<float>("ExpGain", "ExpScapePower", 2.0f);
private ConfigVariable<float> __ExpScapeLinear = new ConfigVariable<float>("ExpGain", "ExpScapeLinear", 0.16f);
Expand Down Expand Up @@ -52,6 +52,8 @@ public class CraftingConfig
private ConfigVariable<int> __TierModifierDefault = new ConfigVariable<int>("StationBalancing", "TierModifierDefault", 0);

// Utility getters
public bool QuantisedQuality {get => __QuantisedQuality.Value; }
public float StochasticVariance {get => __StochasticVariance.Value; }
public float ExpScapeTier {get => __ExpScapeTier.Value; }
public float ExpScapePower {get => __ExpScapePower.Value; }
public float ExpScapeLinear {get => __ExpScapeLinear.Value; }
Expand All @@ -70,8 +72,8 @@ public class CraftingConfig
public int TierModifierInventory {get => __TierModifierInventory.Value; }
public int TierModifierWorkbench {get => __TierModifierWorkbench.Value; }
public int TierModifierForge {get => __TierModifierForge.Value; }
public int TierModifierCauldron { get => __TierModifierCauldron.Value; }
public int TierModifierOven { get => __TierModifierOven.Value; }
public int TierModifierCauldron {get => __TierModifierCauldron.Value; }
public int TierModifierOven {get => __TierModifierOven.Value; }
public int TierModifierStonecutter {get => __TierModifierStonecutter.Value; }
public int TierModifierArtisan {get => __TierModifierArtisan.Value; }
public int TierModifierDefault {get => __TierModifierDefault.Value; }
Expand All @@ -83,8 +85,6 @@ public CraftingConfig()

public void InitConfig(string mod_id, ConfigFile config)
{
// Bind<int>("General", "NexusID", NEXUS_ID, "Nexus mod ID for updates");

Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == "ModConfigEnforcer");
if (assembly != null)
{
Expand All @@ -109,6 +109,8 @@ public void InitConfig(string mod_id, ConfigFile config)
Debug.Log("Mod Config Enforcer not detected.");
}

__QuantisedQuality.init(assembly, config, mod_id);
__StochasticVariance.init(assembly, config, mod_id);
__ExpScapeTier.init(assembly, config, mod_id);
__ExpScapePower.init(assembly, config, mod_id);
__ExpScapeLinear.init(assembly, config, mod_id);
Expand Down
75 changes: 40 additions & 35 deletions CraftingSkill/CraftingSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,12 @@ public class CraftingSkillsPlugin : BaseUnityPlugin
Harmony harmony;

private static CraftingConfig config = new CraftingConfig();
private static Dictionary<string, Texture2D> cachedTextures = new Dictionary<string, Texture2D>();

public CraftingSkillsPlugin() {
LoadEmbeddedAssembly("fastJSON.dll");
}

private static void LoadEmbeddedAssembly(string assemblyName)
{
// RandyKnapp https://github.com/RandyKnapp/ValheimMods/blob/719e1a6dc419f9075c46b3eb4e3eb53285b7ffda/EpicLoot-Addon-Helheim/Helheim.cs#L58
var stream = GetManifestResourceStream(assemblyName);
if (stream == null)
{
Debug.LogError($"Could not load embedded assembly ({assemblyName})!");
return;
}

using (stream)
{
var data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
Assembly.Load(data);
}
}

public static Stream GetManifestResourceStream(string filename)
{
var assembly = Assembly.GetCallingAssembly();
var fullname = assembly.GetManifestResourceNames().SingleOrDefault(x => x.EndsWith(filename));
if (!string.IsNullOrEmpty(fullname))
{
return assembly.GetManifestResourceStream(fullname);
}

return null;
}

void Awake()
{
config.InitConfig(MOD_ID, Config);
Expand Down Expand Up @@ -92,7 +63,6 @@ private static Sprite LoadIconTexture()
}
}

private static Dictionary<string, Texture2D> cachedTextures = new Dictionary<string, Texture2D>();
private static Texture2D LoadTexture(string filepath)
{
if (cachedTextures.ContainsKey(filepath))
Expand All @@ -104,6 +74,37 @@ private static Texture2D LoadTexture(string filepath)
return texture2D;
}

private static void LoadEmbeddedAssembly(string assemblyName)
{
// RandyKnapp https://github.com/RandyKnapp/ValheimMods/blob/719e1a6dc419f9075c46b3eb4e3eb53285b7ffda/EpicLoot-Addon-Helheim/Helheim.cs#L58
var stream = GetManifestResourceStream(assemblyName);
if (stream == null)
{
Debug.LogError($"Could not load embedded assembly ({assemblyName})!");
return;
}

using (stream)
{
var data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
Assembly.Load(data);
}
}

public static Stream GetManifestResourceStream(string filename)
{
// RandyKnapp https://github.com/RandyKnapp/ValheimMods/blob/719e1a6dc419f9075c46b3eb4e3eb53285b7ffda/EpicLoot-Addon-Helheim/Helheim.cs
var assembly = Assembly.GetCallingAssembly();
var fullname = assembly.GetManifestResourceNames().SingleOrDefault(x => x.EndsWith(filename));
if (!string.IsNullOrEmpty(fullname))
{
return assembly.GetManifestResourceStream(fullname);
}

return null;
}

[HarmonyPatch(typeof(ItemDrop.ItemData))]
public static class ItemDataPatcher
{
Expand All @@ -114,9 +115,11 @@ public static class ItemDataPatcher
[HarmonyPatch("GetTooltip", typeof(ItemDrop.ItemData), typeof(int), typeof(bool))]
static void GetTooltip(ItemDrop.ItemData item, int qualityLevel, bool crafting, ref string __result)
{
// Display craft quality if item has it
// Then display crafting experience if there is a crafting recipe for the item
QualityComponent qualityComp = item.Extended()?.GetComponent<QualityComponent>();
if(qualityComp != null) {
var qcTooltip = qualityComp.GetTooltip();
var qcTooltip = qualityComp.GetTooltip(config);
__result += String.Format(
"\n{0}: <color=orange>{1}</color>",
CraftQualityLabel,
Expand All @@ -139,10 +142,10 @@ public static float GetItemQualityScalingFactor(ItemDrop.ItemData item, float mi
if (qualityComp == null) {
return 1.0f;
}
float scalingFactor = min + (max - min) * qualityComp.Quality.Skill;
return scalingFactor;
return min + (max - min) * qualityComp.Quality.ScalingFactor(config);
}


// First override the simple methods which returns floats
// public float GetArmor(int quality){}
// public float GetWeight(){}
Expand Down Expand Up @@ -199,6 +202,8 @@ public static void GetDamage(ref HitData.DamageTypes __result, ItemDrop.ItemData
}
}

// Below code handles gaining experience when crafting

public static float GetCraftTierMod(Recipe recipe)
{
switch (recipe.m_craftingStation?.m_name)
Expand Down Expand Up @@ -295,7 +300,7 @@ Recipe ___m_craftRecipe
if (isWorkbenchRecipe || isForgeRecipe || isNoStation || isStonecutterRecipe || isArtisanRecipe) {
float craftExperience = GetCraftExperience(___m_craftRecipe, craftLevel);
player.RaiseSkill((Skills.SkillType)CRAFTING_SKILL_ID, craftExperience);
float SkillLevel = player.GetSkillFactor((Skills.SkillType)CRAFTING_SKILL_ID);
// float SkillLevel = player.GetSkillFactor((Skills.SkillType)CRAFTING_SKILL_ID);
// ZLog.LogError($"Craft Succeeded => exp={craftExperience}, {SkillLevel}");
}
}
Expand Down
3 changes: 2 additions & 1 deletion CraftingSkill/CraftingSkill.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Quality.cs" />
<Compile Include="QualityComponent.cs" />
<Compile Include="QualityTier.cs" />
<Compile Include="StackableQuality.cs" />
</ItemGroup>
<ItemGroup>
Expand All @@ -149,4 +150,4 @@
xcopy /y /d "$(ProjectDir)CraftingSkillIcon.png" "M:\SteamLibrary\SteamApps\common\Valheim\BepInEx\plugins\CraftingSkill"
</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>
91 changes: 51 additions & 40 deletions CraftingSkill/Quality.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,64 +6,75 @@

namespace CraftingSkill
{
[Serializable]
public enum QualityTier
{
MIXED = 0,
AWFUL = 1,
POOR = 2,
NORMAL = 3,
FINE = 4,
SUPERIOR = 5,
EXCEPTIONAL = 6,
MASTERWORK = 7,
ARTIFACT = 8
}

// Extension method to QualityTier enum
public static class _QualityTier
{
public static string GetTooltip(this QualityTier tier) {
switch ( tier ) {
case QualityTier.MIXED: return "Mixed";
case QualityTier.AWFUL: return "Awful";
case QualityTier.POOR: return "Poor";
case QualityTier.NORMAL: return "Normal";
case QualityTier.FINE: return "Fine";
case QualityTier.SUPERIOR: return "Superior";
case QualityTier.EXCEPTIONAL: return "Exceptional";
case QualityTier.MASTERWORK: return "Masterwork";
case QualityTier.ARTIFACT: return "Artifact";
}
return "UNKNOWN";
}
}

[Serializable]
public class Quality
{
// Skill level when item is created
public float Skill = 0;
// Level of station used to create item
public int StationLevel = 0;
// Quantised item quality
public QualityTier Tier = QualityTier.NORMAL;
// So we can handle stack merges
public int Quantity = 1;
// Level of station used to create item
public int StationLevel = 0;
// For random outcomes
public float Variance;

public Quality()
{
Variance = UnityEngine.Random.value;
}
public string GetTooltip()

public string GetTooltip(CraftingConfig config)
{
float factor = ScalingFactor(config);
if (config.QuantisedQuality)
{
QualityTier tier = GetQualityTier(factor);
factor = tier.GetFactor();
return String.Format(
"{0} ({1})",
GetQualityTier(this.Skill).GetTooltip(),
(factor * 100f).ToString("0")
);
}

return String.Format(
"{0} ({1})",
this.Tier.GetTooltip(),
(this.Skill * 100f).ToString("0")
"{0} / 100",
(factor * 100f).ToString("0")
);
}

public float ScalingFactor(CraftingConfig config)
{
var factor = this.Skill;

if (config.StochasticVariance > 0)
{
// map 0,1 to -1,+1
var variance = 2.0f * (this.Variance - 0.5f);
// scale by config, add to factor
factor += config.StochasticVariance * variance;
// clamp invalid values (level 0 and 100)
factor = Mathf.Clamp(factor, 0.0f, 1.0f);
}

if (config.QuantisedQuality)
{
QualityTier tier = GetQualityTier(factor);
factor = tier.GetFactor();
}
return factor;
}
public static QualityTier GetQualityTier(float factor)
{
foreach (QualityTier tier in (QualityTier[])Enum.GetValues(typeof(QualityTier)))
{
if (tier.GetFactor() >= factor)
{
return tier;
}
}
return QualityTier.NORMAL;
}
}
}
23 changes: 9 additions & 14 deletions CraftingSkill/QualityComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public override BaseExtendedItemComponent Clone()
return MemberwiseClone() as BaseExtendedItemComponent;
}

public string GetTooltip()
public string GetTooltip(CraftingConfig config)
{
// Non-formated right hand side of "Quality: XXX"
return this.Quality.GetTooltip();
return this.Quality.GetTooltip(config);
}

public static void OnNewExtendedItemData(ExtendedItemData itemdata)
Expand Down Expand Up @@ -100,21 +100,16 @@ public static void OnNewExtendedItemData(ExtendedItemData itemdata)
ZLog.LogWarning("qualityComponent is not null during ExtendedItemData creation");
return;
}

var quality = new Quality();
quality.Skill = player.GetSkillFactor((Skills.SkillType)CraftingSkillsPlugin.CRAFTING_SKILL_ID);
quality.Quantity = itemdata.m_stack;

var skill = player.GetSkillFactor((Skills.SkillType)CraftingSkillsPlugin.CRAFTING_SKILL_ID);
var quantity = itemdata.m_stack;

CraftingStation station = player.GetCurrentCraftingStation();
if (station)
{
quality.StationLevel = station.GetLevel();
}

var qc = new StackableQuality();
qc.Qualities.Add(quality);
int stationLevel = station == null ? 0 : station.GetLevel();

var quality = new StackableQuality(skill, quantity, stationLevel);

itemdata.AddComponent<QualityComponent>().SetQuality(qc);
itemdata.AddComponent<QualityComponent>().SetQuality(quality);
}

public static void OnLoadExtendedItemData(ExtendedItemData itemdata)
Expand Down
Loading

0 comments on commit 533219a

Please sign in to comment.