#Input handling issue
1 messages Β· Page 1 of 1 (latest)
code ^^
as you might notice, it allows for parries in between the attacks
im aware of the fact that i have the attack attribute ( skilldebounce ) to be set to true for the attack duration - 0.1, but still i think it should not be happening
(yes i did use ai to figure out where the fuck the problem is... no success tho) π³οΈ
what is physical resistance π
yeah
its an input handler
which
sucks
cuz ofc i had to use ai to try to fix the issue
which it didnt
@marble willow
im checking if the action is valid
nope
then how did you make this client sided
you need to rollback the ability
or the action
if client predicts wrong
like what happens if I activate an ability when server saw me as stunned
look, on the client i set ClientAction
on server is SkillDebounce
it might be cuz the block code is old ( block client )
block server:
input handlers are not usually meant to do cooldown but ok
aside from that
whats the issue
they dont do cooldown
they do an additional check
as you might see in the clip
you can parry
mid holding m1
if you spam F
i dont want to add blocking cd
nor adding fake delay to make blocking just not show up
huh?
do you ever get out of m1 state
yeah when you do
you can parry
simple
nothing looks out of ordinary here
--// Main Task Thread
Tasks = task.spawn(function()
Packets.ReplicateRemote:Fire(
{Skill = "Punch", Function = "Effects"},
"M1",
character,
module.Combo[character]
)
--task.delay(Prehit - Sync, function()
-- module.PreHit(player, character)
--end)
task.delay(Hitreg - Sync, function()
module.Hit(player, character)
end)
task.delay(
AnimManager:GetLength(character, Animation) - 0.07- Sync,
function()
module.End(player, character)
stunConnection:Disconnect()
end
)
end)
--// Combo Reset Timer
task.spawn(function()
local oldCombo = module.Combo[character]
task.wait(module.ResetCD)
if oldCombo == module.Combo[character] then
module.Combo[character] = 0
end
end)
--// Auto Reset at 5
if module.Combo[character] == 5 then
module.Combo[character] = 0
return
end
thats a snippet of the punch code
( m1 )
holy threads π
i like threads
start using animation events what the hell
i do use them
but not in all cases
cuz
let me explain
what i do is
i play anim on client
and send 1 event to the server
to start the skill on server ( with server checks )
and what it does, is get the time to each animation event
of a specific animation
and i use delays to match the client animation
i do this so i wont have to send a ton of events
while keeping it synced
if an exploiter starts the skill
it will only play the animation
and nothing else is going to continue
which means it wont affect anyone else
using ma module
that i actually coded 80% of it
which im proud of
π«‘
i had a get all animation events function
but i removed it for a certein reason i dont even remember
you know that your game can fail fully
if the service goes down
happened to me once
wdym?
outage lasted 6 hours
i never have any issue
there's a chance
had*
there's a chance
chance of what π
what could happen?
the only thing that isnt failsafe is when you dont init the system
and then ofcourse it break
breaks*
my grammer sucks today
KeyframeSequenceProvider can be down
and when it is
your whole game fails
Im not even joking
really.?
yup
tf is roblox doing
happened to me once
giving a feature
I had to scrap the entire system
yeah i get it
it's crazy
roblox should have a feature to preload this shit
and publish it with the game itself
like wtf is clipproviderservice
or keyframesequenceprovider
I mean
and
there's a chance
i have to retry to make the same game
a very slim one
for the 12th time
I would say
just keep going with this
and then make a preload system
like run a script to preload them as attributes
or smt like that
so you dont need to trash the entire game
only this part
how tf am i supposed to do that when im struggling to
make a working m1 and block system
π
after the outage was over
Just give him cooldown manager
I donβt use the feature anymore..
I use cooldown manager
good good
oh
the one I sent you
ye ye
--!strict
export type CooldownManager = {
Cooldowns: {[string]: {Duration: number, Start: number}},
Destroyed: boolean,
SetCooldown: (self: CooldownManager, name: string, duration: number) -> (),
IsOnCooldown: (self: CooldownManager, name: string) -> boolean,
ResetCooldown: (self: CooldownManager, name: string) -> (),
ClearCooldowns: (self: CooldownManager) -> (),
Destroy: (self: CooldownManager) -> (),
}
local CooldownManager = {}
function CooldownManager.new(): CooldownManager
local self: CooldownManager = {} :: any
self.Destroyed = false
self.Cooldowns = {}
self.SetCooldown = function(self: CooldownManager, name: string, duration: number)
assert(not self.Destroyed, "CooldownManager already destroyed.")
assert(duration >= 0, "Cooldown can't be negative.")
self.Cooldowns[name] = {Duration = duration, Start = os.clock()}
end
self.IsOnCooldown = function(self: CooldownManager, name: string): boolean
assert(not self.Destroyed, "CooldownManager already destroyed.")
local cd = self.Cooldowns[name]
if not cd then return false end
local delta = os.clock() - cd.Start
if delta >= cd.Duration then
self.Cooldowns[name] = nil
return false
end
return true
end
self.ResetCooldown = function(self: CooldownManager, name: string)
assert(not self.Destroyed, "CooldownManager already destroyed.")
if not self.Cooldowns[name] then return end
self.Cooldowns[name].Start = os.clock()
end
self.ClearCooldowns = function(self: CooldownManager)
assert(not self.Destroyed, "CooldownManager already destroyed.")
self.Cooldowns = {}
end
self.Destroy = function(self: CooldownManager)
self:ClearCooldowns()
self.Destroyed = true
end
return self
end
return CooldownManager
ehm
ts
im doing the same thing
ye I know
he's talking about smt else
he had an integrated system for cooldowns that went through the input pipeline
it was pretty weird
so I suggested keep it simple
im still not like hundred percent satisfied with where im binding my inputs but it works
ay
chill
im here to cry about how cooked im
and not to hear
how cooked YOU are
Nah im taking it over
π
man
im suffering from severe deep fryness that cant be fixed 
bro
its my
idk
12th attempt
of doing the same typa game
and i scrapped
every single. ONE!
i thought this system was pretty decent π
trust combat is hard to get right
especially client combat
client combat is harder
yeah
ik
i did a fully server one
but
its
ewhhhhhhhh
like
it didnt feel responsive
thats why i want to play the animation on client
and then let the server sync with the client ( after fact checking that its possible to use the skill or smth )
I mean bro
deepwoken is server combat
deadass
so is jjs
yeah
but it sucks
in terms of responsiveness
if u are above 100 ping
what about jjs?
same
I know a few games
that did client combat
but the problem is
that feels bad too π
because now the updates are delayed
instead of inputs
your hits get constantly rolledback
there's no perfect solution
there's decisions
each to their own
man
idk
like
this whole time
ive been in the developing community
ive never succeeded to make a single viable combat system
and its been 4 years
since i started touching scripting
):
Give up give up give up
wha thappened is it a race condition
nah gng dont give up
keep it up ur doing great
i mean
is there a point
to continue working of a broken system?
I just seems like he can block during in between m1 state switches
tis could be a no.1 ccu game if u keep at it
like i do have a semi reliable base framework
yeah
how are you gon fix it
then
my games broken all the time
do i give up
no
what u need to do is make sure they only set 1 state at a time like roblox's humanoids
um
make a system where anytime a state is set an ongoing state is disabled
i guess
but wouldnt it ruin fluidity
cuz my system is attribute based
idk what to do
like
like bro
I HAVE ABSOLUTLY NO IDEA
dont overthingk it
when m1 no block
when block no m1
just do that
simples
do u want my state handler
fym bruh
π
I thought you were already doing that
why do states exist then
just run the code
and let everyone fight over
for the race condition
it might help but i think in too deep in...
--Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--Classes
local StateHandler = {} :: Global.statehandler
--Functions
local function UnsetCurrent(statehandler: Global.statehandler, ...)
if statehandler.CurrentState then
if statehandler[statehandler.CurrentState].onUnset then statehandler[statehandler.CurrentState].onUnset(...) end
statehandler.CurrentState = nil
end
end
--Class
local function <states>newStateHandler(states: {{Name: string, onSet: () -> (), onUnset: () -> ()}})
local meta = table.clone(StateHandler)
meta.__index = meta
meta.CurrentState = nil
meta.Changed = Global.Event()
local self = Global.Metatable(meta)
for _, state in states do
self[state.Name] = {onSet = state.onSet, onUnset = state.onUnset}
end
return self
end :: ({{Name: string, onSet: () -> (), onUnset: () -> ()}}) -> Global.statehandler)
function StateHandler:Set(state, ...)
if self.CurrentState == state then return end
if state == nil then
UnsetCurrent(self, ...)
self.Changed:Fire(nil)
return
elseif not self[state] then
return
end
UnsetCurrent(self, ...)
self.CurrentState = state
if self[state].onSet then self[state].onSet(...) end
self.Changed:Fire(state)
warn("Set state to: ", state)
end
return newStateHandler
ok there i think its fine for everyboy and not just global now
oops there
i think atp ill rework the whole system
the only thing that works great for me
and actually re-useable
i clone the metatable here to store the currenstate and event deep inside the metatable so u can loop through the states
is the client to server module communication
if u want change that
do u like it bc it scares u or bc u think u'll save 1 second accumilatvly before the universae ends
cuz at the end i get into oop soup
that makes me regret my existance
well either way just use whatever uwant
to make it t owhere when 1 thing is set
another thing is unset
so u can only hv 1 thing set a time
thats ur problem u can use whatever solutio u nwat
mine is good
no metatables
still OOP
but partial OOP
as long as i dont have 3 thousend self constants π
brother no other way to make an object unfortunately π
also
I need to update cleaner
and state machine
I added functions to cleaner
is cleanr like janitor
a long time ago u said janitor sucks and id rather just have a destroy in my object
you know what you clean
I still do that
I just do that in batch
dang my memory so good
whats that mean
janitor has functionality to partially clean
which is what Im against
like everything gets tangled up
- janitor auto searches stuff
wth is partially clean...
what I did is ajust a bucket
cleaning only 1 thing or few things

