| 212 | } |
| 213 | |
| 214 | void StatSet::update(float dt) { |
| 215 | // We use two intermediate values for calculating the effective stat value. |
| 216 | // The baseModifiedValue represents the application of the base percentage |
| 217 | // modifiers and the value modifiers, which only depend on the baseValue. |
| 218 | // The effectiveModifiedValue is the application of all effective percentage |
| 219 | // modifiers successively on the baseModifiedValue, causing them to stack with |
| 220 | // each other in addition to base multipliers and value modifiers |
| 221 | |
| 222 | // First, clear the modified values to get rid of temporary stats applied |
| 223 | // from modifiers that may no longer be there |
| 224 | m_effectiveStats.clear(); |
| 225 | |
| 226 | // Then we do all the StatValueModifiers and StatBaseMultipliers and |
| 227 | // compute the baseModifiedValue |
| 228 | |
| 229 | for (auto& p : m_baseStats) { |
| 230 | auto& stat = m_effectiveStats[p.first]; |
| 231 | stat.baseValue = p.second; |
| 232 | stat.baseModifiedValue = stat.baseValue; |
| 233 | } |
| 234 | |
| 235 | for (auto const& p : m_statModifierGroups) { |
| 236 | for (auto const& modifier : p.second) { |
| 237 | if (auto baseMultiplier = modifier.ptr<StatBaseMultiplier>()) { |
| 238 | auto& stat = m_effectiveStats[baseMultiplier->statName]; |
| 239 | stat.baseModifiedValue += (baseMultiplier->baseMultiplier - 1.0f) * stat.baseValue; |
| 240 | } else if (auto valueModifier = modifier.ptr<StatValueModifier>()) { |
| 241 | auto& stat = m_effectiveStats[valueModifier->statName]; |
| 242 | stat.baseModifiedValue += valueModifier->value; |
| 243 | } |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | // Then we do all the StatEffectiveMultipliers and compute the |
| 248 | // final effectiveModifiedValue |
| 249 | |
| 250 | for (auto& p : m_effectiveStats) |
| 251 | p.second.effectiveModifiedValue = p.second.baseModifiedValue; |
| 252 | |
| 253 | for (auto const& p : m_statModifierGroups) { |
| 254 | for (auto const& modifier : p.second) { |
| 255 | if (auto effectiveMultiplier = modifier.ptr<StatEffectiveMultiplier>()) { |
| 256 | auto& stat = m_effectiveStats[effectiveMultiplier->statName]; |
| 257 | stat.effectiveModifiedValue *= effectiveMultiplier->effectiveMultiplier; |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | // Then update all the resources due to charging and percentage tracking, |
| 263 | // after updating the stats. |
| 264 | |
| 265 | for (auto& p : m_resources) { |
| 266 | Maybe<float> newMaxValue; |
| 267 | if (p.second.max.is<String>()) |
| 268 | newMaxValue = statEffectiveValue(p.second.max.get<String>()); |
| 269 | else if (p.second.max.is<float>()) |
| 270 | newMaxValue = p.second.max.get<float>(); |
| 271 | |