public override void OnGameTick(float deltaTime)
        {
            if ((tickAccum += deltaTime) < 0.33f)
            {
                return;
            }
            tickAccum = 0;

            float nowStressLevel = 0f;

            List <string> codesToRemove = null;

            foreach (var stateAndcode in ActiveStatesByCode)
            {
                string         code    = stateAndcode.Key;
                ActiveEmoState state   = stateAndcode.Value;
                float          leftDur = state.Duration -= 10 * deltaTime;
                if (leftDur <= 0)
                {
                    if (codesToRemove == null)
                    {
                        codesToRemove = new List <string>();
                    }
                    codesToRemove.Add(code);

                    entityAttr.RemoveAttribute(code);
                    continue;
                }

                nowStressLevel += availableStates[state.StateId].StressLevel;
            }
            if (codesToRemove != null)
            {
                foreach (string s in codesToRemove)
                {
                    ActiveStatesByCode.Remove(s);
                }
            }

            float curlevel = entity.WatchedAttributes.GetFloat("stressLevel");

            if (nowStressLevel > 0)
            {
                entity.WatchedAttributes.SetFloat("stressLevel", Math.Max(curlevel, nowStressLevel));
            }
            else
            {
                if (curlevel > 0) // no need to keep recalculating and setting it once it reaches 0
                {
                    curlevel = Math.Max(0, curlevel - deltaTime * 1.25f);
                    entity.WatchedAttributes.SetFloat("stressLevel", curlevel);
                }
            }


            if (entity.World.EntityDebugMode)
            {
                // expensive string operations
                entity.DebugAttributes.SetString("emotionstates", string.Join(", ", ActiveStatesByCode.Keys.ToList()));
            }
        }
        public bool TryTriggerState(string statecode, double chance, long sourceEntityId)
        {
            bool triggered = false;

            for (int stateid = 0; stateid < availableStates.Length; stateid++)
            {
                EmotionState newstate = availableStates[stateid];

                if (newstate.Code != statecode || chance > newstate.Chance)
                {
                    continue;
                }

                if (newstate.whenHealthRelBelow < healthRel)
                {
                    continue;
                }

                ActiveEmoState activeState = null;

                foreach (var val in ActiveStatesByCode)
                {
                    if (val.Key == newstate.Code)
                    {
                        activeState = val.Value;
                        continue;
                    }

                    int          activestateid = val.Value.StateId;
                    EmotionState activestate   = availableStates[activestateid];
                    if (activestate.Slot == newstate.Slot)
                    {
                        // Active state has priority over this one
                        if (activestate.Priority > newstate.Priority)
                        {
                            return(false);
                        }
                        else
                        {
                            // New state has priority
                            ActiveStatesByCode.Remove(val.Key);

                            entityAttr.RemoveAttribute(newstate.Code);
                            break;
                        }
                    }
                }

                float duration = newstate.Duration;
                if (newstate.BelowTempThreshold > -99 && entity.World.BlockAccessor.GetClimateAt(entity.Pos.AsBlockPos, EnumGetClimateMode.NowValues).Temperature < newstate.BelowTempDuration)
                {
                    duration = newstate.BelowTempDuration;
                }

                float newDuration = 0;
                if (newstate.AccumType == EnumAccumType.Sum)
                {
                    newDuration = activeState?.Duration ?? 0 + duration;
                }
                if (newstate.AccumType == EnumAccumType.Max)
                {
                    newDuration = Math.Max(activeState?.Duration ?? 0, duration);
                }
                if (newstate.AccumType == EnumAccumType.NoAccum)
                {
                    newDuration = activeState?.Duration > 0 ? activeState?.Duration ?? 0 : duration;
                }

                if (activeState == null)
                {
                    ActiveStatesByCode[newstate.Code] = new ActiveEmoState()
                    {
                        Duration = newDuration, SourceEntityId = sourceEntityId, StateId = stateid
                    };
                }
                else
                {
                    activeState.SourceEntityId = sourceEntityId;
                }


                entityAttr.SetFloat(newstate.Code, newDuration);
                triggered = true;
            }

            return(triggered);
        }