javierriveracastro / betteroll-swade

A Better Rolls port for SWADE
GNU General Public License v3.0
16 stars 32 forks source link

Gang Up: Allow for different melee distances #507

Closed eXaminator closed 1 year ago

eXaminator commented 1 year ago

Right now BR2 includes Gang Up if the distance between two tokens is 1" or lower. As far as I can tell, this compares the center of the tokens to calculate the distance. There are 2 scenarios where this approach isn't great:

  1. When a token is larger than 1", it has to be very close ("inside") of other tokens to be considered for gang up.
  2. When token art does not fill the complete "grid cell" but is smaller and/or is not a square / circle token, it can be hard to see if tokens overlap enough to be considered for gang up.

This is especially problematic on gridless maps.

I propose the following changes:

  1. Allow GMs to set the grid distance to be considered within default melee distance. It could default to the current 1", but I might set it to 1.2 or something to allow a little bit more leeway when calculating gang up.
  2. Take the size of the token into consideration when calculating if someone is in melee range. One thing to keep in mind though: Tokens don't have to be square, but could also be rectangular. This should also keep the seeting for 1) into account. For example: A 2x2 token and a 1x1 token should be within reach with a distance of 1.5 (or 1.7 if the default distance was set to 1.2, to add the extra 0.2 reach).
javierriveracastro commented 1 year ago

Point 1 done.

I have to think about point 2 specially for the 2x1 tokens.

javierriveracastro commented 1 year ago

Not really sure how this can work, but, about number 2.

1.- Add the z and y size and divide it by two for both tokens. 2.- Add both numbers above and substrac 2. 3.- Add the result to the setting melee distance.

If setting distance is 1, this will results:

The only other way is to try to measure from the closest token border and this will get a little more trickier.

javierriveracastro commented 1 year ago

Done. It should work well for square tokens, and kinda work for rectangular ones.

eXaminator commented 1 year ago

I have some questions about your calculations.

If I have a 1x1 and a 2x2 token that are placed exactly next to each other, the distance between their center points should be 1.5" (0,5" from the 1x1 token plus 1" from the 2x2 token), which should be the default Gang Up distance in this case I think. But your calculation results in the Gang Up distance being 2", which is quite a bit larger.

If I place two 2x2 tokens next to each other, their center points would have a distance of 2", so that should be the Gang Up distance, but your calculation results in 3".

This does seem to get worse with scaling. Am I missing something?

Maybe the calculation should be simplified to either always use the lowest or highest dimension for irregular tokens. Those are probably an exception anyway when it comes to melee and Gang Up.

In that case you could just add half the "size" of each token and get the "default" melee distance. Now increase that by the configurable "offset" value (or the derived offset based on that). So if the configured "default melee" distance is 1.2, you could just take the 0.2 and add that to the new melee distance. Or you could do some percentage calculation (so 1.2 is a 20% increase over the default, so increase all melee distances by 20% – though this might not scale well).

And next we could talk about melee weapons with reach 😆

eXaminator commented 1 year ago

On a sidenote: My thoughts expect the tokens to be round. That works well on a gridless map, but might cause problems when playing gridded, as the diagonal distance of tokens would always be greater than 1". I wonder if there has to be some kind of special handling for that case... 🤔

javierriveracastro commented 1 year ago

Yes, the problem with you approach are grids. Non adjacent big tokens give gang up.

javierriveracastro commented 1 year ago

After some testing and error, I believe this should work:


function withinRange(origin, target, range) {
    const size_mod_origin = (origin.document.width + origin.document.height)/2;
    const size_mod_target = (target.document.width + target.document.height)/2;
    range = range - 0.5 + Math.max(size_mod_origin, size_mod_target)
    const ray = new Ray(origin, target);
    const grid_unit = canvas.grid.grid.options.dimensions.distance
    let distance = canvas.grid.measureDistances([{ ray }], {gridSpaces: false})[0];
    distance = distance / grid_unit
    return range >= distance;
}```

What is does is taken the biggest "medium size" size (the real size for square token, the median size for rectangular ones). Add it the ranged defined in options, subtract 0.5 to it (it could be any number greater and close to root square of 2 minus 1 I yhink), and check this against the "real" (that means don't count squares on grids) distance.
eXaminator commented 1 year ago

That might be close enough, even if it's not perfect (given that tokens are technically square, perfect might not be easy to achive anyway). So just to see that I understood this (and to document the results for the future). Please correct me if I'm making some stupid mistake here (which could be very likely).

Given the initial range passed to the function is 1.

This might not a problem for most people though, so this might be ok. Maybe it would be good to get some more oppinions into this discussion?

I realize that this is a difficult and probably annoying problem to solve. I am still of the oppinion, that it might be best to use different calculations for gridded and gridless scenes.

Gridless could use an exact measurement using your sizemod from above. So basically distance - sizeModA/2 - sizeModB/2. That should result in the "outer" distance of the tokens, given they are roughly round (which is probably a fair assumption for most tokens. Even top-down tokens would probably fit the "roughly round" descriptor well enough). Compare that with the expected range (which I realize would probably have to default to 0, as that would be the "outer" distance between tokens, so they'd have to "touch").

For gridded maps you could probably just use gridSpaces: true when calculation the distance? That would use the 5e way of calculatng diagonals (every diagonal grid space is counted as 1), but that might be ok for this case?

Or, like I said, maybe I'm totally off here... 😅