derkork / godot-statecharts

A state charts extension for Godot 4
MIT License
761 stars 39 forks source link

Can events carry some custom parameters? #135

Open smile-coder opened 1 month ago

smile-coder commented 1 month ago

Hello, the godot-statecharts is really easy to use and great tool. I found that the triggered event can not carry some custom parameters. I would like to know if this can be implemented. If it can be implemented, it will greatly increase the ease of use.

For example, if a player takes damage in a non-invincible state, the damage value can be customized by triggering the function: _$StateCharts.sendevent("damage", 12) and _func eventreceived(event, args...).

Or is there an elegant alternative?

derkork commented 1 month ago

Funny enough I had a similar idea the other day. This is most certainly doable though it will be a breaking change because of the signal. It will also only support a single argument but that should be sufficient as you can give any Godot object as event data, which includes custom objects and things like dictionaries and arrays. It will probably be a bit more work though as I think it would be very useful to have event data also available in expression guards and this will need a bit of fiddling.

eobet commented 1 month ago

I must admit I'm confused and hesitant about any sort of code based logic via the Godot State Charts node inspectors, and that includes the Expression Guard.

However, I too would love to have something like this, because I'm currently having quite some trouble figuring out how to solve the particular type of movement logic I want without a more explicit queue feature or some sort of a signal/event guard... (or partially keeping track of the state charts in my code, which I feel kinda defeats the purpose of the plugin).

For me (and this will be pseudo code now) I envision I'd use it for something like $StateCharts.send_event("PlayerPressedAMovementInput", "ButOnlyTransitionWhenTweenCompletes") if you see what I mean, because the first part happens in unhandled input and the second part will happen when tween sends the finished signal so I sort of want to queue that up somehow...

Anyway, if this feature would be expanded upon, I'd love it if custom parameters could also be managed in a list, just like events now are!

DaveMS commented 1 month ago

I would also like to see this, and jumped on to here to post the same thing.

in my case I want to transition to a "Switching Weapon" state when a user presses a key to switch to a different weapon. It would be useful to be able to pass a parameter to the new state to specify which weapon is being switched to so that the new state can load the correct model and perform the appropriate animation.

At the moment I have to work around it by storing this in a class level weapon_to_switch_to variable which is only used to pass this data between these 2 states.

DaveMS commented 1 month ago

Thinking about it a bit more, maybe my usecase is slightly different than the one posted. But as an extension to the initial enhancement and custom parameters are added to events: if a state transition is triggered by an event with a custom parameter, would it be possible to pass the custom parameter data to the on_entered handler of the new state?

derkork commented 1 month ago

Yes that would indeed make sense, however this is going to break every project that is currently using the library as I cannot change the signal parameter list in a backwards compatible way. I will have to think about how I can make this happen in a way that isn't super frustrating when upgrading the project to a new library version. Also there are some interesting edge cases with this setup. Say you have a setup like this:

image

Now you do a send_event("some_event", some_value). This will call state_entered on B and give you some_value as a parameter. Then immediately after this B will transition to C or D depending on the value of x. Now say it transitions to C, what is given as a parameter to state_entered for C? Is is null because the state change wasn't technically directly triggered by an event or is it some_value because the state change was a chain effect from the transition to B. I think you can find valid arguments for both positions but I really can only implement one of them (also detecting chain effects may be tricky). So I think this is going to need a bit more thought to have a universally useful behaviour.