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); }
private void ServerRebuildFinalCacheIfNeeded( ICharacter character, BaseCharacterPrivateState privateState, ICharacterPublicState publicState) { if (!privateState.FinalStatsCache.IsDirty) { return; } // rebuild stats cache SharedCharacterStatsHelper.RefreshCharacterFinalStatsCache(this.ProtoCharacterDefaultEffects, publicState, privateState); }
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); }