How would i implement a modular status effect system?

I highly recommend ECS. However, on a side note you could achieve the something with OOP as long as you use components, one module script only does one thing with a single responsibility principle.

Here are some code examples to illustrate

Entity creation of player with pure data

local npcEntity = world:Entity()
npcEntity :Set(HumanoidComponent(Instance.new("Humanoid")))
npcEntity:Set(PoisonComponent(5))
--You can add infinite amounts of components hence modular
npcEntity:Set(StunComponent(10))
npcEntity:Set(SpeedBuffComponent({value = 5, duration = 30}))

local entityDictionary = {}
entityDictionary[npcModel] = npcEntity --keep track of model --> entity
--hit detection -->part-->model-->dictionary --> Entity object
--remember to delete after model is destroyed, ancestor is set to nil should be good enough

System detects and tracks components, ex: status effect every frame doing poison damage, one module script called PoisonSystem.lua, easily find and track this system in charge of only doing one thing

PoisonSystem module script
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Components = require(script.Parent.Parent.Components)
local PoisonComponent = Components.PoisonComponent
local HealthComponent = Components.HealthComponent

local ECS = require(ReplicatedStorage.Shared.ECSFolder.ECS)

local World, System, Query, Component = ECS.World, ECS.System, ECS.Query, ECS.Component

--only thing that matters is if an entity is poisoned and has health
--transform is kinda equal to RunService heartbeat
local PoisonDamageSystem = System("transform", 1, Query.All(PoisonComponent, HealthComponent))

function PoisonDamageSystem:Update(Time)
    for i, entity in self:Result():Iterator() do
        local health = entity[HealthComponent].value
local poisonDamageRate = entity[PosionComponent].value
        entity:Set(HealthComponent(health - poisonDamageRate*))
    end
end

return PoisonDamageSystem

Another system is in charge of purely poison visual effects

Summary
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Components = require(script.Parent.Parent.Components)

local ECS = require(ReplicatedStorage.Shared.ECSFolder.ECS)

local World, System, Query, Component = ECS.World, ECS.System, ECS.Query, ECS.Component

local PoisonVisualEffects = System("transform", 1, Query.All(PoisonComponent, ModelComponent))

--When a new entity is created with a char model, and poisoned
function PoisonVisualEffects:OnEnter(Time, entity)
    local model = entity[ModelComponent].value
    
    --add particles to model
end

return PoisonVisualEffects

And you add drop on demand components.

npcEntity:Unset(PoisonComponent)
7 Likes