That ability could be very useful in many cases. For example, if a friendly unit moves into zone of reconnaissance of a hostile unit, and thus discovers it.
Unfortunately, both the Invisible and Mask trait does not support this kind of “third-party” actions (they share much of the same code, so not too surprising). To some extent the Restricted Access and Restrict Commands traits also has some limitations.
The problem is, that the traits filter what actions can be taken based on the current PlayerSide. Perhaps an example is illustrative:
- suppose we have a piece
athat has been “hidden” (masked, made invisible, restrict access or commands) by sideA. - When ever
areceives a “sensitive” command, it will check if the currentPlayerSidematches the internally storedownerof the piece. If they do not match, then the action is rejected.- This mostly makes sense, because it prevents side
Bfrom “revealing” the piece.
- This mostly makes sense, because it prevents side
- Now suppose the current
PlayerSideisB(or more accurately notA). The player performs some action that should reveal the piecea.- It could be that the End movement on this map command is triggered, and some logic in the module decides that piece
ashould be revealed - for example if aBpiece - saybmoves into the same hex asa. - The module logic can then send a command to piece
atelling it to reveal itself.
- It could be that the End movement on this map command is triggered, and some logic in the module decides that piece
- However, to piece
a, it looks as ifPlayerSideBwas the one that send the command, and will therefore reject it. - In other words, piece
awill only accept “sensitive” commands whenAis the currentPlayerSide.
What the traits really need, is to allow for some command (perhaps only Named Commands) that will be processed no matter what. Of course, then it would be up to the module designer to make sure that those commands cannot be triggered in an “illegal” way.
Another problem may be, that when piece a is “hidden” by side A, it is not addressable when side B is active. That is, a command will never even try to be delivered to piece a if side A is not the current PlayerSide. However, I don’t think that’s a problem - only worth considering.
For the Mask trait (called Obscurable in the code), the culprit is in VASSAL.counters.Obscurable#keyEvent. Here, all key events are filtered based on VASSAL.counters.Obscurable#obscuredToMe which in turn uses
VASSAL.counters.PlayerAccess#currentPlayerHasAccess,VASSAL.counters.SideAccess#currentPlayerHasAccess, orVASSAL.counters.SpecifiedSideAccess#currentPlayerHasAccess.
The logic is similar in the Invisible trait (called Hideable in the code) - see VASSAL.counters.Hideable#myGetKeyCommands.
Both of these traits could have additional key commands that are always executed no matter the current PlayerSide. That would allow the module to execute those commands “on behalf” of the “owning” side. It could also be done in derived traits so as to leave the old traits as they are.
If someone would submit a PR that did this, then now would be a good time, as it would have a chance going into the up-coming 3.8.0 release. Nudge, nudge, wink, wink ![]()
Yours,
Christian