Page MenuHomeFeedback Tracker

Vehicle IsAreaAtDoorFree fails for some objects depending on vehicle crew entry position
Assigned, NormalPublic

Description

If the crew entry position for a specific seat of a vehicle has enough distance from the door area, the IsAreaAtDoorFree check can fail to detect blocking objects (like basebuilding walls) because it moves the box that is used by IsBoxColliding behind the object.

This mostly affects some modded vehicles and allows players to glitch through said objects when getting out in some situations.

The solution is to stretch the box used for checking collision all the way from the crew entry position to the vehicle, as shown below. Also, the height check does not subtract the max allowed object height, thus increasing the checked area past the players height, which can prevent getting out in some situations where it should be possible (e.g. parking an Ada sideways in front of the open entrance of a car tent). Both issues are addressed below.

class Transport
{
	// snip...
	bool IsAreaAtDoorFree( int currentSeat, float maxAllowedObjHeight, inout vector extents, out vector transform[4] )
	{
		GetTransform(transform);
		
		vector crewPos;
		vector crewDir;
		CrewEntry( currentSeat, crewPos, crewDir );

		//! Adjust bbox depth so it stretches to the vehicle
		extents[2] = extents[2] + crewDir.Length();

		vector entry[4];
		entry[2] = crewDir;
		entry[0] = vector.Up * crewDir;
		entry[1] = entry[2] * entry[0];
		entry[3] = crewPos + crewDir * 0.5;  //! Adjust bbox position for altered depth
		
		Math3D.MatrixMultiply4( transform, entry, transform );
		
		vector position = transform[3];
		vector orientation = Math3D.MatrixToAngles(transform);
		
		position[1] = position[1] + maxAllowedObjHeight + (extents[1] * 0.5);
		
		array<Object> excluded = new array<Object>;
		array<Object> collided = new array<Object>;
		
		excluded.Insert(this);
		
		GetGame().IsBoxColliding(position, orientation, extents, excluded, collided);
		
		orientation.RotationMatrixFromAngles(transform);
		transform[3] = position;
		
		foreach (Object o : collided)
		{
			EntityAI e = EntityAI.Cast(o);			
			if (IsIgnoredObject(o))
				continue;
			
			vector minmax[2];
			if (o.GetCollisionBox(minmax))
				return false;
		}

		return true;
	}

	bool IsAreaAtDoorFree( int currentSeat, float maxAllowedObjHeight = 0.5, float horizontalExtents = 0.5, float playerHeight = 1.7 )
	{
		vector transform[4];
		vector extents;
		
		extents[0] = horizontalExtents;
		if (playerHeight > maxAllowedObjHeight)
			extents[1] = playerHeight - maxAllowedObjHeight;  //! extents height needs to be adjusted for maxAllowedObjHeight
		else
			extents[1] = playerHeight;
		extents[2] = horizontalExtents;
		
		return IsAreaAtDoorFree( currentSeat, maxAllowedObjHeight, extents, transform );
	}
	
	Shape DebugFreeAreaAtDoor( int currentSeat, float maxAllowedObjHeight = 0.5, float horizontalExtents = 0.5, float playerHeight = 1.7 )
	{
		int color = ARGB(20, 0, 255, 0);
		
		vector transform[4];
		vector extents;
		
		extents[0] = horizontalExtents;
		if (playerHeight > maxAllowedObjHeight)
				extents[1] = playerHeight - maxAllowedObjHeight;  //! extents height needs to be adjusted for maxAllowedObjHeight
		else
				extents[1] = playerHeight;
		extents[2] = horizontalExtents;
		
		if (!IsAreaAtDoorFree( currentSeat, maxAllowedObjHeight, extents, transform ))
		{
			color = ARGB(20, 255, 0, 0);
		}
		
		Shape shape = Debug.DrawBox(-extents * 0.5, extents * 0.5, color);
		shape.SetMatrix(transform);
		return shape;
	}
	// ...snip
}

Details

Severity
None
Resolution
Open
Reproducibility
Always
Operating System
Windows 10 x64
Category
Modding

Event Timeline

lava76 created this task.Jun 21 2023, 12:22 PM

@lava76 Holy cow! Not that I would be able to in any way judge the quality, but impressive ticket, straight up delivering a potential solution. Respect!

Geez changed the task status from New to Assigned.Jun 28 2023, 11:57 AM