DaemonEngine / Daemon

The Dæmon game engine. With some bits of ioq3 and XreaL.
https://unvanquished.net
BSD 3-Clause "New" or "Revised" License
298 stars 61 forks source link

[RFC] Flexible, mod-friendly key bindings #939

Open slipher opened 11 months ago

slipher commented 11 months ago

This is a proposal for a more general system of conditionally activated binds to replace teambind. Loosely inspired by the discussion of Xonotic bind overlays in #108 (although I don't think I ever managed to find any information on what Xonotic actually does here.). Setting a team-specific bind would look something like bind team:humans hw:m "itemact medkit". (I should probably think of a different separator instead of ':' in team:humans since : is also used to specify keys). But there may be various other bind masks active in addition to the team, e.g. mod:ctf, class:dragoon etc. I was motivated to write this the other day because I was working on a mod and wanted to have a different binding for mouse1 but didn't want to clobber the user's usual Unvanquished binds. (Just reinterpreting the default bind to mean something different wasn't that easy because of the difference between plus commands and normal commands). A mod:xyz bind mask would be a solution to this.

illwieckz commented 11 months ago

I fixed the markup in the comment.

illwieckz commented 11 months ago

One interesting thing is that you may even be able to do per class binds, With granger having priority over aliens which would have priority over the base bind.

Why not thinking about prefix:name? I'm not sure team or class are good prefixes, I would just use a game/mod keyword as prefix, the inheritance would be handled by the game. For example:

bind all:all hw:` toggleConsole
bind all:all hw:w +forward
bind all:all MOUSE1 +attack
bind unv:all hw:q +activate
bind unv:humans MOUSE3 "itemact grenade"
bind unv:aliens MOUSE3 +attack3
bind unv:granger CTRL +toggledWallwalk
bind unvrace:all hw:1 "say I am the Nightrider!"

The "unvrace" mod would inheritate keys from unv, that would inheritate keys from all. In the unv game itself, granger would inheritate keys from aliens, that would inheritate keys from all.

DolceTriade commented 11 months ago

Is there a performance implication for this? How do mods ship their bind masks? What does the default UI do for bind masks?

slipher commented 11 months ago

One interesting thing is that you may even be able to do per class binds, With granger having priority over aliens which would have priority over the base bind.

Why not thinking about prefix:name? I'm not sure team or class are good prefixes, I would just use a game/mod keyword as prefix, the inheritance would be handled by the game. For example:

It's a good point that maybe granger should be more specific than aliens by default. In my original proposal if you did something like something like bind team:aliens CTRL +attack; bind class:granger CTRL +toggledWallwalk, then the system would complain that the binds are ambiguous when used as granger since they both have one mask. You'd have to add -class:granger to the first bind (making the binds non-overlapping), or add another mask to the second bind (making it more specific).

I should clarify why I originally proposed the maskname:maskvalue associative structure for masks, and not just a freeform maskname e.g. aliens or granger. The only purpose of this was to make it more convenient for the cgame to set a new value while simultaneously clearing a new one. So upon evolution setting class:dragoon would automatically clear class:mara, class:dretch etc. without the cgame having to remember the old one and clear it.

To fix the granger not being more specific than aliens problem, maybe each mask can have a priority. Like team:aliens 2, class:granger 3, mod:unvrace 100 or something. And the total "weight" for breaking ties between binds would be the sum of mask priorities.

As for hierarchies or "inheritance" between masks, I don't want to restrict everything into a single hierarchy. For example I want to have class:spectator which is active when you are dead on a team, as well as on spectators.

Is there a performance implication for this? How do mods ship their bind masks? What does the default UI do for bind masks?

I see little performance implication. The map of key -> array of commands length 4 will be replaced with key -> vector of (mask list, command). You have to additionally compare the masks but ormally there won't be more than a couple of entries there.

The cgame will have trap calls to control the set of active masks.

The UI can work in a generalized way of how it does now. Currently the UI can detect binds that are less specific than it expects (i.e. an all-teams bind when it wants to set a aliens bind), and unbinds those when setting a new key. But it is ignorant of binds that are more specific -- when there exists an human-specific bind for a control that the UI wants to bind for everyone. So with the new functionality trap_Key_GetKeysForBinds will take a command and a list of masks (in the existing case, either an empty list or a single team mask) and return binds compatible with those masks. Binds specifying any mask name not specified in the call will be ignored.