Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }