This commit is contained in:
2026-04-25 23:37:10 +02:00
commit 19d6bd934a
476 changed files with 9198 additions and 0 deletions
@@ -0,0 +1,28 @@
using System;
using RPGCore.Core.Objects;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
/// <summary>
/// Extend this to make custom effect that can be used by <see cref="StatusDefinitionSO"/>.
/// </summary>
[Serializable]
public class Effect
{
public BaseObject obj { get; internal set; }
public Status status { get; internal set; }
internal void OnApply_Internal() => OnApply();
internal void OnEnd_Internal() => OnEnd();
internal void OnRemove_Internal() => OnRemove();
protected virtual void OnApply() {}
protected virtual void OnEnd() {}
protected virtual void OnRemove() {}
protected void EndStatus()
{
status.statusModule.End(status);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 930348137c8044d5bbbb64dcf54ae953
timeCreated: 1772974582
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3c6b215386e14a38afa090853d1e7e84
timeCreated: 1772974553
@@ -0,0 +1,6 @@
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects
{
public class NotControllableEffect : Effect
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dccc3743dc3e4a67b738d8ac3c8e8347
timeCreated: 1773175390
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 74fcfad35dc74866831cc42cdcfbbe44
timeCreated: 1764884979
@@ -0,0 +1,14 @@
using RPGCore.Core.Objects;
using RPGCore.ObjectModules.EventObjectModule;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
{
/// <summary>
/// Executed when <see cref="Status"/> ends normally - by timer or by <see cref="Effect"/>.
/// </summary>
public class StatusEndEvent : BaseEvent<BaseObject>
{
public BaseObject target;
public Status status;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a41609619e254d8a98ce6805b3d3edf8
timeCreated: 1762636552
@@ -0,0 +1,14 @@
using RPGCore.Core.Objects;
using RPGCore.ObjectModules.EventObjectModule;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
{
/// <summary>
/// Executed when <see cref="Status"/> ends forcefully - by something else than timer or <see cref="Effect"/>.
/// </summary>
public class StatusRemoveEvent : BaseEvent<BaseObject>
{
public BaseObject target;
public Status status;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c16881cb8c65431b97b97cd8956ed455
timeCreated: 1773264987
@@ -0,0 +1,14 @@
using RPGCore.Core.Objects;
using RPGCore.ObjectModules.EventObjectModule;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
{
/// <summary>
/// Executed when <see cref="Status"/> is applied.
/// </summary>
public class StatusStartEvent : BaseEvent<BaseObject>
{
public BaseObject target;
public Status status;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e35d6b98b192496ea8853d49de0b0790
timeCreated: 1762636360
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
public sealed class Status
{
public StatusDefinitionSO definition { get; private set; }
public StatusModule statusModule { get; private set; }
public float timeRemaining { get; private set; }
public List<Effect> effects { get; private set; }
internal Status(StatusDefinitionSO definition, StatusModule statusModule)
{
this.definition = definition;
this.statusModule = statusModule;
timeRemaining = definition.time;
effects = definition.effects.Select(e =>
{
var copy = JsonUtility.FromJson<Effect>(JsonUtility.ToJson(e));
copy.obj = statusModule.parent;
copy.status = this;
return copy;
}).ToList();
}
internal void UpdateTime_Internal(float deltaTime)
{
if (definition.permanent) return;
timeRemaining -= deltaTime;
if (timeRemaining <= 0) statusModule.End(this);
}
internal void OnApply_Internal() => effects.ForEach(effect => effect.OnApply_Internal());
internal void OnEnd_Internal() => effects.ForEach(effect => effect.OnEnd_Internal());
internal void OnRemove_Internal() => effects.ForEach(effect => effect.OnRemove_Internal());
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f4785e633dfa471082b97be16fb90522
timeCreated: 1767359048
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using RPGCore.Core.Objects;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
using RPGCoreCommon.DynamicValues;
using RPGCoreCommon.Helpers.CustomTypes;
using UnityEngine;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
[Serializable]
[CreateAssetMenu(menuName = "RPG Core/Status")]
public class StatusDefinitionSO : ScriptableObject
{
[Header("Connected to:")]
[SerializableType(typeof(BaseObject), allowAbstract: true)] public SerializableType forType;
[Header("Display")]
public string displayName;
public bool hidden;
public Texture2D displayIcon;
[DynamicValue(DynamicValueType.ByDynamicTypes)] public DynamicValue description;
[Header("Duration")]
public bool permanent;
[Min(0)] public float time;
[Header("Effects")]
[SerializeReference] public List<Effect> effects = new();
private void OnValidate()
{
description.RemoveDynamicTypes();
description.SetDynamicType("object", forType);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9e1852531ea144a181ad7f23cfa40991
timeCreated: 1762633180
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RPGCore.Core;
using RPGCore.Core.Objects;
using RPGCore.ObjectModules.EventObjectModule;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events;
using UnityEngine;
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
[Serializable]
[RequireComponent(typeof(BaseObject))]
public class StatusModule : ObjectModule<BaseObject>
{
internal List<Status> statuses { get; private set; } = new();
[SerializeField] internal StatusUpdateType updateType;
/// <summary>Checks if any <see cref="Status"/> has <see cref="NotControllableEffect"/>.</summary>
public virtual bool IsControllable()
{
return !statuses.Any(status => status.definition.effects.Any(effect => effect is NotControllableEffect));
}
/// <summary>Checks if any active <see cref="Status"/> that uses <see cref="StatusDefinitionSO"/> is present.</summary>
public bool Check(StatusDefinitionSO definition)
{
return statuses.Any(status => status.definition == definition);
}
/// <summary>Adds new <see cref="Status"/>.</summary>
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;
}
/// <summary>Removes given <see cref="Status"/> forcefully.</summary>
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 });
}
/// <summary>Removes all <see cref="Status"/>es forcefully that uses <see cref="StatusDefinitionSO"/>.</summary>
public void Remove(StatusDefinitionSO definition)
{
GetStatuses(definition).ForEach(Remove);
}
/// <summary>Executed internally when status ending itself (by timer or effect).</summary>
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 });
}
/// <summary>Returns all active <see cref="Status"/>es.</summary>
public List<Status> GetStatuses()
{
return statuses.ToList();
}
/// <summary>Returns all active <see cref="Status"/>es that uses <see cref="StatusDefinitionSO"/>.</summary>
public List<Status> 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));
}
/// <summary>Update each status timer, decreases them by given seconds.</summary>
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));
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0ce33596b3d549c7b86629c1d1e6532c
timeCreated: 1762633163
@@ -0,0 +1,8 @@
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
{
public enum StatusUpdateType
{
Automatically,
Manually,
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5585782dbfae4ea6bc631cb2038e51f1
timeCreated: 1773176713