--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c +++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c @@ -137,6 +137,31 @@ if (scripted) detail = scripted.GetActionDebugInfo(); if (detail.Length() > 200) detail = detail.Substring(0, 200); return string.Format("%1 state=%2 suspended=%3", detail, action.GetActionState(), action.GetActionIsSuspended()); + } + // Read-only state at the failed proof boundary, not a claim about the earlier + // release trigger. Release may already have cleared its waypoint and order. + protected void LossDiagnostic(ERR_ConvoyVehicle unit, int slot, float now) + { + if (!unit) { PrintFormat("ERR CONVOY LOSS: slot=%1 record missing", slot); return; } + PrintFormat("ERR CONVOY LOSS: slot=%1 index=%2 entity=%3 alive=%4 released=%5 arrived=%6", + slot, unit.Index, unit.Entity, ERR_Actors.Alive(unit.Entity), unit.Released, unit.Arrived); + bool enemyGroup = unit.Group && unit.Group.GetFaction() == m_Mode.EnemyFaction(); + bool aboard; + if (unit.Driver && unit.Entity) aboard = ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(unit.Driver), unit.Entity); + PrintFormat("ERR CONVOY LOSS: group=%1 enemyGroup=%2 driver=%3 alive=%4 canFight=%5 player=%6", + unit.Group, enemyGroup, unit.Driver, ERR_Actors.Alive(unit.Driver), ERR_Actors.CanFight(unit.Driver), ERR_Actors.Player(unit.Driver)); + int routeCount; + if (m_Task.Route) routeCount = m_Task.Route.Count(); + PrintFormat("ERR CONVOY LOSS: aboard=%1 routeIndex=%2 routeCount=%3 now=%4 legDeadline=%5", + aboard, unit.RouteIndex, routeCount, now, unit.LegDeadline); + PrintFormat("ERR CONVOY LOSS: waypoint=%1 members=%2 taskReady=%3 taskStopped=%4 reason=%5", + unit.Waypoint, unit.Members.Count(), m_Task.Ready, m_Task.Stopped, m_Task.Reason); + for (int i = 0; i < unit.Members.Count() && i < 32; i++) + { + IEntity member = unit.Members[i]; + PrintFormat("ERR CONVOY LOSS: member=%1 actor=%2 alive=%3 canFight=%4 player=%5 sameGroup=%6", + i, member, ERR_Actors.Alive(member), ERR_Actors.CanFight(member), ERR_Actors.Player(member), ERR_Actors.Group(member) == unit.Group); + } } protected void MovementDiagnostic(float now) { @@ -376,7 +401,8 @@ for (int i = 0; i < 6; i++) { ERR_ConvoyVehicle vehicle = m_Task.Vehicles[i]; - if (!vehicle.Entity || (vehicle.Released && !vehicle.Arrived)) { Check(false, "vehicle released before road movement proof"); return -1; } + if (!vehicle || !vehicle.Entity || (vehicle.Released && !vehicle.Arrived)) + { LossDiagnostic(vehicle, i, now); Check(false, "vehicle released before road movement proof"); return -1; } minimum = Math.Min(minimum, vector.DistanceXZ(m_Origins[i], vehicle.Entity.GetOrigin())); } float leader = vector.DistanceXZ(m_Origins[0], m_Task.Vehicles[0].Entity.GetOrigin());