예제 #1
0
        private IReadOnlyList <StatModificationData> CreateEffectsList(IReadOnlyStatsDictionary statsDictionary)
        {
            var multipliers       = statsDictionary.Multipliers;
            var totalEntriesCount = multipliers.Count + statsDictionary.Values.Count;

            if (totalEntriesCount == 0)
            {
                return(null);
            }

            var result = new Dictionary <StatName, StatModificationData>(capacity: totalEntriesCount);

            foreach (var entry in statsDictionary.Values)
            {
                var statName = entry.Key;
                if (!this.IsHidden(statName))
                {
                    AppendValue(statName, entry.Value);
                }
            }

            foreach (var entry in multipliers)
            {
                var statName = entry.Key;
                if (!this.IsHidden(statName))
                {
                    AppendPercent(statName, entry.Value);
                }
            }

            return(result.Values.OrderBy(p => p.StatName)
                   .ToList());

            void AppendValue(StatName key, double value)
            {
                if (result.TryGetValue(key, out var entry))
                {
                    entry.Value += value;
                    return;
                }

                result[key] = new StatModificationData(key,
                                                       value,
                                                       percent: 1.0);
            }

            void AppendPercent(StatName key, double percent)
            {
                if (result.TryGetValue(key, out var entry))
                {
                    entry.Percent += percent;
                    return;
                }

                result[key] = new StatModificationData(key,
                                                       value: 0,
                                                       percent);
            }
        }
예제 #2
0
        protected sealed override void PrepareProto()
        {
            var effects = new Effects();

            this.PrepareEffects(effects);
            this.ProtoEffects = effects.ToReadOnly();

            this.PrepareProtoPerk();
        }
예제 #3
0
        public static void RefreshCharacterFinalStatsCache(
            IReadOnlyStatsDictionary protoEffects,
            ICharacterPublicState publicState,
            BaseCharacterPrivateState privateState,
            bool isFirstTime = false)
        {
            var containerEquipment = (publicState as ICharacterPublicStateWithEquipment)?.ContainerEquipment;

            privateState.ContainerEquipmentLastStateHash = containerEquipment?.StateHash;

            FinalStatsCache finalStatsCache;

            using (var tempStatsCache = TempStatsCache.GetFromPool(isMultipliersSummed: false))
            {
                // merge character prototype effects
                tempStatsCache.Merge(protoEffects);

                if (privateState is PlayerCharacterPrivateState playerCharacterPrivateState)
                {
                    // merge skill effects
                    var skills = playerCharacterPrivateState.Skills;
                    skills.SharedFillEffectsCache(tempStatsCache);
                }

                foreach (var statusEffect in privateState.StatusEffects)
                {
                    var protoStatusEffect = (IProtoStatusEffect)statusEffect.ProtoLogicObject;
                    tempStatsCache.Merge(protoStatusEffect.ProtoEffects);
                }

                if (containerEquipment != null)
                {
                    // merge equipment effects
                    foreach (var item in containerEquipment.Items)
                    {
                        if (item.ProtoGameObject is IProtoItemEquipment protoEquipment)
                        {
                            tempStatsCache.Merge(protoEquipment.ProtoEffects);
                        }
                    }
                }

                // calculate the final stats cache
                finalStatsCache = tempStatsCache.CalculateFinalStatsCache();
            }

            privateState.FinalStatsCache = finalStatsCache;

            // need to recalculate the weapon cache as it depends on the final cache
            privateState.WeaponState.WeaponCache = null;

            ApplyFinalStatsCache(finalStatsCache, publicState.CurrentStats, isFirstTime);
        }
예제 #4
0
        public void Merge(IReadOnlyStatsDictionary otherStatsCache)
        {
            this.ValidateIsNotReadOnly();

            this.Merge(
                this.Values,
                otherStatsCache.Values,
                isMultipliers: false);

            this.Merge(
                this.Multipliers,
                otherStatsCache.Multipliers,
                isMultipliers: true);

            StatsSources.Merge(ref this.sources, otherStatsCache.Sources);
        }
