public void FillEffectsCache(BaseStatsDictionary statsCache, byte level) { if (!this.HasStatEffects) { return; } // this temp cache will be taken only when necessarily TempStatsCache tempStatsCache = null; foreach (var statEffect in this.StatEffects) { if (level < statEffect.Level) { // level is lower than required continue; } tempStatsCache ??= TempStatsCache.GetFromPool(); var statName = statEffect.StatName; tempStatsCache.AddValue(this, statName, statEffect.CalcTotalValueBonus(level)); tempStatsCache.AddPercent(this, statName, statEffect.CalcTotalPercentBonus(level)); } if (tempStatsCache is not null) { statsCache.Merge(tempStatsCache); tempStatsCache.Dispose(); } }
private static WeaponFinalCache ServerCreateWeaponFinalCacheForDrone( ICharacter characterOwner, IProtoItemWeapon protoMiningTool, IDynamicWorldObject objectDrone) { using var tempStatsCache = TempStatsCache.GetFromPool(); // fill only the skills cache from character (status effects have no effect) foreach (var pair in characterOwner.SharedGetSkills().Skills) { var protoSkill = pair.Key; var skillLevel = pair.Value.Level; protoSkill.FillEffectsCache(tempStatsCache, skillLevel); } var finalStatsCache = tempStatsCache.CalculateFinalStatsCache(); return(new WeaponFinalCache( characterOwner, finalStatsCache, weapon: null, protoWeapon: protoMiningTool, protoAmmo: null, damageDescription: protoMiningTool.OverrideDamageDescription, protoExplosive: null, objectDrone: objectDrone)); }
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); }
protected sealed override void PrepareProtoWorldObject() { base.PrepareProtoWorldObject(); var defenseDescription = new DefenseDescription(); // Set default defense for static objects. By default there is no defense except for psi and radiation which are set to Max. // Individual objects will override this value with some specific tier of defense in their own class. defenseDescription.Set(ObjectDefensePresets.Default); this.PrepareDefense(defenseDescription); var defense = defenseDescription.ToReadOnly(); using var effects = TempStatsCache.GetFromPool(); defense.FillEffects(this, effects, maximumDefensePercent: double.MaxValue); this.DefenseStats = effects.CalculateFinalStatsCache(); this.PrepareProtoDynamicWorldObject(); }
protected sealed override void PrepareProtoWorldObject() { base.PrepareProtoWorldObject(); var defaultTexture = this.PrepareDefaultTexture(this.GetType()); if (defaultTexture is ITextureAtlasResource defaultTextureAtlas && !(defaultTexture is ITextureAtlasChunkResource)) { // use the first chunk of the atlas texture defaultTexture = defaultTextureAtlas.Chunk(0, 0); } this.DefaultTexture = defaultTexture; var layout = new StaticObjectLayout(); this.CreateLayout(layout); this.Layout = layout.ToReadOnly(); var defenseDescription = new DefenseDescription(); // Set default defense for static objects. By default there is no defense except for psi and radiation which are set to Max. // Individual objects will override this value with some specific tier of defense in their own class. defenseDescription.Set(ObjectDefensePresets.Default); this.PrepareDefense(defenseDescription); var defense = defenseDescription.ToReadOnly(); using (var effects = TempStatsCache.GetFromPool(isMultipliersSummed: true)) { defense.FillEffects(this, effects, maximumDefensePercent: double.MaxValue); this.DefenseStats = effects.CalculateFinalStatsCache(); } this.PrepareProtoStaticWorldObject(); }
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); }