Help Making Replication System

I’m making movesets for a game and one thing I always have troubles with is making a replication system for effects, my plan was to have 2 modules with the same function names. One will be for the effects itself and one will be for the server logic. Would this work or is there a better way to handle this? Here is an example:

--MODULE 1

local Effects = {}

function Effects.Move1()
  --... Effects will display here
end

return Effects

--MODULE 2
local Moveset = {}

function Moveset.Move1()
  --... Move logic goes here
end

return Moveset

Though its a good idea to seperate effects from the actual logic for a move usually it is done in one whole script. There really is no “good” way to handle effects its really just the same as the logic so its commonly put together in one script. You can still do it this way to understand it better but i’d reccomend handling most effects in a client script for less server resources spent and smoother effects.

My whole goal is to replicate the effects separately from the server. Do you recommend a way to achieve this?

To put it simply it seems like your way of just using a effect module and a logic module would be best for you. Though again i would render every effect through the client called through the server.

Heres a quick example of what i mean (NOT TESTED):

--//MODULESCRIPT\\--
local ClientEvent = game.ReplicatedStorage.EffectEvent -- Example
local Effects = {}

function Effects.Move1(Origin)
     ClientEvent:FireAllClients("Effect1") -- This doesn't have to be the same it could be certain or only players within range.
     --//RANGE EXAMPLE\\--
    for i,Player in pairs(game.Players:GetPlayers()) do
         if (Player.Character.HumanoidRootPart.Position-Origin.Position).Magnitude <= 400 then -- Within 400 studs of origin position.
            ClientEvent:FireClient(Player,"Effect1")
         end
    end
end
--//CLIENT\\--
local ClientEvent = game.ReplicatedStorage.EffectEvent -- Once again just a example remote, but the client has to see the same remote.
ClientEvent.OnClientEvent:connect(function(Var1)
    if Var1 == "Effect1" then
        -- EFFECT CODE --
    end
end)
1 Like

Would me putting the move module into repstorage cause any issues?
So here example Player attacks → server calls specific move → :FiresClient and runs the same code

Would I put all character moves in a place where both server & clients can access so the effects can be replicated?

Also, would I use RunService:IsClient() so only the client can run the vfx? Simple stuff like this is what makes me very confused about making replicated effects

Effects should be in ReplicatedStorage. Each client should be attached to an effect remote to trigger the corresponding effect. The easiest method is to have the client tell the server when it’s doing an action and then have the server tell all clients to play the effects.

The “smoother experience” method would have you do the event on the initiating client while telling the server with a timestamp, then the server telling the other clients about the effects and passing along the timestamp. In that case, depending on the type of visual, the animation can skip along as far as that time difference was. However, this method is more complicated obviously. I would recommend looking into rollback netcode for that:

Personally, I keep my Effects Modules in ReplicatedStorage and make sure the Move Logic is on the server.

So when a Player presses a keybind, I send a remote to the server to run the move logic on the server, then whenever I need to replicate a FX to the clients, just use :FireAllClients(ModuleName, EffectName, ... ) to replicate to them. That gets the Effect Module and Effect to replicate.

Ok so there is a lot of confusion here on my end and on your end so im gonna visualize it using studio. Your setup doesn’t have to be the same this is just how i did it.

image
First off this is what im talking about ^^^.

I’m gonna start off with the module script

local module = {}

module.Effects = function(Effect, Origin, Range)
	for i,Player in pairs(game.Players:GetPlayers()) do
		if (Origin.Position - Player.Character.HumanoidRootPart.Position).Magnitude <= Range then
			game.ReplicatedStorage.RemoteEvent:FireClient(Player,Effect)
		end
	end
end

module.Moves = function(Move, Origin, Range)
	if Move == "Punch2" then Range = 0 end -- If the move is punch2 then the effect will not be rendered.
	module.Effects(Move, Origin, Range) -- Feed the move info given into the effect function
	print("THIS IS WHERE THE LOGIC FOR HITBOXES AND DAMAGE GOES!!!")
end

return module

I don’t have two seperate modules but instead one in this example. One that will handle rendering effects and one that will handle the logic for everything else.

In the function “Effects” I make it so only people within a specified range will be able to see the effect through the RemoteEvent in ReplicatedStorage.

game.ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function(Var1,Var2)
	if Var1 == "Punch" then
		local Part = Instance.new("Part", workspace)
		Part.CFrame = Var2.CFrame
		print("CLIENT VFX")
	end
end)

This is the client script. It’s simple and doesn’t need much explaining needed. If the client recieves any argument like “Punch” then it will spawn a part on the Origin position also being the players humanoidrootpart who fired the module.

local MoveModule = require(game.ServerStorage.ModuleScript)

script.Parent.Activated:Connect(function()
	local Character = script.Parent.Parent
	print("I FIRED FROM A TOOL!")
	MoveModule.Moves("Punch",Character.HumanoidRootPart, 100)
end)

And this is the tool used to fired the module itself.
Together you should have something like this.


A part infront of the player who used the tool.
And on the server it should have nothing like this:

Hopefully this should clear up any confusion.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.