Diagonal vehicle fix

As you all well know one of the problems with a game where everything is in a square-like grid comes when you try to rotate something. This is especially apparent in vehicles, where if you drive in a diagonal fashion, many parts of the vehicle that are “inside” are exposed to the outside via one of the diagonal tiles, whereas if the vehicle were at a 90 degree angle it would be normal (ie, no part exposed to the outside and the driver safely inside)
At the current state, if you say park a car diagonally, a zombie is capable of walking into one of the tiles diagonal to the driver’s seat, and attack you.
My proposal to fix this is simple in theory, but I’m not sure how simple it is in terms of code. Every tile in a vehicle currently has an “Inside” or “Outside” flag, and I propose that any entity or monster cannot interact with something that has the “Inside” flag unless it is also standing in a tile that also has the “Inside” flag, such as an open car door or a broken windshield. This would remove many the problems associated with cataclysm’s work-around for simulating the rotation of vehicles.

Thanks for suggesting this. I’ve been meaning to propose a similar solution, but haven’t because so lazy.

+1000 to this suggestion. Invisible walls that keep creatures from moving into your vehicle through a diagonal gap.

Need a bit more detail for this to be a workable suggestion, it’s easy to describe in vague terms, the hard part is handling all the details.

When you examine a vehicle, every tile of the vehicle has an “In” or “Out” flag, right? To separate outer parts of the vehicle from the inner parts to calculate whether or not the player suffers the effects of weather like rain or cold temperatures?
Make it so that only an entity standing in an “In” tile of a vehicle can interact with, grab, attack, or do anything with something also in an “In” vehicle tile.

There will always be “outside” tiles adjacent to “inside” tiles in a vehicle, which means there will always be situations where a zombie can’t attack you for no good reason. For example, in this car:

