포스트

[C# , Unity] StatValue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Core.Stat
{
    public enum StatModType
    {
        Add,
        MultiplierAdd,
        Multiply
    }

    public class StatModifier
    {
        public int order;
        public StatModType statModType;
        public double value;
        public object source;

        public StatModifier(StatModType statModType, double value, int order, object source)
        {
            this.statModType = statModType;
            this.value = value;
            this.order = order;
            this.source = source;
        }
    }

    public class StatValue
    {
        public double Result => _resultCache;
        public event Action OnChanged;

        private LinkedList<StatModifier> statModifiers = new();

        private double _baseValue = 0;
        private double _resultCache;

        public StatValue(double baseValue)
        {
            SetBaseValue(baseValue);
        }

        public void SetBaseValue(double baseValue)
        {
            _baseValue = baseValue;
            CalculateResult();
        }

        public void AddModifier(StatModifier statModifier)
        {
            statModifiers.AddLast(statModifier);
            CalculateResult();
        }

        public void RemoveModifier(StatModifier modifier)
        {
            statModifiers.Remove(modifier);
            CalculateResult();
        }

        public void RemoveAllModifiersFromSource(object source)
        {
            var replaceList = new LinkedList<StatModifier>();
            statModifiers.Where(modifier => modifier.source != source).Foreach(modifier => replaceList.AddLast(modifier));
            statModifiers = replaceList;
            CalculateResult();
        }

        private void CalculateResult()
        {
            _resultCache = _baseValue;

            statModifiers.GroupBy(modifier => modifier.order)
                .OrderBy(group => group.Key)
                .Foreach(group =>
                {
                    double multiplier = 1;

                    group.OrderBy(layer => layer.statModType).Foreach(modifier =>
                    {
                        switch (modifier.statModType)
                        {
                            case StatModType.Add:
                                _resultCache += modifier.value;
                                break;
                            case StatModType.MultiplierAdd:
                                multiplier += modifier.value;
                                break;
                            case StatModType.Multiply:
                                _resultCache *= modifier.value;
                                break;
                        }
                    });

                    _resultCache *= multiplier;
                });

            OnChanged?.Invoke();
        }

        public void Clear()
        {
            statModifiers.Clear();
            CalculateResult();
        }
    }
}

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.