db0 / godot-card-game-framework

A framework which comes with prepared scenes and classes to kickstart your card game, as well as a powerful scripting engine to use to provide full rules enforcement.
http://dbzer0.com/projects/godot-card-game-framework/
GNU Affero General Public License v3.0
907 stars 96 forks source link

Allow ScriptingEngine to handle signal-based automation #57

Closed db0 closed 3 years ago

db0 commented 3 years ago

Currently the scripts trigger on player activation (double-click to be exact), but a lot of card effects are also reactive. E.g. "When this card is drawn, discard a card", or "When a card is destroyed, draw a card".

I have to figure out a way to trigger card scripts based on signals defined in their code. This needs to work in parallel with the state-based limit, as a script might require a signal and a specific state.

One way to do this, is to make various common actions trigger signals. I can think of a few generic ones

etc.

Those signals would be caught by a central point (the board? cfc? some new signal coordinator node? not sure yet) and then will call some sort of parser, to see if there's any other cards who are listening for those signals.

I think I should go through a central coordinator node as I don't think it makes sense to connect each card to each other card just in case.

db0 commented 3 years ago

I had some thoughts on how to do this

There will be a SignalOrchestrator in cfc. All it will do is connect to all the signals from every card in the game whenever it appears (typically during startup or spawning). Also on instancing every card, it will be added to the "Cards" group.

Whenever a card emits a signal, such as card_rotated(self,degree), the signal propagator will catch it and call a pre-specified function using a group call, to all the cards

func on_Card_rotated(card,degrees)
    get_tree().call_group("cards", "execute_scripts(card,degree)")

The CardScriptDefinitions Dictionary will be extended to have a parent dictionary per trigger, above the card position. The trigger that alredy exists in "manual activation", and the other triggers will be based on the name of the signal. So for card rotation, the trigger will be "card_rotated".

The execute function on the card will be extended to expect the trigger name so that it retrieves the right dictionary from the CardDefinitions.