RPTools / maptool

Virtual Tabletop for playing roleplaying games with remote players or face to face.
http://rptools.net
GNU Affero General Public License v3.0
801 stars 262 forks source link

[Feature]: More Options for Token (In)visibility #4379

Open Pmofmalasia opened 1 year ago

Pmofmalasia commented 1 year ago

Describe the Problem

A common feature across tabletop games is the ability for things to become invisible. Currently, the way this is represented is through some combination of decreasing the token's opacity or unchecking the "Visible to Players" box. However, these solutions are not necessarily optimal.

For the former, decreasing the token's opacity does not actually affect functions such as canSeeToken(). It also does not actually make the token completely invisible, which may or not be desired.

For the latter, while it does prevent functions from "seeing" the token, an equally common feature in tabletop games is the ability to see invisible things. Creatures with this feature are prevented from being able to see the token with canSeeToken(), even though they should be able to see it.

A further issue with canSeeToken() - there is currently (to my knowledge) no way to creatively override the inability to see a token marked "Not Visible" via macros. canSeeToken() will not detect it. getTokens() and similar functions will detect the invisible token, but can only evaluate for straight distance to the token and not actual vision (the visible option is of course not viable). Therefore, I can't even check if invisible tokens should be able to be seen by a creature that can see them - while keeping them hidden to other tokens.

To outline it more succinctly, issues with the current setup are as follows:

The Solution you'd like

This would likely require some pretty big changes. The first would be the addition of an "Invisible" property on tokens. The second would be the addition of a rule in sights/lights that allows for vision on creatures tagged as invisible.

There could be some potential for different types of tags that limit visibility as well, e.g. D&D has the ability for creatures to be unseen in the Ethereal Plane. It would be nice to be able to have custom tags that prevent vision (e.g. prevent vision due to Invisibility, prevent vision due to Ethereal, etc.) but I can't envision (no pun intended) a way of making this system user-friendly.

Alternatives that you've considered.

The ability to run the canSeeToken() function assuming the token can see tokens marked as not visible to players would help as well. It would not solve the on-map discrepancy, but seems much more feasible.

Additional Context

An additional note about the purpose of Invisible vs. Not Visible to Players, for clarity - Invisible would allow tokens to overcome it as part of the game rules. Not Visible to Players (as it is now) overrides these game rules and is a 100% secure way for GMs to hide things on the map.

Azhrei commented 1 year ago

This has been discussed over the years. I recall three solutions being discussed; there are probably more. (Now that I've typed up options 1 and 2, I can't remember what the third one was. Sigh. #FrankIsOld)

  1. Create a layer (or layers) for invisible creatures, then define sight types that can see tokens on those layers. This plays well with existing MTscript functions: a token can "see" another if it's within line of sight and on a layer that's visible to the token. This could potentially allow for ethereal, incorporeal, thermal, echolocation, and other specialized layers. @kwvanderlinde posted recently #4378 about cleaning up layer definition and usage, so this might be the time to speak up.
  2. Define some kind of "teams" for players. Allow a given token to be a member of multiple teams at once. Add the "invisible" team to a token and only tokens on the "see invisible" team will be able to detect them. This is pretty clunky, as it requires two teams dedicated for invisibility. However, existing MTscript functions can work as they do now. This solution also allows the benefit of an "observer" team that can see a game being played but is not allowed to see any invisible tokens (so as not to leak information to players). Teams could be set as an internal field of the token or a specific property name could be reserved for the use of team designations (could break compatibility, but allows an existing API to modify team values). It may add work for the GM, though, since players shouldn't be allowed to add their tokens to teams without approval. That's a whole can of worms.
  3. Um...

I'm a fan of the layer-based approach. The community has been asking for more generalized layers for a long time, and invisibility is a good use case, along with many others.

Pmofmalasia commented 1 year ago

The layer-based approach would like solve this, but one foreseeable issue/pain point would be that you'd need to change layers to move around the invisible tokens. Unless perhaps the generalized layers could be set up in sort of groups, where you can move tokens around in a group of layers as long as you're on one of them.

kwvanderlinde commented 1 year ago

I quite like this part of the FR:

There could be some potential for different types of tags that limit visibility as well, e.g. D&D has the ability for creatures to be unseen in the Ethereal Plane. It would be nice to be able to have custom tags that prevent vision (e.g. prevent vision due to Invisibility, prevent vision due to Ethereal, etc.) but I can't envision (no pun intended) a way of making this system user-friendly.

It would be quite straightforward to extend sights to specify which types of invisiiblity they overcome. A plain list of invisibility names would suffice.

But I think we can slightly generalize that idea for greater effect:

  1. Tokens are given a "visibility category". E.g., can be set to "visible" for a regular visible token, "invisible" for a token under the effects of an Invisibility spell, "ethereal" for a token on the Ethereal plane, etc. Available options are defined by the campaign somehow, with "visible" being a standard option.
  2. Sights are allowed to provide a list of visibility categories they can see. By default, just "visible", but specialized sights could be more specific. E.g., Blindsight would leave out "visible" but include "invisible"; some "Ethereal sight" could list both "visible" and "ethereal".
  3. Allow stacking multiple sights on a token. E.g., darkvision + blindsight + ethereal sight. Tokens can see any visibility categories in any of their sights (respecting vision ranges of course).
Pmofmalasia commented 1 year ago

But I think we can slightly generalize that idea for greater effect [...]

All of your suggestions would be wonderful - particularly # 3 was one I had been thinking about in a separate context (though being able to create unique sights as is in the works for lights would alleviate that need somewhat).

If this is feasible, I think it would be preferred over the layer-based option, which has the potential for clunkiness as I mentioned above, and also as Az mentioned in the associated issue about layers where tokens on the "invisible" layer can't necessarily see other tokens on the invisible layer. And needing a ballooning amount of layers if they are used for different elevations.

cwisniew commented 1 year ago

I quite like this part of the FR:

There could be some potential for different types of tags that limit visibility as well, e.g. D&D has the ability for creatures to be unseen in the Ethereal Plane. It would be nice to be able to have custom tags that prevent vision (e.g. prevent vision due to Invisibility, prevent vision due to Ethereal, etc.) but I can't envision (no pun intended) a way of making this system user-friendly.

It would be quite straightforward to extend sights to specify which types of invisiiblity they overcome. A plain list of invisibility names would suffice.

But I think we can slightly generalize that idea for greater effect:

  1. Tokens are given a "visibility category". E.g., can be set to "visible" for a regular visible token, "invisible" for a token under the effects of an Invisibility spell, "ethereal" for a token on the Ethereal plane, etc. Available options are defined by the campaign somehow, with "visible" being a standard option.
  2. Sights are allowed to provide a list of visibility categories they can see. By default, just "visible", but specialized sights could be more specific. E.g., Blindsight would leave out "visible" but include "invisible"; some "Ethereal sight" could list both "visible" and "ethereal".
  3. Allow stacking multiple sights on a token. E.g., darkvision + blindsight + ethereal sight. Tokens can see any visibility categories in any of their sights (respecting vision ranges of course).

The logical -- although not as straightforward to implement -- extension to this is that VBL should have visibility categories that they can block; for example, an illusionary wall would block most vision types but not a vision type given to someone that has a spell cast on them that allows them to see illusions for what they are.

Pmofmalasia commented 1 year ago

Good point about the illusions - which reminds me that another consideration for implementing illusions would be the token images, with those seeing through the illusion seeing the "true" form of the creature. Perhaps this be done via image "loadouts" on the tokens, tagged with these same visibility category to determine what is seen.

This goes much further than the original idea, but just an additional thought while it is under discussion.

bubblobill commented 11 months ago

IMHO, to do this properly we need to go beyond light and sight, and think instead of "sources/senses". Token's need the ability to have more than one environment sense for it to work and there needs to be a table of how things interact. As a supernatural bat I have:

Being invisible to each of these is a different thing. Wrapping myself in anechoic foam defeats sonar but nothing else. Going transparent doesn't stop me making or reflecting sound. Being vewwy vewwy quiet defeats hearing. Defeating a mass sensor probably requires going desolid or phase-shifting.

Since MT prides itself on being system agnostic, we should try to implement something that can conceivably be configured to deal with different mechanisms.

There are also "non-targeting" senses that only give you a general region of an opponents position. Do you blur the token image and paint a footprint of its area of likely occupation until it is actually observed? Oh dear, I just found a practical application of quantum physics.

With shared vision, can other players see what I see if they don't have the same senses as me?