enum EAlarmClockState { UNSET, SET, RINGING, //----------- COUNT } class ClockBase : Inventory_Base { float m_AlarmTime01; int m_State = EAlarmClockState.UNSET; static const float UPDATE_TICK_RATE = 1; // Clock update tick frequency ref Timer m_TimerUpdate; float m_RingingDuration; int m_StatePrev = -1; EffectSound m_RingingSoundLoop; EffectSound m_TurnOnSound; EffectSound m_DestoryedSound; EffectSound m_HitSound; EffectSound m_WorkingSound; const float RINGING_DURATION_MAX = 60;//in secs, at or past this value, the clock stops ringing void ClockBase() { Init(); } void ~ClockBase() { SEffectManager.DestroyEffect(m_WorkingSound); SEffectManager.DestroyEffect(m_HitSound); SEffectManager.DestroyEffect(m_DestoryedSound); SEffectManager.DestroyEffect(m_TurnOnSound); SEffectManager.DestroyEffect(m_RingingSoundLoop); } void Init() { RegisterNetSyncVariableInt("m_State", 0, EAlarmClockState.COUNT - 1); } override void SetActions() { super.SetActions(); AddAction(ActionAttachExplosivesTrigger); } protected int GetAlarmInMin() { int alarm_hand_in_mins = ConvertAlarmHand01ToMins12h(m_AlarmTime01); int pass, hour, minute; GetGame().GetWorld().GetDate(pass, pass, pass, hour, minute); int curr_time_in_minutes = ConvertTimeToMins12h(hour, minute); int ring_in_mins = GetTimeDiffInMins12h(curr_time_in_minutes, alarm_hand_in_mins); return ring_in_mins; } static int ConvertAlarmHand01ToMins12h(float time01) { return Math.Lerp(0,12*60,time01); } static int ConvertAlarmHand01ToMins(float time01, int mins_max/*what's the upper range in minutes we are trying to map the time01 to*/) { return Math.Lerp(0,mins_max,time01); } static float ConvertMins12hToAlarmHand01(int mins) { return Math.InverseLerp(0,12*60,mins); } static int ConvertTimeToMins12h(int hour, int minute) { if (hour >= 12) hour -= 12; return hour * 60 + minute; } static int GetTimeDiffInMins12h(int from_mins, int to_mins) { if (to_mins > from_mins) { return to_mins - from_mins; } else if (to_mins < from_mins) { return ((12 * 60) - from_mins) + to_mins; } else return 0; } string GetToggleSound() { return ""; } string GetRingingSound() { return ""; } string GetHitSound() { return ""; } string GetDestroyedSound() { return ""; } string GetWorkingSound() { return ""; } override void EEKilled(Object killer) { super.EEKilled(killer); TurnOff(); } override void EEHitByRemote(int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos) { super.EEHitByRemote(damageType, source, component, dmgZone, ammo, modelPos); PlaySoundSet( m_HitSound, GetHitSound(), 0, 0 ); } override void OnDamageDestroyed(int oldLevel) { super.OnDamageDestroyed(oldLevel); if (GetGame().IsClient()) { OnRingingStopClient(); if (oldLevel != -1) { PlaySoundSet(m_DestoryedSound, GetDestroyedSound(), 0, 0); } } } protected void OnRingingStartServer() { ActivateParent(); } protected void OnRingingStartClient() { PlaySoundSetLoop( m_RingingSoundLoop, GetRingingSound(), 0, 0 ); if (m_WorkingSound) { SEffectManager.DestroyEffect(m_WorkingSound); } } protected void OnRingingStopServer(); protected void OnRingingStopClient() { SEffectManager.DestroyEffect(m_RingingSoundLoop); } void SetAlarmInXMins(int in_mins) { int pass, hour, minute; GetGame().GetWorld().GetDate(pass, pass, pass, hour, minute); int mins12h = ConvertTimeToMins12h(hour, minute) + in_mins; float time01 = ConvertMins12hToAlarmHand01(mins12h); SetAlarmTimeServer(time01); Arm(); } float GetRingingDurationMax() { return RINGING_DURATION_MAX; } protected void SetupTimerServer() { m_TimerUpdate = new Timer(); m_TimerUpdate.Run(UPDATE_TICK_RATE , this, "OnUpdate", null, true); } protected void SetState(EAlarmClockState state) { m_State = state; SetSynchDirty(); } protected void Disarm() { SetState(EAlarmClockState.UNSET); } protected void Arm() { SetupTimerServer(); SetState(EAlarmClockState.SET); m_RingingDuration = 0; } protected void ActivateParent() { if (GetHierarchyParent()) { ItemBase parent = ItemBase.Cast(GetHierarchyParent()); if (parent) { parent.OnActivatedByItem(this); } } } protected void MakeRingingStart() { if (!m_TimerUpdate) SetupTimerServer(); SetState(EAlarmClockState.RINGING); OnRingingStartServer(); } protected void MakeRingingStop() { SetState(EAlarmClockState.UNSET); OnRingingStopServer(); } void TurnOnClient(); void TurnOffClient(); override void OnVariablesSynchronized() { super.OnVariablesSynchronized(); if (m_State != m_StatePrev)//state changed { if (m_StatePrev == EAlarmClockState.RINGING) { OnRingingStopClient(); } else if (m_State == EAlarmClockState.RINGING) { OnRingingStartClient(); } if (m_State == EAlarmClockState.SET) { if (m_StatePrev != -1 || IsInitialized()) { PlaySoundSet( m_TurnOnSound, GetToggleSound(), 0, 0 ); } if (GetWorkingSound()) { PlaySoundSet( m_WorkingSound, GetWorkingSound(), 0, 0, true ); } } else if (m_State == EAlarmClockState.UNSET) { if (m_StatePrev == EAlarmClockState.SET) { if (m_WorkingSound) { SEffectManager.DestroyEffect(m_WorkingSound); } if (m_StatePrev != -1 || IsInitialized()) { PlaySoundSet( m_TurnOnSound, GetToggleSound(), 0, 0 ); } } } m_StatePrev = m_State; } } //--------------------------------------------------------------------------------------------------------- //---------------------------------------------- Public methods ------------------------------------------- //--------------------------------------------------------------------------------------------------------- bool IsRinging() { return (m_State == EAlarmClockState.RINGING); } bool IsAlarmOn() { return (m_State == EAlarmClockState.SET); } void TurnOn() { Arm(); } void TurnOff() { if ( IsRinging() ) { MakeRingingStop(); } else { Disarm(); } m_TimerUpdate = null; } void SetAlarmTimeServer(float time01) { SetAnimationPhaseNow("ClockAlarm", time01); m_AlarmTime01 = time01; } }