yea this also works
i just do Global.Utility:DisconectAll and Global.Utility:DestroyThreads when i need
oh wait a min
I just got tired of making .Threads .Connections .Instances
everytime
and I made a bucket for them
this is still wrong gng
what happen
oh crap
you shouldn't use coroutine.cancel
that is cooked
a question
i think i used that bc it didnt error
or cause an error
π π
if u do somn
bro that errors is telling you smt important
im going to have a holiday from the 3rd of april to the 13th of april
that is really bad news π
congrats
and improve
wdm imrpove
no i forgot exactly waht it was but it had to do with it not erroring if it was in a state or somn proabaly
ask sinek i have never really made a proper proper combat system
lemme swit h to native one tho
wait what if its a running thread bro?
if i did while true do or osmn and i store it inside of it wouldn it be in a running state
@marble willow
I only made server combat
gng
Im sorry
i mean
also this doesnt check if ur trying to cancel fro the thread ur on
bro
if i made a server sided combat
running thread can't be suspended
π
bro like
ur game isnt fully broken its just this part that doesnt work
if u get cut u put bandaid not cut of limb
jus take some time off go get white monster or somn and come back
i dont drink energy drinks
thats the problem
@abstract jetty i have an example
why i didnt go with a single state machine
cuz
for example you are blocking
you need to keep track of posture.
and how can you access posture if not thru a global data place
well typically the way u'd have this setup is like how roblox has services and under that methods
for exmaple u'd have Players -> Player -> Charcter
in my game i have the same thing
did you see my implementation
Global -> Players -> Player -> Character
of the state machine
tahts how i handle my states
sinek has a global state machine tho
so u could use his instead
I fix this
by letting users define a context
it's a generic type
so it becomes whatever you pass in
that context will hold your data
so context: Blocking, Data = {Posture = num}
I have OnEnter OnUpdate and OnExit per state
what
context is literally an value you want
and the state has context
i dont understand
I have a main combat handler that I pass into my states
I have all the combat state there
and combat functions
it looks like this
OnEnter = function(stateMachine, combatHandler)
print(combatHandler.Posture)
end
there is StateCache which is cleaned up on transition
and there is Cache
which is persistent
even across states
i dont see how i can implement it
@marble willow can you help me make a combat system from ground up?
I mean ey bro Im literally giving you exactly how I do it
I don't have that much time
π
unfortunately
man
I barely have time for my self
i have a holiday from the 3rd of april till the 13th
i just dont want to waste it
like i want to make something actually good
that can be scaled
How about u make friends
I have a question
i got friends
but
none are intrested
in coding ands tuff
Acc ill dm u
ye sur
and asking random people to work with me on a game
Bc they cool
Ull figure it out one day beo but u gotta be willing to fail and fail
ive failed more than 12 times trying to make combat
thats why asking for help π
mainly just think about a system where when they are punching they cannot block
only 1 at a time
yeah this can be achieved without switching to a state machine
the thing is
that the skilldebounce ( aka being inside the m1 )
is 0.1 less then the full attack animation
making it so if you perfect spam block while holding m1
u can sneak in a parry
@abstract jetty /block
waht
why
u have to make it to where at the beginning of the punch
u set state to punching
and then if they try to block its not blocking anymore
u can set states regardless of animation
dealing damage doesnt have to be tied to state
idk what u mean
look
if i can do another m1
after the first m1 animation
ah
so
i basicly make it so it will animation merge
the previous m1
with the new one
make it feel smoother\
oh
u can have a queue system with priority or somn if u want
wait what i dont understand
holding m1 to spam m1 is not made this way
or tbf
if you are in m1
you shouldn't do anything at all
it doesn't make sense
then you have a bug bro π
check the code that does parry
and see if it's checking against m1
or any state at all
like i said earlier
its because i set the skilldebounce ( in action state )
Im not getting
for the lenght of the attack - 0.1
meaning that in that 0.1
you can sneak
a parry
why then
why not do it for the duration of the attack
- why are your inputs controlling state transition rules
cuz
they arent?
i dont set states on client
they are from what you are describing
unless client action
animations on client
but
the stuff
is on server
like i said
i time
the server actions to the animations event
I still don't get it you are allowing 0.1 second window
and mad that the window exists
at the same time
ah
let me explain
i made that window
to allow animation merging between m1s
so they transition smoothly
well sounds like that's the thing that needs to be fixed
sounds like the root issue
then how can i make the animations transition better?
I really don't get it gng
do you understand there's animation
and the actual m1 state
yes
the actual state can be smaller than the animation duration
what you do is
when they do smt like block when the m1 satate is over
you stop the m1 anim
lemme record in a sec
i tested it without that window
and it still allowed for the same thing
but it was slower
@marble willow
just make the m1 state exist for as long u need this issue to not occur
and animations have this thing u can pass into it called fadetime
maybe that might help u
wdmy allow bro
I dont get it bruh
animations and states dont have to be tied together
you have an m1 state that's active for x amount of time
if that block happens in that x
you haev a bug
if it happens out of that x
that's intended
ye
it's so simple
yup
maybe your design is broken
well intended or not based off ur code thats what ull get
why just make state duration gbigger
and now the m1s feel delayed
due to m1s having a window in between them
set fadetime to be higher in ur animation when u play it
when u do animationTrack:Play(fadeTime) u can pass fade time into it
heres the properties u can pass
this looks pretty goo dbtw
na
the bug is still present
ill prolly waste another 20 hours reworking the system to work with a 1 state system
@marble willow so what you were recommending is that I do 1 state that changes, and this state has so called sub categories like for the state blocking we have category posture
And blocking is a category of action
no?
I never suggested sub states
ever
State and context
you have Idle state
which goes into different states
like blocking
parry
m1
guardbreak
at least that's what I do
it's like this
Idle = {
OnEnter = function(machine, handler)
end,
OnUpdate = function(machine, handler)
local input = handler:ReadFromInputQueue()
if input.Action == "M1" then
machine:TransitionTo("M1")
end
end,
OnEnd = function(machine, handler)
end
}
@vivid grail
this is usually how state machines work
thats insane that i coincidently did what everyone else does
client will only change state and play animations when the server set that state
it can be server or client
this architecture
One question
ask ask questions are good
yes
which one
no
dont give states data
states are just runners
ok dont do that
not state holders
So how am I supposed to do the posture thingy when Im blocking?
i mean look u can have states have states if u want but in this specific case u dont need that moreover that has the same principle
cancel the existing posture and do the one appropriate to teh current state
regardless of whatever the substate is
what is that
yeah what is that btw
For example you are blocking, posture is the amount of damage you can negate with block and after it reaches 0 or the move block breaks, you get blockbroken
So when you are blocking you have 100 posture for example
When you get hit by a punch when blocking posture goes down by 20
And your block can basically tank 5 hits until it block breaks you
Meaning that I need to have in theory both posture and blocking
Because posture keeps existing when you are not blocking ( for example when it's regenerating)
Actually...
What I can do is make a character class
That has walkspeed posture and other stuff
And then just do the checks when you enter the state
For example when you enter blocking state
And you get hit
It reduces the posture
Is it valid? @marble willow
bro
dont overcomplicate pls
really
there are better ways
just do that in the damage callback as a side effect
have you heard of priority based numeric values
Hmmm I don't think so
is server gonna tell your walkspeed or client recreate
or both?
It's basically a system where you can register numbers for a specific duration and specific priority
the priority handler always uses the highest priority active number
Like I'll create the class just to store data
that is valid I mean
but for combat specific shit I would just store them in the combat handler
still storing walkspeed directly
not a good idea
@vivid grail
like this
this is basically a priority system with lifetime per entitiy
yep
do you get it?
I have a module for it
it's open source
but I haven't shared anywhere
Idk where to drop
maybe this is the time π
give me a full state handler
wdym
π
you already have a state machine
also
mind you
I had to build these from scratch
cuz there was nothing like this online
π
gives me PTSD
my utility write era
dw twin
I wrote everything you need for a combat system
I gotchu πΉ
need to drop SinekUtil
Istg Ill drop SinekUtil someday
I jsut need more modules
Im missing a few pieces
@vivid grail
u writing code using rojo?
cuz i see you got a lot of luau files
for open source stuff
roblox now exports as .luau
try it rn
like
I didnt write cleaner in rojo
no
it used to be lua
by default
you can see all the scripts that have .lua
those are from roblox
Oh my fucking god
RELEASE THE FILES π£οΈ
the sinek files
nah but fr dont be fooled
half of these are trash and duplicates
I have old code there
@marble willow one question, about the priority list
do you have a list of all the states
and then set priority to them so for example the attacking state cant overide the stunned state
No
That is already xoded into the logic
Through state machine
Onlt 1 state can be active at all times
yeah
but its like
if state A has lower priority then state B
then when state B is active
State A cant overwrite it
Priority handler just has .ValueChanged and GetCurrentValue
So you set the actual value on .ValueChanged
Like hum.WalkSpeed
i dont really get it
also
do i keep the statehandler module
that you created in server only?
@marble willow
It would require a rewrite to the states
Cuz state machine has 3callbacks
im asking cuz if i keep it server only
i cant made additional checks on client'
so it wont send unneccesary events
I would do the state on both client and server to keep things consistent
Replicate the State?
Yes
Basically rollback
yeah
But I guess thats a good thing in in your case?
Not much unless the value is changing very frequently
it does change really frequently
How
like
Im talking abt every frame
Yeah shouldnt be that often
For example to replicate energy dont use attributes
Youre gonna get lag spiked
ill replicate
starting to
regen
and starting to go down
and make it do its own math
something like it right?
So prediction
You can just use an unreliable
Or just a regular remote even
im planning on using packet
Yeah thats what I do
also
about the animation system that im using
do you think its going to be an issue in the future?
What animation system
I just saw :LoadAnimation
the one with that gets the time to an event
i had it cuz i played the anim on client
going to start moving my whole system after i fully figure out the state handler
Hmmm
gonna take a lot of nerves and tume
but
i gotta go thru the reworking arc once again
@marble willow , so do i jjust use simple animation events?
like
without the timing thingy
Yeah I recommend so
And if you have a dash that needs to start and end at points
Gl cuz usually hard coding per anim is the way to do
ππ
bowliiin
punch script is done
i like how easy i made my skill framework
now i have to do it for the rest of the skills,
and transfer them to the new statemanager
fahhhhhhhhhhhhh
what about body velocities
do i move them to the server too
it will save the hurdle of keeping it on client and firing an event to get it
eeeeeeeeeeeewwwwwwwwwwwwwwwwh
im already starting to feel that server sided animation delay
π
im playing with 0.07 replication delay
and it feels awful
No dont do that
Keep body mover client
ok
yk what
ill keep my own system
ill just rework the state machine
cuz whe playtesting with others i didnt have any bad expirience with desync and animations breaking
so yh
and it was smooth as hell
thats how state machines usually work
thats what im going to do
cuz i used simpel attributes b4
I mean bro
what were you expecting
are you playing from mars
ima keep my system
whats your ping
ill just
no genuinely whats your ping
isnt it 70 ping?
0.07 ms delay?
cuz when i tested with my system at 0.1 second replication delay
it feels smooth af
but i fire once
a roundtrip is 2 1 way trip
and server does it alll
you fire from client
server tells you to do smt
1 round trip
140ms
if you put 0.035 that's 70ms
smooth doesn't mean it will be accurate in game
you need real world staistics
to see how many times it rollsback
it is
or goes out of sync
have you tested with testers
Idk if you are getting the actual problem with client sided combat
I know
its a hybrid system
but like if I press parry
where i just play the animation on client and thats all
it fires a remote to server
to make the check
yeah but on my client I parried instantly
and it should've went through but it didnt
the smoothness is not the question
,it's a tradeoff
about lying to players with visuals
or showing actually what's happening
and there's no netcode that can erase the delay
you dont get instand visuals tho
there's stuff that hides it well
which isnt instant
that's what Im saying
it felt like you parried
but you didn't
client combat can be good
but most parry based games don't do it for a reason
ok
my game has perfect blocking
and not parrieng
parrying
thats the best way i can explain it
since you cannot have both comboes and parrying
i decided to go with perfect blocking instead of parrying
then client approach is still valid Id say
