From 49699d7f2f7e17dacb9af65a3c638654af855f8f Mon Sep 17 00:00:00 2001 From: Trevor Shelton Date: Tue, 21 May 2024 10:22:14 -0700 Subject: [PATCH] Change #10028: Overtaking Routines Improved --- src/roadveh_cmd.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index a638f379fe..6557aaa32f 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -772,7 +772,38 @@ static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data) { const OvertakeData *od = (OvertakeData*)data; - return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr; + /* This is the offset to tile in front of either the passer the passee, looking the passer's way. */ + TileIndexDiff front = TileOffsByDiagDir(DirToDiagDir(od->v->direction)); + + /* A vehicle blocking overtake must be an engine running on the road. */ + if (v->type != VEH_ROAD || v->First() != v) return nullptr; + + /* A vehicle must be a third party to block. If it is the same as either the passer + * or passee, it's just part of the base overtake and there is no blockage. */ + if (v == od->u || v == od->v) return nullptr; + + /* Overtaking concerns the overtaker's tile as well as the few in front of them. + * If a third party is not in these tiles, it is not blocking the overtake. + * If the overtakee and overtaker are on separate tiles, look one tile further. */ + if ( v->tile != od->v->tile + && v->tile != od->v->tile + front + && v->tile != od->v->tile + front + front + && v->tile != od->u->tile + front + front) return nullptr; + + /* From here, the third vehicle is blocking if one of the below is true. */ + + /* 1: The third vehicle is going the opposite way, so it's not wise to pass. */ + if (v->direction == ReverseDir(od->v->direction)) return v; + + /* 2: If the passee is active but not moving, then it is likely wanting to overtake as well. + * It's safer to let it deal with this first. If it is moving, it is better to close passer + * and passee's distance first than it is to try and overtake. */ + if (!(od->u->vehstatus & VS_STOPPED || od->u->breakdown_ctr == 1)) return v; + + /* 3: Third vehicle is trying to overtake too, but it is stuck for some reason. */ + if (((RoadVehicle*)v)->overtaking && v->cur_speed == 0) return v; + + return nullptr; } /**