using System; using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; using VOID.Generic.Objects.Abstract; using VOID.Generic.Objects.Abstract.Events; using VOID.Generic.Objects.Unit; using VOID.Generic.Status.Effect; namespace VOID.ScriptableObjects { [Serializable] [CreateAssetMenu(fileName = "Status", menuName = "GAME DATA/Status", order = 0)] public class BasicStatus : ScriptableObject { [Title("Nested into:")] [ShowInInspector] public AbstractObject forObject { get; private set; } [Title("Display")] [Required] public string displayName; [Required] public bool hidden = false; [Required] public Texture2D displayIcon; [Required, TextArea(10,10)] public string description; [Title("Effects list")] [Required, SerializeReference] public List effects = new(); [Title("Statuses interactions")] public List removes = new(); [Title("Duration")] public bool permanent = false; [MinValue(0)] public int durationInTurns; [ReadOnly] public int durationLeftInTurns; [ReadOnly] public float durationLeft; public event Action OnTimeDecrease; public void Init(AbstractObject forObject, UnitObject source = null) { this.forObject = forObject; effects.ForEach(effect => effect.Init(forObject, this, source)); } public void Apply() { if (permanent) durationInTurns = 1; // TODO: zdefiniować gdzieś ile czasu w sekundach to tura, na sztywno tutaj dodane 4 sekundy durationLeftInTurns = durationInTurns; durationLeft = durationInTurns*4f - 0.0001f; var otherStatuses = forObject.statusManager.GetStatuses(); var selfRemove = false; foreach (var otherStatus in otherStatuses) { if (otherStatus == this) continue; // if other status removes current one selfRemove = selfRemove || otherStatus.removes.Any(removeStatus => removeStatus.GetType() == GetType()); // if other status is removed by current one if (removes.Any(statusToRemove => statusToRemove.GetType() == otherStatus.GetType())) otherStatus.Cancel(); } if (selfRemove) { forObject.statusManager.RemoveStatus(this); return; } forObject.basicEvents.onStatusStart.Invoke(new StatusEvent { obj = forObject, status = this }); // Statuses already added via editor inspector need to be started this way foreach (var effect in effects) { effect.OnApply(); forObject.basicEvents.onEffectStart.Invoke(new EffectEvent { effect = effect }); } } public void End() { if (permanent) { durationLeftInTurns = 1; // TODO: zdefiniować gdzieś ile czasu w sekundach to tura, na sztywno tutaj dodane 4 sekundy durationLeft += durationInTurns * 4f; return; } foreach (var effect in effects) { effect.OnEnd(); forObject.basicEvents.onEffectEnd.Invoke(new EffectEvent { effect = effect }); } forObject.statusManager.RemoveStatus(this); forObject.basicEvents.onStatusEnd.Invoke(new StatusEvent { obj = forObject, status = this }); } public void Cancel() { effects.ForEach(effect => { effect.OnCancel(); forObject.basicEvents.onEffectEnd.Invoke(new EffectEvent { effect = effect }); }); forObject.statusManager.RemoveStatus(this); forObject.basicEvents.onStatusEnd.Invoke(new StatusEvent { obj = forObject, status = this }); } public void OnTurnSelfStart() { // TODO: zdefiniować gdzieś ile czasu w sekundach to tura, na sztywno tutaj dodane 4 sekundy durationLeftInTurns -= 1; durationLeft -= 4f; effects.ForEach(effect => effect.OnTurnSelfStart()); OnTimeDecrease?.Invoke(); } public void OnTurnSelfEnd() { effects.ForEach(effect => effect.OnTurnSelfEnd()); if (durationLeft <= 0f) End(); } public void DecreaseDurationRealTime() { // TODO: zdefiniować gdzieś ile czasu w sekundach to tura, na sztywno tutaj dodane 4 sekundy if (durationLeft%4f - Time.fixedDeltaTime < 0f) { effects.ForEach(effect => effect.OnTurnSelfStart()); effects.ForEach(effect => effect.OnTurnSelfEnd()); durationLeftInTurns -= 1; } OnTimeDecrease?.Invoke(); durationLeft -= Time.fixedDeltaTime; if (durationLeft < 0f) End(); } } }