using System;
using System.Collections.Generic;
using System.Linq;
using RPGCore.Core;
using RPGCore.Core.Objects;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events;
using UnityEngine;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
[Serializable]
[ObjectModule(
name: "[Status] Status",
description: "Attached to any implementation of BaseObject. Manages statuses and their effects. " +
"Create scriptable object "+nameof(StatusDefinitionSO)+" to make new status. " +
"For new effect create new implementation of "+nameof(BaseEffect)+"."
)]
public class StatusModule : ObjectModule
{
internal List statuses { get; private set; } = new();
[SerializeField] internal StatusUpdateType updateType;
/// Checks if any has .
public virtual bool IsControllable()
{
return !statuses.Any(status => status.definition.effects.Any(effect => effect is NotControllableEffect));
}
/// Checks if any active that uses is present.
public bool Check(StatusDefinitionSO definition)
{
return statuses.Any(status => status.definition == definition);
}
/// Adds new .
public Status Apply(StatusDefinitionSO definition)
{
var status = new Status(definition, this);
statuses.Add(status);
status.OnApply_Internal();
parent.events.Invoke(new StatusStartEvent { status = status, target = parent });
return status;
}
/// Removes given forcefully.
public void Remove(Status status)
{
if (status == null) return;
if (!statuses.Contains(status)) return;
status.OnRemove_Internal();
statuses.Remove(status);
parent.events.Invoke(new StatusRemoveEvent { status = status, target = parent });
}
/// Removes all es forcefully that uses .
public void Remove(StatusDefinitionSO definition)
{
GetStatuses(definition).ForEach(Remove);
}
/// Executed internally when status ending itself (by timer or effect).
internal void End(Status status)
{
if (status == null) return;
if (!statuses.Contains(status)) return;
status.OnEnd_Internal();
statuses.Remove(status);
parent.events.Invoke(new StatusEndEvent { status = status, target = parent });
}
/// Returns all active es.
public List GetStatuses()
{
return statuses.ToList();
}
/// Returns all active es that uses .
public List GetStatuses(StatusDefinitionSO definition)
{
return statuses.Where(status => status.definition == definition).ToList();
}
private void FixedUpdate()
{
if (updateType is StatusUpdateType.Automatically)
statuses.ToList().ForEach(status => status.UpdateTime_Internal(Time.fixedDeltaTime));
}
/// Update each status timer, decreases them by given seconds.
public void UpdateTime(float deltaTime)
{
if (updateType is not StatusUpdateType.Manually)
{
Debug.LogError($"Updating status time available only when: {nameof(StatusUpdateType)} = {nameof(StatusUpdateType.Manually)}");
return;
}
statuses.ForEach(status => status.UpdateTime_Internal(deltaTime));
}
}
}