......
.|--|.
."""".
.+@Z'.
.+##+.
.|HH|.
.|++|.
......

The Z is on an “Out” square, and the @ is on an “In” square, but they should obviously be able to attack each other.

Wait, why is the Z’s square considered an Out square?

Yeah, I thought only opened doors/trunks/tiles without a roof are considered “Out”?

If it worked the way you thought it did, you’d have the same problem if the Z were in the driver’s side door square.
The reason it counts as outside is open doors don’t provide shelter.

The way that voskhod suggests might be a little strict, which is what Kevin is saying in his counter-example.

How about any zombie (and NPCs and PCs) that is not standing on a vehicle tile cannot move or attack anything that is an ‘In’ tile on a vehicle? Can anyone think of a counter-example for which that would lead to a non-intuitive result?

[quote=“digitCruncher, post:9, topic:9984”]The way that voskhod suggests might be a little strict, which is what Kevin is saying in his counter-example.

How about any zombie (and NPCs and PCs) that is not standing on a vehicle tile cannot move or attack anything that is an ‘In’ tile on a vehicle? Can anyone think of a counter-example for which that would lead to a non-intuitive result?[/quote]

open doors again. if you are one tile away from the open door, you’re considered Inside and in this case a boomer, for example, won’t be able to spit at you, although he should be able to do so.

I have one pretty hard solution for that.
So in order to implement this we need to create some virtual impassable invisible object and opaque passable object. (in some sense it can be called a corner)

Let’s imagine next situation

z/
/x

In that situation X shows a place where there should be impassable “corner” but it’s not because of the way the game engine works. In order to fix that we check IF these two adjacent objects are impassable. If that’s true (both objects are walls) then we create that invisible impassable object which restricts zombies from coming in. The same goes for opacity - if both object are opaque we create virtual opaque object. If one of objects is not opaque we don’t create VOO (virtual opaque object).
Now about damaging. Since this method allows to create indestructible corner we need to make VIO & VOO actually refer to those walls. If something comes to damage virtual object then damage should evenly spread to both adjacent walls. I think it’s a fair game. Impassability should be prioritized.
As for “z” in the map this place shouldn’t be checked because it’s actually inside a vehicle.
Although it actually allows to create diagonal pockets INSIDE a vehicle, that’s a rare case and it’s pretty hard to come up with solution.

It’s not the easiest solution to implement, though.

[quote=“digitCruncher, post:9, topic:9984”]The way that voskhod suggests might be a little strict, which is what Kevin is saying in his counter-example.

How about any zombie (and NPCs and PCs) that is not standing on a vehicle tile cannot move or attack anything that is an ‘In’ tile on a vehicle? Can anyone think of a counter-example for which that would lead to a non-intuitive result?[/quote]
Hmm, so if you’re standing on the ground you can’t attack anything that counts as inside. I think there are some situations where you could build some rams or bare frames around an enclosed space and recreate the situation we have now, but you’d have to go out of your way to do it.
I think that would improve the situation a great deal.

That all seems overly complex. Why not de-rotate for adjacency calculations?

Example:

[pre]
. = floor

= unpassable

  • = passable (door/etc)
    [/pre]

Car’s normal layout:

[pre]

.####.
.####.
Z1+++.
.+2++.
.++++.
.####.

[/pre]

Z can strike 1, not 2

Rotated car layout:
[pre]

…####.
…####.
…Z1+++.
…+2++.
…++++.
.####.

[/pre]

Oh no, Z can strike 2! But if we take the car and every space adjacent to it and de-rotate it until it’s at 0 degrees rotation it’s equivalent to the unrotated car and Z will be unable to strike 2, just like if the car is going straight.

De-rotating for adjacency calc only sounds simple, but I’m sure it isn’t easy to code.

The ‘if you’re outside you can’t attack anything that’s inside’ rule is probably the best fix.

Here’s some pretty strong counter examples to the simple “outside can’t attack inside” rule.

  1. Build a single frame with roof.

[code]. = frame with ceiling
_ = outside ground


.
___[/code]
2) Pull frame behind me until I attract zombie attention.
3) Step into frame.
4) Laugh as all the zombies walk up right next to me and I poke them to death while they can’t attack me because I’m “inside”.

Even if you required multiple tile coverage to make something be “inside” you could still build something that easily rendered you completely invulnerable to zombie attacks while being able to kill them with impunity, i.e.:

[code]B = board

B_B
B.B
BBB[/code]

Or heck, how about this:

_B_ B.B _B_
Player is surrounded by walls so they count as “inside”. Diagonal squares aren’t, so count as “outside”. As long as the boards stay standing the player can attack any adjacent zombie with impunity without needing to worry about fear of retribution.

And this could be done on any cars with doors, either by standing in the door square or the square right next to it (depending on if the door counts as “inside” or not). And even if you say “neither inside nor outside can attack one another”, you’re still setting it up for a ranged player to use it, then pull out there gun and just plunk shots at the zombies standing right next to them even though they aren’t allowed to attack them (since there’s no reason why you shouldn’t be able to shoot from “inside” to “outside” or vice versa).

Honestly the “derotating” idea, despite the coding difficulty, is probably going to be the most realistic one. The “all corners are impassable” idea would also work, though it would involve a similar amount of code changing and you’d bet we’d need to implement it in normal buildings too for consistency.

Well you can fix that by making the concept go both ways - zombies can’t attack the player if they’re outside, but neither can the player

As I pointed out, guns should realistically be able to shoot out of a window or door and hit a zombie standing there. Or how about throwing things? Throwing explosives out of car windows at zombie hordes is certainly a tactic that I’ve seen people use before. Enable either of those, and all you’ve done is force our invincible player to be a ranged character instead of a melee one.

And even if we can’t attack back through throwing or ranged weapons, having a spot like that would still be incredibly OP. Losing a battle against a zombie horde? Just step onto your single tile vehicle (which you built a bed on), and hole up for a few days while you heal up, with the zombies still all standing right next to you. If the single tile thing worked they wouldn’t even be able to bash it out from under you, because you are already standing on the tile (and thus they would attempt to attack instead of bash anything). Or if it’s a multitile only type of thing then just stick some repair stuff in there and repair your vehicle every now and then to stop them from bashing their way in.

[me=Kevin Granade]names his vehicle “Elbereth”[/me]

But I think you’re missing a little bit of detail. You can’t make a one-tile vehicle that counts as inside, minimum is 3x3, in which case the path is either blocked and will get smashed, or is open and the monster can step on it, at which point they’re standing on the vehicle and can attack you.

Honestly the "derotating" idea, despite the coding difficulty, is probably going to be the most realistic one. The "all corners are impassable" idea would also work, though it would involve a similar amount of code changing and you'd bet we'd need to implement it in normal buildings too for consistency.
I also forgot to mention in order to create VIO or VOO the distance between two adjacent walls should be <= 2^0.5. As for coding complexity I believe it's far less difficult than derotation. The problem with derotation is that you somehow need to calculate where would object be if they were moving inside a vehicle pointing at north. Normally it's not a problem (just calculate the coordinates of a zombie it would be at by rotating the point around the center of the vehicle by corresponding angle negative (as shown in pic.)), but in our case we would need some virtual, not accessible map-space because if you just rotate a vehicle, the results may get distorted by some map elements or other mobs or else. In short it's not reliable and fast (comparatively) way. Teleporting the entire vehicle somewhere else is no go. Teleporting just an interacting part still may require a lot of debug.

  1. Vehicle rotation direction and angle
  2. Zombie rotation around the center direction and angle
  3. North direction (cardinal direction)
  4. Current vehicle direction
  5. Current zombie positition
  6. Zombie position after rotating
  7. The center of the vehicle

Rotating a vehicle is already pretty complicated and inaccurate because we use tile-based system and round numbers so real coordinates of tiles’ centers get approximated. I tried to code accurate rotation in tile-based game once and… it was a mess. Just a huge mess of trigonometric hell. Without hacks implementing and maintaining accurate rotation in games like Cataclysm is nigh impossible.

We don’t really need to (de)rotate the vehicle. We have vehicle adjacency data easily accessible as part mount points. Those don’t change during combat and movement, only during construction.

So we only really need to translate the attacker’s position to the same coordinate system as vehicle pointing north would have.

After the translation, we have an attacker in vehicle’s local coordinates. If attacker and target positions have maximum distance on x or y > 1, it means the attack is not possible.
Then we can trace a ray from attacker’s position to the target. This ray will have at most 6 (5? 4?) tiles, so it’s not expensive. The zombie should target any of the tiles of the ray that have distance both to it and to target equal to 1.

Example:
Rotated vehicle:

. z / /
. / @ .

Unrotated vehicle:

. z | |
. . | @

Here the distance > 1, so the zombie should attack (if obstacle) or move onto (otherwise) one of the two tiles to the east or south of it.