public int GrantCondition(Actor self, object source, int duration = 0) { if (!CanGrantCondition(self, source)) { return(ConditionManager.InvalidConditionToken); } var token = conditionManager.GrantCondition(self, Info.Condition); HashSet <int> permanent; permanentTokens.TryGetValue(source, out permanent); if (duration > 0) { // Check level caps if (Info.SourceCap > 0) { var timedCount = timedTokens.Count(t => t.Source == source); if ((permanent != null ? permanent.Count + timedCount : timedCount) >= Info.SourceCap) { // Get timed token from the same source with closest expiration. var expireIndex = timedTokens.FindIndex(t => t.Source == source); if (expireIndex >= 0) { var expireToken = timedTokens[expireIndex].Token; timedTokens.RemoveAt(expireIndex); if (conditionManager.TokenValid(self, expireToken)) { conditionManager.RevokeCondition(self, expireToken); } } } } if (Info.TotalCap > 0) { var totalCount = permanentTokens.Values.Sum(t => t.Count) + timedTokens.Count; if (totalCount >= Info.TotalCap) { // Prefer tokens from the same source if (timedTokens.Count > 0) { var expire = timedTokens[0].Token; if (conditionManager.TokenValid(self, expire)) { conditionManager.RevokeCondition(self, expire); } timedTokens.RemoveAt(0); } } } var timedToken = new TimedToken(token, self, source, duration); var index = timedTokens.FindIndex(t => t.Expires >= timedToken.Expires); if (index >= 0) { timedTokens.Insert(index, timedToken); } else { timedTokens.Add(timedToken); // Track the duration and expiration for the longest remaining timer. expires = timedToken.Expires; this.duration = duration; } } else if (permanent == null) { permanentTokens.Add(source, new HashSet <int> { token }); } else { permanent.Add(token); } return(token); }
public int GrantCondition(Actor self, object source, int duration = 0) { if (conditionManager == null || source == null || !CanGrantCondition(self, source)) { return(ConditionManager.InvalidConditionToken); } var token = conditionManager.GrantCondition(self, Info.Condition, duration); var permanent = permanentTokens.GetOrAdd(source); if (duration > 0) { var timed = timedTokens.GetOrAdd(source); // Remove expired tokens timed.RemoveWhere(t => t.Expires < self.World.WorldTick); // Check level caps if (Info.SourceCap > 0) { if (permanent.Count + timed.Count >= Info.SourceCap) { var expire = timed.MinByOrDefault(t => t.Expires); if (expire != null) { timed.Remove(expire); if (conditionManager.TokenValid(self, expire.Token)) { conditionManager.RevokeCondition(self, expire.Token); } } } } if (Info.TotalCap > 0) { var totalCount = permanentTokens.Values.SelectMany(t => t).Count() + timedTokens.Values.SelectMany(t => t).Count(); if (totalCount >= Info.TotalCap) { // Prefer tokens from the same source var expire = timedTokens.SelectMany(t => t.Value.Select(tt => new Tuple <object, TimedToken>(t.Key, tt))) .MinByOrDefault(t => t.Item2.Expires); if (expire != null) { if (conditionManager.TokenValid(self, expire.Item2.Token)) { conditionManager.RevokeCondition(self, expire.Item2.Token); } timedTokens[expire.Item1].Remove(expire.Item2); } } } timed.Add(new TimedToken { Expires = self.World.WorldTick + duration, Token = token }); } else { permanent.Add(token); } return(token); }