diff --git a/Assets/Scriptables.meta b/Assets/Scriptables.meta
new file mode 100644
index 0000000..94a9442
--- /dev/null
+++ b/Assets/Scriptables.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1d13d7aac40657841955febd4faabbfa
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scriptables/EnemyAttributes.asset b/Assets/Scriptables/EnemyAttributes.asset
new file mode 100644
index 0000000..b389e2c
--- /dev/null
+++ b/Assets/Scriptables/EnemyAttributes.asset
@@ -0,0 +1,19 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: c5304ff6dfe84844887d751cee48606a, type: 3}
+ m_Name: EnemyAttributes
+ m_EditorClassIdentifier:
+ STR: {fileID: 0}
+ CON: {fileID: 0}
+ SPD: {fileID: 0}
+ RNG: {fileID: 0}
+ MND: {fileID: 0}
diff --git a/Assets/Scriptables/EnemyAttributes.asset.meta b/Assets/Scriptables/EnemyAttributes.asset.meta
new file mode 100644
index 0000000..a7d5e8f
--- /dev/null
+++ b/Assets/Scriptables/EnemyAttributes.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d5bf638cf02c5b94cb9874d4414c1b8a
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scriptables/StatEffect.asset b/Assets/Scriptables/StatEffect.asset
new file mode 100644
index 0000000..8f4ca8c
--- /dev/null
+++ b/Assets/Scriptables/StatEffect.asset
@@ -0,0 +1,14 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 494a21c06960ec442a7a6806f8aefedb, type: 3}
+ m_Name: StatEffect
+ m_EditorClassIdentifier:
diff --git a/Assets/Scriptables/StatEffect.asset.meta b/Assets/Scriptables/StatEffect.asset.meta
new file mode 100644
index 0000000..b6740dd
--- /dev/null
+++ b/Assets/Scriptables/StatEffect.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4c96040df8ebed746832db7857b25bed
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 11400000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Attribute.cs b/Assets/Scripts/Attribute.cs
index c8c9090..6c9a430 100644
--- a/Assets/Scripts/Attribute.cs
+++ b/Assets/Scripts/Attribute.cs
@@ -1,38 +1,24 @@
+using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
+[Serializable]
public struct Attribute
{
- [SerializeField]
- private long _base;
+ public long Base;
- public Attribute(long stat)
- {
- _base = stat;
- }
-
- ///
- /// Permanently increase the stat value.
- ///
- /// Increase amount.
- public void LevelUp(long by)
- {
- _base += by;
- }
+ public Attribute(long stat) { Base = stat; }
///
/// Calculates the stat value with accumulated buff and debuff modifiers.
///
- /// Additive bonus applied before multiplicative scaling.
- /// Multiplicative scaling in hundredths of a percent. E.g., 625 permyriad corresponds to 6.25%.
- /// Additive bonus applied after multiplicative scaling.
/// (base + baseBonus) * (100% + permyriadBonus) + flatBonus, bounded below by 0.
- public long Calc(long baseBonus, long permyriadBonus, long flatBonus)
+ public long Calc(EffectSO effect)
{
- var r = _base + baseBonus;
- var m = permyriadBonus + 10000;
- r = r * (m / 10000) + (r / 10000) * (m % 10000) + flatBonus;
+ var r = Base + effect.Base;
+ var m = effect.Permyriad + 10000;
+ r = r * (m / 10000) + (r / 10000) * (m % 10000) + effect.Flat;
if (r <= 0)
{
return 0;
diff --git a/Assets/Scripts/EffectSO.cs b/Assets/Scripts/EffectSO.cs
new file mode 100644
index 0000000..f50bce1
--- /dev/null
+++ b/Assets/Scripts/EffectSO.cs
@@ -0,0 +1,45 @@
+using UnityEngine;
+
+[CreateAssetMenu(fileName = "StatEffect", menuName = "Stat Effect")]
+public class EffectSO : ScriptableObject
+{
+ ///
+ /// Additive change applied before multiplicative scaling.
+ ///
+ public long Base;
+ ///
+ /// Multiplicative scaling in units of hundredth of a percent.
+ /// E.g., 625 permyriad is 6.25%.
+ ///
+ public long Permyriad;
+ ///
+ /// Additive change applied after multiplicative scaling.
+ ///
+ public long Flat;
+
+ ///
+ /// Create a new attribute effect instance.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static EffectSO New(long baseBonus = 0, long permyriad = 0, long flat = 0)
+ {
+ var effect = ScriptableObject.CreateInstance();
+ effect.Base = baseBonus;
+ effect.Permyriad = permyriad;
+ effect.Flat = flat;
+ return effect;
+ }
+
+ ///
+ /// Create a new EffectSO from a percentage.
+ ///
+ /// Percentage. E.g., 6.25f results in a Permyriad of 625.
+ /// Effect with the given percentage.
+ public static EffectSO FromPercent(float p)
+ {
+ return New(permyriad: (long)(p * 100));
+ }
+}
diff --git a/Assets/Scripts/EffectSO.cs.meta b/Assets/Scripts/EffectSO.cs.meta
new file mode 100644
index 0000000..a39567b
--- /dev/null
+++ b/Assets/Scripts/EffectSO.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 494a21c06960ec442a7a6806f8aefedb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/EnemyAttributesSO.cs b/Assets/Scripts/EnemyAttributesSO.cs
new file mode 100644
index 0000000..9d1a39f
--- /dev/null
+++ b/Assets/Scripts/EnemyAttributesSO.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+[CreateAssetMenu(fileName = "EnemyAttributes", menuName = "Enemy Attributes")]
+public class EnemyAttributesSO : ScriptableObject
+{
+ [SerializeField] private Attribute STR;
+ [SerializeField] private Attribute CON;
+ [SerializeField] private Attribute SPD;
+ [SerializeField] private Attribute RNG;
+ [SerializeField] private Attribute MND;
+ public long XP { get; private set; }
+ public long Threat { get; private set; }
+
+ public static EnemyAttributesSO New()
+ {
+ return ScriptableObject.CreateInstance();
+ }
+}
diff --git a/Assets/Scripts/EnemyAttributesSO.cs.meta b/Assets/Scripts/EnemyAttributesSO.cs.meta
new file mode 100644
index 0000000..824414f
--- /dev/null
+++ b/Assets/Scripts/EnemyAttributesSO.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c5304ff6dfe84844887d751cee48606a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/HeroAttributesSO.cs b/Assets/Scripts/HeroAttributesSO.cs
new file mode 100644
index 0000000..2a949bb
--- /dev/null
+++ b/Assets/Scripts/HeroAttributesSO.cs
@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HeroAttributesSO : ScriptableObject
+{
+ [SerializeField] private Attribute STR;
+ [SerializeField] private Attribute MAG;
+ [SerializeField] private Attribute DEX;
+ [SerializeField] private Attribute CON;
+ [SerializeField] private Attribute CHA;
+ [SerializeField] private Attribute FTH;
+
+ public static HeroAttributesSO New()
+ {
+ return ScriptableObject.CreateInstance();
+ }
+}
diff --git a/Assets/Scripts/HeroAttributesSO.cs.meta b/Assets/Scripts/HeroAttributesSO.cs.meta
new file mode 100644
index 0000000..a052f16
--- /dev/null
+++ b/Assets/Scripts/HeroAttributesSO.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 538672e6491e46748a1cc27fe3a52455
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Tests/AttributeTest.cs b/Assets/Tests/AttributeTest.cs
index 8668e08..bfb95d4 100644
--- a/Assets/Tests/AttributeTest.cs
+++ b/Assets/Tests/AttributeTest.cs
@@ -7,19 +7,18 @@ using UnityEngine.TestTools;
public class AttributeTest
{
[Test]
- [TestCase(1000000, 0, 0, 0, 0, ExpectedResult = 1000000)]
- [TestCase(1000000, 1, 0, 0, 0, ExpectedResult = 1000001)]
- [TestCase(1000000, 0, 2, 0, 0, ExpectedResult = 1000002)]
- [TestCase(1000000, 0, 0, 10000, 0, ExpectedResult = 2000000)]
- [TestCase(1000000, 0, 0, 0, 3, ExpectedResult = 1000003)]
- [TestCase(0, 1000000, 1000000, 5000, 1000, ExpectedResult = 3001000)]
- [TestCase(1000000, 0, 0, -10000, 0, ExpectedResult = 0)]
- [TestCase(1000000, 0, 0, -20000, 0, ExpectedResult = 0)]
- [TestCase(1000000, 0, 0, -20000, 50, ExpectedResult = 0)]
- public long Calc(long startStat, long levelUp, long baseBonus, long permyriadBonus, long flatBonus)
+ [TestCase(1000000, 0, 0, 0, ExpectedResult = 1000000)]
+ [TestCase(1000000, 1, 0, 0, ExpectedResult = 1000001)]
+ [TestCase(1000000, 0, 2, 0, ExpectedResult = 1000200)]
+ [TestCase(1000000, 0, 0, 10000, ExpectedResult = 1010000)]
+ [TestCase(0, 1000000, 5000, 1000000, ExpectedResult = 2500000)]
+ [TestCase(1000000, 0, -10000, 0, ExpectedResult = 0)]
+ [TestCase(1000000, 0, -20000, 0, ExpectedResult = 0)]
+ [TestCase(1000000, 0, -20000, 0, ExpectedResult = 0)]
+ public long Value(long startStat, long baseBonus, long permyriadBonus, long flatBonus)
{
var attr = new Attribute(startStat);
- attr.LevelUp(levelUp);
- return attr.Calc(baseBonus, permyriadBonus, flatBonus);
+ var effect = EffectSO.New(baseBonus, permyriadBonus, flatBonus);
+ return attr.Calc(effect);
}
}