private static float HandleMovableBridge(ref Vehicle vehicleData, ushort buildingID, ref Building buildingData, bool passing, bool near, float minY, float maxY, float maxSpeed, float vehicleTopY)
        {
            BuildingInfo buildingInfo = buildingData.Info;

            if (!(buildingInfo.m_buildingAI is MovableBridgeAI))
            {
                return(float.MaxValue);
            }

            MovableBridgeAI movableBridgeAi = (MovableBridgeAI)buildingInfo.m_buildingAI;
            float           bridgeClearance = buildingData.m_position.y + movableBridgeAi.m_BridgeClearance;

            if (bridgeClearance > vehicleTopY)
            {
                return(float.MaxValue);
            }

            if (!passing && !near)
            {
                return(float.MaxValue);
            }

            ushort bridgeState = MovableBridgeAI.GetBridgeState(ref buildingData);

            buildingData.m_customBuffer1 |= MovableBridgeAI.FLAG_SHIP_NEAR_BRIDGE;
            if (passing)
            {
                buildingData.m_customBuffer1 |= MovableBridgeAI.FLAG_SHIP_PASSING_BRIDGE_ANY;
            }
            if (bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_LEFT ||
                bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_RIGHT ||
                bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_BOTH ||
                (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_LEFT && passing) ||
                (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_RIGHT && passing) ||
                (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_BOTH && passing))
            {
                return(float.MaxValue);
            }
            if (!passing)
            {
                return(kPassingSpeed);
            }

            vehicleData.m_blockCounter = 0;

            return(0f);
        }
        private static float HandleMovableBridge(ref Vehicle vehicleData, ushort buildingID, ref Building buildingData, bool passing, bool near1, bool near2, float minY, float maxY, float maxSpeed, float vehicleTopY, Vector2 forwardDir)
        {
            BuildingInfo buildingInfo = buildingData.Info;

            if (!(buildingInfo.m_buildingAI is MovableBridgeAI))
            {
                return(float.MaxValue);
            }

            MovableBridgeAI movableBridgeAi = (MovableBridgeAI)buildingInfo.m_buildingAI;
            float           bridgeClearance = buildingData.m_position.y + movableBridgeAi.m_BridgeClearance;

            if (bridgeClearance > vehicleTopY)
            {
                return(float.MaxValue);
            }

            if (!passing && !near1 && !near2)
            {
                return(float.MaxValue);
            }

            Vector2 buildingForwardDir = new Vector2(Mathf.Sin(buildingData.m_angle), Mathf.Cos(buildingData.m_angle));
            var     dot  = Vector2.Dot(forwardDir, buildingForwardDir);
            bool    left = dot > 0;

            ushort bridgeState = MovableBridgeAI.GetBridgeState(ref buildingData);

            buildingData.m_customBuffer1 |= MovableBridgeAI.FLAG_SHIP_NEAR_BRIDGE;
            if (passing || near1)
            {
                buildingData.m_customBuffer1 |= (left ? MovableBridgeAI.FLAG_SHIP_PASSING_BRIDGE_LEFT : MovableBridgeAI.FLAG_SHIP_PASSING_BRIDGE_RIGHT);
            }

            if (passing)
            {
                return(float.MaxValue);
            }

            if (bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_LEFT ||
                (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_LEFT && near1))
            {
                if (left)
                {
                    return(float.MaxValue);
                }
            }
            else if (bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_RIGHT ||
                     (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_RIGHT && near1))
            {
                if (!left)
                {
                    return(float.MaxValue);
                }
            }
            else if (bridgeState == MovableBridgeAI.STATE_BRIDGE_OPEN_BOTH ||
                     (bridgeState == MovableBridgeAI.STATE_BRIDGE_WAITING_BOTH && near1))
            {
                return(float.MaxValue);
            }

            if (!near1)
            {
                return(kPassingSpeed);
            }

            vehicleData.m_blockCounter = 0;

            return(0f);
        }