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); } }
protected sealed override void PrepareProto() { var effects = new Effects(); this.PrepareEffects(effects); this.ProtoEffects = effects.ToReadOnly(); this.PrepareProtoPerk(); }
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); }
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); }
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); }
public StatModificationDisplay(IReadOnlyStatsDictionary statsDictionary, bool hideDefenseStats) { this.StatsDictionary = statsDictionary; this.HideDefenseStats = hideDefenseStats; }
public ViewModelStatModificationDisplay(IReadOnlyStatsDictionary effects, bool hideDefenseStats) { this.hideDefenseStats = hideDefenseStats; this.lazyStatModifications = new Lazy <IReadOnlyList <StatModificationData> >( () => this.CreateEffectsList(effects)); }