CleverRaven/Cataclysm-DDA — pull request #7273 by BevapDin (2014-04-17 17:47:51+00:00)
Title: when the displaced vehicle is not found in the expected submap, search all submaps for it.

Fixes the bug reported there: http://smf.cataclysmdda.com/index.php?topic=6089 (I hope)

What happens (for me) is this:

Removing the part at (mount_dx, mount_dy) = (0, 0).

`vehicle::shift_parts` is called an while shift the vehicle parts to make sure that a part at (0,0) exists. This function simply goes through the list of vehicle parts and uses the first one that has a structure part. It shifts the vehicle coordinates (`vehicle::posx`, `vehicle::posy`), too.

The problem is that the vehicle is stored in the submap that contains the (0,0) part. In other words, the submap that contains (`vehicle::posx`, `vehicle::posy`) (usual coordinates). Shifting the internal locations around moves the origin of the vehicle (posx, posy) outside of the submap, but the vehicle pointer is still stored in the original submap.

`map::displace_vehicle` can't find the vehicle in the expected submap.

Example:
A vehicle has (posx, posy) = (4, 1), it is stored in the submap at (1, 2), its global coordinates are (1*12+4,2*12+1) = (16, 25).
Now the vehicle parts are shifted by (0, -2), (posx, posy) is now (4, -1), the shifting does not move the vehicle to another submap. So its global position is now (1*12+4,2*12-1) = (16, 23). This is "correct" - most parts of the code use `vehicle::global_x` which returns the correct values.

Now skip to `map::displace_vehicle`. For some reason it does not use a vehicle pointer as parameter, but a coordinate of the vehicle.

It looks up what submap the source coordinates are on, and than searches in that submap for the vehicle that should be displaced. The vehicle has the (16, 23) as global coordinates, so it is expected to be in submap (1, 1) and its (posx,posy) values are expected to be (4, 11).

The search can't find the vehicle as it searches the wrong submap. This lead to the debug message `displace_vehicle our_i=-1` (see `map::displace_vehicle`), as observed in the forum.

How to reproduce:

- New game, get driving skill to avoid fumbling.
- Spawn a Bubble car, move the bubble car north or south, do not change the direction, just straight north or south until the driver seat is on one submap, and the seat behind the driver seat is in another submap (look at the minimap when it changes you've moved to another submap):
```
"""
""#"" <- last row on submap 1
"###" <- first row on submap 2
+"H"+
"""
```
Now remove all parts of the driver seat. When you open the vehicle screen, the cursor start always on the vehicle part at (0,0). This should be the driver seat initially. When the driver seat (and all parts on that tile) are removed, the cursor should initially be on the seat behind the driver seat. This is now the new (0,0) point of the vehicle.

Now install controls on that seat, enable debug messages and start driving. This gives the behavior described in the forum.

----

The fix is to simply search all the other submaps, too. This solution is robust and compatible with current saves.