Overall, I have a setup for my game as current, and while I don’t feel like restarting to do anything to it, I do soon plan on creating a side project so that I can use the new knowledge I have in a new scope. Right now I’m in combat, but a lot of things will be setup similarly so I was just curious if this looks like a good setup.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local ActionContainer = ReplicatedStorage.Modules.ActionContainer
local Shared = ReplicatedStorage.Modules.Shared
local BridgeNet = require(ReplicatedStorage.Libraries.BridgeNet2)
local Constants = require(ReplicatedStorage.Modules.WhitelistedInputs)
local ActionHandler_C = {
["CombatActions_C"] = require(ActionContainer.CombatActions_C),
["MovementActions_C"] = require(ActionContainer.MovementActions_C)
}
local function FuncSender(InputData : { })
local Actionnare, CurrentAction
CurrentAction = function()
for ActionsIndex, PickedClass in pairs(ActionHandler_C) do
if type(PickedClass) == "table" then
if PickedClass[InputData.Key] then
Actionnare = PickedClass[InputData.Key]
return require(ActionContainer[ActionsIndex].Functions_C)[Actionnare["Name"]] -- Directs me to the Action for a certain Action Subset, whether being Movement Actions or Combat Actions
end
end
end
end
local Action = CurrentAction()
Action()
end
local InputClient = {}
function InputClient.FunctionSender(Input: InputObject, GameProcesssedEvents : BoolValue )
if GameProcesssedEvents then return end
if not table.find(Constants.WhitelistedUserInputTypes, Input.UserInputType) then return end
if not table.find(Constants.WhitelistedKeybinds, Input.KeyCode) then return end
FuncSender(({
Type = Input.UserInputType,
State = Input.UserInputState,
Key = (Input.KeyCode == Enum.KeyCode.Unknown and Input.UserInputType or Input.KeyCode)
}))
end
return InputClient
Client-Sided setup, explaination commented on what the random function is doing there
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local VFXModules = ReplicatedStorage.Modules.VFXModules
local CombatActions_CM = ReplicatedStorage.Modules.Shared.CombatActions_CM
local ClientVFX = ReplicatedStorage.RE.ClientVFX
local BridgeNet = require(ReplicatedStorage.Libraries.BridgeNet2);
local PlrControllerModule = require(ReplicatedStorage.Modules.Client);
local HitboxModule_C = require(CombatActions_CM.HitboxModule_C);
local ClientSideBehavior = require(ReplicatedStorage.Modules.ClientSideBehavior)
local BaseHitboxTable = {}
BaseHitboxTable.OriginalPart = nil
BaseHitboxTable.HitboxSize = Vector3.new(3.5, 4.25, 4)
BaseHitboxTable.Duration = nil
--local ClientVFX = BridgeNet.ClientBridge("VFXController")
local VFXFunc = function(seen)
--[[if WrapperPlayer:GetState(seen, "P-Blocking") then
Animation:AdjustSpeed(0)
end]]
local MainModuleBase = VFXModules:FindFirstChild("CombatVFXBegin")
local RequiredModule = require(MainModuleBase)
RequiredModule["HitReaction"](seen)
return seen:FindFirstChild("HumanoidRootPart")
end
UserInputService.InputBegan:Connect(PlrControllerModule.FunctionSender)
UserInputService.InputEnded:Connect(PlrControllerModule.FunctionSender)
What actually happens on the client
VFXFunction is primarily for the reactive VFX system I’ve implemented.
Afterwards, when the Action is found and done, the client side functionality is done over here
, in the Functions script, and most function are setup like this
Server is very similar expect the fact that it instead carries the functionality and introduces the State System which I’m not completely sure is needed to be shown here, but I will show the server-side of things, and if you’d allow me I could go further in depth about the state system.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Modules_S = ServerStorage.Modules
local ClientRemote = ReplicatedStorage.RE.ClientRemote
local Shared = ReplicatedStorage.Modules:WaitForChild("Shared")
local Things = require(Shared.DataHandler.playerdataHandler)
local BridgeNet = require(ReplicatedStorage.Libraries.BridgeNet2)
local BehaviorControl = require(ServerStorage.Modules.BehaviorControl)
local ActionHandler_Server = ServerStorage.Modules.ActionHandler_S
local CA_S = require(Modules_S.ActionHandler_S.CombatActions_S)
local MA_S = require(Modules_S.ActionHandler_S.MovementActions_S)
local ActionHandler_S = {
["CombatActions_S"] = CA_S;
["MovementActions_S"] = MA_S;
}
function ActionHandler_S:Init(Params: {})
local Action, CurrentAction
Action, CurrentAction = {}, function()
for Index, Actions in pairs(ActionHandler_S) do
if type(Actions) == "table" then
if not Actions[Params.Input] then continue end
return require(ActionHandler_Server[Index])[Params.Input]
end
end
end
local Actionnare = CurrentAction()
Actionnare(Params)
end
--local ClientRemote = BridgeNet.ServerBridge("ClientRemote")
ClientRemote.OnServerEvent:Connect(function(Player, Params)
ActionHandler_S:Init(Params)
end)
would appreciate the feedback so much, thank you.