Alright, I need to quickly update this, because really the issue isn’t up to date.
In specific the Enum.KeyCode.F, after the cooldown is done, something has the random chance of going for a further time before working again, which in turn allows this
if not table.find(Constants.WhitelistedKeybinds, Input.KeyCode) then print(Input.KeyCode) return end
To become bypassed, but I have no understanding as to why.
Now the issue is sincerely confusing, because it’s more of a logic issue than a minor spelling.
I will now provide all of the scripts which are in use, but be aware, these scripts are pretty long, the Cooldown Script being the longest.
Client - Local Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local PlrControllerModule = require(ReplicatedStorage.Modules.Client)
UserInputService.InputBegan:Connect(PlrControllerModule.FunctionSender)
UserInputService.InputEnded:Connect(PlrControllerModule.FunctionSender)
Client - Module Script
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 Held = false
local ActionHandler_C = {
["CombatActions_C"] = require(ActionContainer.CombatActions_C),
["MovementActions_C"] = require(ActionContainer.MovementActions_C)
}
local function FuncSender(InputData : { })
local Actionnare, CurrentAction
CurrentAction = function() -- method of directly executing one of the actions
for ActionsIndex, PickedClass in pairs(ActionHandler_C) do
if type(PickedClass) == "table" then -- Checks the table whether it's an actual table or not
if PickedClass[InputData.Key] then
Actionnare = PickedClass[InputData.Key] -- Gets the key of the specific action
print(Actionnare)
return require(ActionContainer[ActionsIndex].Functions_C)[Actionnare["Name"]] -- Play the Action from the Functions (They are all named this for convenience
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 print(Input.KeyCode) return end
FuncSender(({
Type = Input.UserInputType,
State = Input.UserInputState,
Key = (Input.KeyCode == Enum.KeyCode.Unknown and Input.UserInputType or Input.KeyCode)
}))
print(Input.KeyCode == Enum.KeyCode.Unknown and Input.UserInputType or Input.KeyCode)
end
return InputClient
Combat Actions Homebase
local Functions = require(script.Functions_C)
local CC = {
[Enum.UserInputType.MouseButton1] = {Name = "M1", Cooldown = .15};
--[Enum.UserInputType.MouseButton2] = {};
[Enum.KeyCode.F] = {Name = "Blocking", Cooldown = .5};
--[Enum.KeyCode.C] = {Name = "Dodging", Cooldown = 1.5};
["W + M1"] = {Name = "Running Punch", Cooldown = 5},
}
return CC
Actual Combat Actions
-- Private Variables
local ReplicatedStorage = game:GetService("ReplicatedStorage");
local Players = game:GetService("Players");
local UserInputService = game:GetService("UserInputService");
local Shared = ReplicatedStorage.Modules.Shared;
local BridgeNet = require(ReplicatedStorage.Libraries.BridgeNet2);
local Animation_C = require(Shared.CombatActions_CM.Animation_C);
local CoolDownHandler = require(Shared.CombatActions_CM.Cooldowns);
local WrapperPlayer = require(ReplicatedStorage.Modules.Shared.PlayerModules.WrapperPlayer_C)
local Player = Players.LocalPlayer;
local Character = Player.Character or Player.CharacterAdded:Wait();
local Humanoid = Character:WaitForChild("Humanoid");
local ClientRemote = BridgeNet.ClientBridge("ClientRemote")
local Count = 0;
local Held = false;
local Animation, Length;
local CombatActions_C = {
["M1"] = function(Parameters)
if CoolDownHandler:CheckCD(Player, {"M1", "M1StringFinish"}) == false and not WrapperPlayer:CheckStateActivities(Player, "Attacking") then
if Count >= 4 then
Count = 1
else
Count += 1
end;
if Count == 4 then
CoolDownHandler:CreateCooldown(Player, "M1StringFinish", Length * 5)
end;
Animation, Length = Animation_C.getmultipleAnimation(Character, Count, Animation_C.CombatAnimations);
Animation:Play()
CoolDownHandler:CreateCooldown(Player, "M1", Length * 1.5)
Animation:GetMarkerReachedSignal("HitboxSummon"):Connect(function()
ClientRemote:Fire({Input = "M1", Player = Player, Count = Count, Length = Length})
end);
end
end;
["Dodging"] = function(Parameters)
ClientRemote:Fire({Input = "Dodging", Player = Player})
end;
["Blocking"] = function(Parameters)
if UserInputService:IsKeyDown(Enum.KeyCode.F) and (not CoolDownHandler:CheckCD(Player, {"Blocking"})) == true then
ClientRemote:Fire({Input = "Blocking", Player = Player, Held = true})
end
if not UserInputService:IsKeyDown(Enum.KeyCode.F) and (not CoolDownHandler:CheckCD(Player, {"Blocking"})) == true then
ClientRemote:Fire({Input = "Blocking", Player = Player, Held = false})
CoolDownHandler:CreateCooldown(Player, "Blocking", 1)
end
end,
}
return CombatActions_C
Beware- The longest script - Cooldown Module
local Debris = game:GetService("Debris")
local CreateInstanceValue = true
local CooldownModule = {}
local CooldownHandler = {
Cooldowns = {}
}
local clocky = os.clock
local function CreateNewValue(Name, Time)
local StringValue = Instance.new("StringValue")
StringValue.Name = Name
StringValue.Value = "Cooldown"
StringValue.Parent = script
if Time then
Debris:AddItem(StringValue, Time)
end
return StringValue
end
function CooldownModule:CreateCooldown(Player, Name, Length)
local IndividualCharacterCD = CooldownHandler.Cooldowns[Player]
if not IndividualCharacterCD then
CooldownHandler.Cooldowns[Player] = {}
IndividualCharacterCD = CooldownHandler.Cooldowns[Player]
end
local RealCD = IndividualCharacterCD[Name]
if not RealCD then
IndividualCharacterCD[Name] = {}
RealCD = IndividualCharacterCD[Name]
end
local CDProperties = {}
CDProperties[1] = Length
CDProperties[2] = clocky()
CDProperties[3] = CreateInstanceValue and CreateNewValue(Player.Character.Name .. "_" .. Name, Length) or nil
local CooldownPos = (#RealCD + 1)
table.insert(RealCD, CooldownPos, CDProperties)
end
function CooldownModule:CheckCD(Player, Name)
Name = typeof(Name) == "string" and {Name} or Name
if CreateInstanceValue then
for _, v in ipairs(Name) do
if script:FindFirstChild(Player.Character.Name .. "_" .. v) then
return true
end
end
end
local IndividualCharacterCD = CooldownHandler.Cooldowns[Player]
if not IndividualCharacterCD then
CooldownHandler.Cooldowns[Player] = {}
return false
end
for i = 1, #Name do
local CooldownName = Name[i]
local Index = IndividualCharacterCD[Name]
if Index then
for i, v in pairs(Index) do
if clocky() - v[2] > v[1] then
return true
else
table.remove(IndividualCharacterCD[CooldownName], i)
IndividualCharacterCD[CooldownName] = nil
end
end
end
end
return false
end
return CooldownModule
See, the issue is that I cannot pinpoint the main issues possibly origins, even though I don’t find my script extremely confusing.