I've tried with multiple objects of differing sizes and positions and I've narrowed it down to the IntersectAll function which is called in GamePlayerControl at:
tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx,tffdcy,tffdcz,ttpersonobj)
It seems that for large objects there's an upper limit as to how far from the centre point of the model it can calculate a raycasting hit, and this limit is about 200 ingame units.
This means that when you're more than c200 units from the centre of the model, the IntersectAll stops working an returns a value of 0 (and the camera clipping/movement reverts to the standard camera distance).
However I've solved your problem with the following code as a replacement in the GamePlayerControl:
-- check if this places camera in collision
tthitvalue=0
ttbuffervalue=2
if ( bIgnoreCameraCollision==false ) then
if ( RayTerrain(ttpx,ttpy,ttpz,tffdcx,tffdcy,tffdcz) == 1 ) then tthitvalue = -1 end
if ( RayTerrain(ttpx,ttpy,ttpz,tffdcx-10,tffdcy,tffdcz-10) == 1 ) then tthitvalue = -1 end
if ( RayTerrain(ttpx,ttpy,ttpz,tffdcx-10,tffdcy,tffdcz+10) == 1 ) then tthitvalue = -1 end
if ( RayTerrain(ttpx,ttpy,ttpz,tffdcx+10,tffdcy,tffdcz-10) == 1 ) then tthitvalue = -1 end
if ( RayTerrain(ttpx,ttpy,ttpz,tffdcx+10,tffdcy,tffdcz+10) == 1 ) then tthitvalue = -1 end
if ( tthitvalue == 0 ) then
if (ttpx > tffdcx) then
if (ttpz > tffdcz) then
tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx-ttbuffervalue,tffdcy,tffdcz-ttbuffervalue,ttpersonobj)
else
tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx-ttbuffervalue,tffdcy,tffdcz+ttbuffervalue,ttpersonobj)
end
else
if (ttpz > tffdcz) then
tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx+ttbuffervalue,tffdcy,tffdcz-ttbuffervalue,ttpersonobj)
else
tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx+ttbuffervalue,tffdcy,tffdcz+ttbuffervalue,ttpersonobj)
end
end
-- tthitvalue=IntersectAll(ttpx,ttpy,ttpz,tffdcx,tffdcy,tffdcz,ttpersonobj)
end
end
if ( tthitvalue ~= 0 ) then
if ( tthitvalue == -1 ) then
-- terrain hit
tthitvaluex=GetRayCollisionX()
tthitvaluey=GetRayCollisionY()
tthitvaluez=GetRayCollisionZ()
else
-- entity hit
tthitvaluex=GetIntersectCollisionX()
tthitvaluey=GetIntersectCollisionY()
tthitvaluez=GetIntersectCollisionZ()
end
-- work out new camera position
SetGamePlayerControlCamCollisionSmooth(0)
ttddx=ttpx-tthitvaluex
ttddy=ttpy-tthitvaluey
ttddz=ttpz-tthitvaluez
ttdiff=math.sqrt(math.abs(ttddx*ttddx)+math.abs(ttddy*ttddy)+math.abs(ttddz*ttddz))
if ( ttdiff>12.0 ) then
ttddx=ttddx/ttdiff
ttddy=ttddy/ttdiff
ttddz=ttddz/ttdiff
if (ttpx > tthitvaluex) then
tffdcx=tthitvaluex+(ttddx*5.0)+(1/math.abs(ttddx))
else
tffdcx=tthitvaluex+(ttddx*5.0)-(1/math.abs(ttddx))
end
tffdcy=tthitvaluey+(ttddy*1.0)
if (ttpz > tthitvaluez) then
tffdcz=tthitvaluez+(ttddz*5.0)+(1/math.abs(ttddx))
else
tffdcz=tthitvaluez+(ttddz*5.0)-(1/math.abs(ttddx))
end
SetGamePlayerControlLastGoodcx(tffdcx)
SetGamePlayerControlLastGoodcy(tffdcy)
SetGamePlayerControlLastGoodcz(tffdcz)
SetGamePlayerControlCamCurrentDistance(ttdiff)
SetGamePlayerControlCamDoFullRayCheck(1)
else
tffdcx=GetGamePlayerControlLastGoodcx()
tffdcy=GetGamePlayerControlLastGoodcy()
tffdcz=GetGamePlayerControlLastGoodcz()
end
else
-- this one ensures the full-ray check does not flick the camera to 'full-retract distance'
if ( GetGamePlayerControlCamDoFullRayCheck() == 2 ) then
tffdcx=GetGamePlayerControlLastGoodcx()
tffdcy=GetGamePlayerControlLastGoodcy()
tffdcz=GetGamePlayerControlLastGoodcz()
end
end
Basically what this does it project the camera 2 units further out from the player before checking the intersection with entities. Then when it comes to positioning it, it moves the camera 2 units closer (but slowly reduces this value the closer the camera gets to the player so the transition as the camera swings by is un-noticable).