enum eModifiersTickType { TICK = 1, ACTIVATE_CHECK = 2, DEACTIVATE_CHECK = 4, } class ModifierBase { int m_ID = 0; ModifiersManager m_Manager; //! the manager instance string m_System = "Modifiers"; float m_ActivatedTime; //! overall time this modifier was active bool m_TrackActivatedTime; //!should this modifier track overall time it was active ? bool m_IsPersistent; //! is this modifier saved to the DB ? PlayerBase m_Player; float m_TickIntervalInactive = 5; float m_TickIntervalActive = 3; bool m_IsActive; bool m_ShouldBeActive; float m_AccumulatedTimeActive; float m_AccumulatedTimeInactive; float m_LastTickedActive; int m_TickType = (eModifiersTickType.TICK | eModifiersTickType.ACTIVATE_CHECK | eModifiersTickType.DEACTIVATE_CHECK);//some modifiers do not need to check activate condition, as they get activated by request float m_LastTickedInactive; bool m_IsLocked = false; EActivationType m_ActivationType; eModifierSyncIDs m_SyncID; //! max 32 synced modifiers supported, 0 == no sync PluginPlayerStatus m_ModulePlayerStatus; protected bool m_AnalyticsStatsEnabled; void ModifierBase() { Class.CastTo(m_ModulePlayerStatus, GetPlugin(PluginPlayerStatus)); } void InitBase(PlayerBase player, ModifiersManager manager) { m_Manager = manager; m_Player = player; Init(); } void Init() { if (m_AnalyticsStatsEnabled) AnalyticsRegisterStat(m_ID, "state"); } PlayerBase GetPlayer() { return m_Player; } bool IsPersistent() { return m_IsPersistent; } void MakeParamObjectPersistent(Param object) { m_Manager.m_ParamList.Insert(object); } void ResetLastTickTime() { m_LastTickedActive = 0; } string GetDebugText() { return ""; } string GetDebugTextSimple() { return ""; } void DisableActivateCheck() { m_TickType = (m_TickType & ~eModifiersTickType.ACTIVATE_CHECK); } void DisableDeactivateCheck() { m_TickType = (m_TickType & ~eModifiersTickType.DEACTIVATE_CHECK); } void Tick(float delta_time) { if (!m_IsActive && m_ShouldBeActive) Activate(); if (m_IsActive) { m_AccumulatedTimeActive += delta_time; if (m_AccumulatedTimeActive > m_TickIntervalActive) { if (m_TickType & eModifiersTickType.DEACTIVATE_CHECK && DeactivateCondition(m_Player) && !IsLocked()) { Deactivate(); } else { m_ActivatedTime += m_AccumulatedTimeActive; OnTick(m_Player, m_AccumulatedTimeActive); } m_AccumulatedTimeActive = 0; } } else if (m_TickType & eModifiersTickType.ACTIVATE_CHECK) { m_AccumulatedTimeInactive += delta_time; if (m_AccumulatedTimeInactive > m_TickIntervalInactive) { if (ActivateCondition(m_Player)) { if (!IsLocked()) ActivateRequest(EActivationType.TRIGGER_EVENT_ON_ACTIVATION); } m_AccumulatedTimeInactive = 0; } } } bool IsActive() { return m_IsActive; } void SetLock(bool state) { m_IsLocked = state; } bool IsLocked() { return m_IsLocked; } bool IsTrackAttachedTime() { return m_TrackActivatedTime; } float GetAttachedTime() { return m_ActivatedTime; } void SetAttachedTime(float time) { m_ActivatedTime = time; } int GetModifierID() { return m_ID; } string GetName() { string name = ClassName(); int indexStart = name.Length() - 4; int indexEnd = name.Length(); name = name.SubstringInverted(name, indexStart, indexEnd); return name; } bool ActivateCondition(PlayerBase player) { return false; } bool DeactivateCondition(PlayerBase player) { return false; } //! is called when an inactive modifier gets activated during gameplay, is NOT called on activation upon player server connection(see OnReconnect) void OnActivate(PlayerBase player); //! is called when a modifier is being re-activated upon player server connection, use to activate systems which are not persistent and need to run alongside active modifiers void OnReconnect(PlayerBase player); void OnDeactivate(PlayerBase player); void Activate() { if (m_AnalyticsStatsEnabled) { AnalyticsRegisterStat(m_ID, "state"); AnalyticsSetState(m_ID, 1.0); } m_IsActive = true; m_Player.m_SyncedModifiers = (m_Player.m_SyncedModifiers | m_SyncID); if (m_ActivationType == EActivationType.TRIGGER_EVENT_ON_ACTIVATION) OnActivate(m_Player); else if (m_ActivationType == EActivationType.TRIGGER_EVENT_ON_CONNECT) OnReconnect(m_Player); m_Player.SetSynchDirty(); } void ActivateRequest(EActivationType trigger) { m_ShouldBeActive = true; m_ActivationType = trigger; } void Deactivate(bool trigger = true) { if (!m_IsActive) return; if (m_AnalyticsStatsEnabled) AnalyticsSetState(m_ID, -1.0); m_Player.m_SyncedModifiers = (m_Player.m_SyncedModifiers & ~m_SyncID); m_ShouldBeActive = false; m_IsActive = false; m_ActivatedTime = 0; if (trigger) OnDeactivate(m_Player); } void OnStoreSave(ParamsWriteContext ctx); private void OnTick(PlayerBase player, float deltaT); private void AnalyticsRegisterStat(int modifierId, string keySuffix) { string modifierIdName = EnumTools.EnumToString(eModifiers, modifierId); modifierIdName.ToLower(); m_Player.StatRegister(string.Format("%1_%2", modifierIdName, keySuffix)); } //! special treating of the value to set state only (without counter use) private void AnalyticsSetState(int modifierId, float value) { string modifierStatKey = EnumTools.EnumToString(eModifiers, modifierId); modifierStatKey.ToLower(); string formatttedKey = string.Format("%1_state", modifierStatKey); if (value == -1.0) { if(m_Player.StatGet(formatttedKey) == 0.0) return; } if (value == 1.0) { if(m_Player.StatGet(formatttedKey) == 1.0) return; } m_Player.StatUpdate(formatttedKey, value); } }