예제 #5
0
        public void Merge(IReadOnlyStatsDictionary otherStatsCache)
        {
            this.ValidateIsNotReadOnly();

            // values are merged via sum
            this.Merge(
                this.Values,
                otherStatsCache.Values,
                isMultiplied: false);

            // multipliers are merged via multiplication
            this.Merge(
                this.Multipliers,
                otherStatsCache.Multipliers,
                isMultiplied: !this.IsMultipliersSummed);

            StatsSources.Merge(ref this.sources, otherStatsCache.Sources);
        }
        public static void RefreshCharacterFinalStatsCache(
            IReadOnlyStatsDictionary protoEffects,
            ICharacterPublicState publicState,
            BaseCharacterPrivateState privateState,
            bool isFirstTime = false)
        {
            var containerEquipment = (publicState as ICharacterPublicStateWithEquipment)?.ContainerEquipment;

            privateState.ContainerEquipmentLastStateHash = containerEquipment?.StateHash;

            FinalStatsCache finalStatsCache;

            using (var tempStatsCache = TempStatsCache.GetFromPool())
            {
                // merge character prototype effects
                tempStatsCache.Merge(protoEffects);

                if (privateState is PlayerCharacterPrivateState playerCharacterPrivateState)
                {
                    // merge origin effects
                    if (playerCharacterPrivateState.Origin is not null)
                    {
                        tempStatsCache.Merge(playerCharacterPrivateState.Origin.Effects);
                    }

                    // merge skill effects
                    var skills = playerCharacterPrivateState.Skills;
                    skills.SharedFillEffectsCache(tempStatsCache);

                    // merge perks from tech nodes
                    foreach (var techNode in playerCharacterPrivateState.Technologies.Nodes)
                    {
                        foreach (var nodeEffect in techNode.NodeEffects)
                        {
                            if (nodeEffect is TechNodeEffectPerkUnlock perkUnlock)
                            {
                                tempStatsCache.Merge(perkUnlock.Perk.ProtoEffects);
                            }
                        }
                    }
                }

                foreach (var statusEffect in privateState.StatusEffects)
                {
                    if (statusEffect.IsDestroyed)
                    {
                        // the status effect might be already destroyed but still remain in the list
                        continue;
                    }

                    var protoStatusEffect = (IProtoStatusEffect)statusEffect.ProtoLogicObject;
                    tempStatsCache.Merge(protoStatusEffect.ProtoEffects);
                }

                if (containerEquipment is not null)
                {
                    // merge equipment effects
                    foreach (var item in containerEquipment.Items)
                    {
                        if (item.ProtoGameObject is IProtoItemEquipment protoEquipment &&
                            protoEquipment.SharedCanApplyEffects(item, containerEquipment))
                        {
                            tempStatsCache.Merge(protoEquipment.ProtoEffects);
                        }
                    }
                }

                // calculate the final stats cache
                finalStatsCache = tempStatsCache.CalculateFinalStatsCache();
            }

            privateState.FinalStatsCache = finalStatsCache;

            // need to recalculate the weapon cache as it depends on the final cache
            privateState.WeaponState.WeaponCache = null;

            ApplyFinalStatsCache(finalStatsCache, publicState.CurrentStats, isFirstTime);
        }
예제 #7
0
 public StatModificationDisplay(IReadOnlyStatsDictionary statsDictionary, bool hideDefenseStats)
 {
     this.StatsDictionary  = statsDictionary;
     this.HideDefenseStats = hideDefenseStats;
 }
예제 #8
0
 public ViewModelStatModificationDisplay(IReadOnlyStatsDictionary effects, bool hideDefenseStats)
 {
     this.hideDefenseStats      = hideDefenseStats;
     this.lazyStatModifications = new Lazy <IReadOnlyList <StatModificationData> >(
         () => this.CreateEffectsList(effects));
 }