1486 lines
44 KiB
C++
1486 lines
44 KiB
C++
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Game Source Code
|
|
//
|
|
// File: XEntityVehicle.cpp
|
|
// Description: Entity player vehicle stuff, split into another file
|
|
// to avoid to have everything in xplayer.cpp
|
|
//
|
|
// History:
|
|
// - this file uses code from xplayer.cpp created by petar and kirill
|
|
// - October 09, 2002: this file created by Marco Corbetta
|
|
// - October 11, 2002: major changes to boat/vehicle code by M.C.
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "XPlayer.h"
|
|
#include "XVehicle.h"
|
|
#include "ScriptObjectStream.h"
|
|
#include "WeaponSystemEx.h"
|
|
#include "WeaponClass.h"
|
|
#include <IEntitySystem.h>
|
|
#include <ISound.h>
|
|
#include <IAgent.h>
|
|
|
|
//for cvars
|
|
#include "Game.h"
|
|
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::ProcessVehicleMovements(CXEntityProcessingCmd &ProcessingCmd)
|
|
{
|
|
if ( ProcessingCmd.CheckAction(ACTION_RUNSPRINT) ) // we are in the vehicle - let's cycle to next position if run pressed
|
|
m_pEntity->SendScriptEvent(ScriptEvent_CycleVehiclePos,0);
|
|
if (m_stats.inVehicleState == PVS_DRIVER) // driver - DRIVE!
|
|
m_pVehicle->ProcessMovement(ProcessingCmd);
|
|
}
|
|
|
|
|
|
/*
|
|
//
|
|
// calculates world position of intersection point of weapon ray with something
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CPlayer::Get3DCrosshairPosition( Vec3& pos3D, Vec3& posScr )
|
|
{
|
|
if(m_pVehicle)
|
|
{
|
|
pos3D = m_pVehicle->m_vCross3D;
|
|
if(m_pVehicle->m_bCrossOnScreen)
|
|
{
|
|
posScr = m_pVehicle->m_vCrossScreen;
|
|
// posScr = m_pVehicle->m_vCrossScreenSmoothed;
|
|
}
|
|
else
|
|
{
|
|
posScr.x = -1;
|
|
posScr.y = -1;
|
|
}
|
|
|
|
return m_pVehicle->m_bTargetIsLocked;
|
|
}
|
|
return false;
|
|
}
|
|
*/
|
|
//Attaches the player to a vehicle
|
|
//param pVehicle pointer to a vehicle to which the player should be attached to
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::EnterVehicle( CVehicle *pVehicle, eInVehiclestate state, const char *szHelperName)
|
|
{
|
|
// if the vehicle is not specified or we are already
|
|
// inside a vehicle return
|
|
if ((!pVehicle) || (m_pVehicle))
|
|
return;
|
|
|
|
SwitchFlashLight(false); // switch off flashlight
|
|
|
|
GoStand(); // stand up - maybe was proining
|
|
|
|
// [kirill] GoStand can fail coz of some collisions
|
|
// but we need to force eyeHeight anyway
|
|
pe_player_dimensions dimEyes;
|
|
dimEyes.heightEye = m_PlayerDimNormal.heightEye;
|
|
m_pEntity->GetPhysics()->SetParams( &dimEyes );
|
|
|
|
m_LegAngle = 0.0f;
|
|
m_pVehicle = pVehicle;
|
|
|
|
// add this user to the vechicle
|
|
m_pVehicle->AddUser( m_pEntity->GetId() );
|
|
|
|
m_PrevWeaponID=-1;
|
|
m_stats.inVehicleState = state;
|
|
|
|
if ( (m_pGame->IsMultiplayer() && IsMyPlayer()) || (!m_pGame->IsMultiplayer() && !m_bIsAI ) )
|
|
{
|
|
if (m_stats.inVehicleState==PVS_DRIVER)
|
|
{
|
|
m_sVehicleEyeHelper = "eye_pos";
|
|
m_pVehicle->ResetCamera(true,m_sVehicleEyeHelper.c_str());
|
|
}
|
|
// else if (m_stats.inVehicleState==PVS_GUNNER)
|
|
// m_pVehicle->ResetCamera(true,"gunner_eye_pos");
|
|
else if (m_stats.inVehicleState==PVS_PASSENGER)
|
|
{
|
|
// std::string eye_String(szHelperName);
|
|
// eye_String = eye_String+"_eye_pos";
|
|
m_sVehicleEyeHelper = string(szHelperName)+"_eye_pos";
|
|
m_pVehicle->ResetCamera(true,m_sVehicleEyeHelper.c_str());
|
|
// m_pVehicle->ResetCamera(true,"passenger_eye_pos");
|
|
}
|
|
}
|
|
else // if this is MP server and not local player - keep the helper name to use for shooting
|
|
{
|
|
if (m_stats.inVehicleState==PVS_DRIVER)
|
|
m_sVehicleEyeHelper = "eye_pos";
|
|
else
|
|
m_sVehicleEyeHelper = string(szHelperName)+"_eye_pos";
|
|
}
|
|
|
|
// update weapon usage
|
|
// gunner has prioriti ocer driver
|
|
// passangers don't use vehicle weapon
|
|
//if (m_stats.inVehicleState==PVS_PASSENGER)
|
|
// return; // when passenger - don't change the weapon
|
|
|
|
if( m_stats.inVehicleState == PVS_DRIVER ) // when driver - can't use any weapon
|
|
{
|
|
bool bIsAI = m_pEntity->GetAI() && m_pEntity->GetAI()->GetType()==AIOBJECT_PLAYER;
|
|
m_pVehicle->m_DriverID = m_pEntity->GetId();
|
|
if(bIsAI)
|
|
// user is Player - he can control light
|
|
m_pVehicle->m_bAIDriver = false;
|
|
else
|
|
// user is AI - enable AutoLights
|
|
m_pVehicle->m_bAIDriver = true;
|
|
}
|
|
|
|
/*if( GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName( m_pVehicle->GetWeaponName( PVS_DRIVER)) == -1
|
|
&&
|
|
GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName( m_pVehicle->GetWeaponName( PVS_GUNNER)) == -1)
|
|
return; // it's a vehicle without mounted weapon - don't change/deselect the weapon*/
|
|
|
|
if( (m_pVehicle->GetWeaponName(m_stats.inVehicleState) == "none") ||
|
|
GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName(m_pVehicle->GetWeaponName(m_stats.inVehicleState)) != -1 )
|
|
{
|
|
m_PrevWeaponID = GetSelectedWeaponId();
|
|
|
|
//GetISystem()->GetILog()->Log("last weap id: %i\n", m_PrevWeaponID );
|
|
|
|
SelectWeapon(-1);
|
|
m_pVehicle->SetWeaponUser( m_pEntity->GetId() );
|
|
}
|
|
|
|
InitCameraTransition( PCM_ENTERINGVEHICLE );
|
|
}
|
|
|
|
|
|
// Detaches the player from a vehicle
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::LeaveVehicle()
|
|
{
|
|
//we cannot leave the vehicle if we're not inside
|
|
if (!m_pVehicle)
|
|
return;
|
|
|
|
//filippo: force the player to stand up once he get out from the vehicle,
|
|
//because could happen the player didn't get stand up when entering the vehicle.
|
|
GoStand();
|
|
|
|
m_stats.crosshairOnScreen = true;
|
|
m_sVehicleEyeHelper.clear();
|
|
|
|
m_pVehicle->WeaponState( m_pEntity->GetId(), false );
|
|
if (IsMyPlayer() && (m_stats.inVehicleState==PVS_DRIVER || m_stats.inVehicleState==PVS_PASSENGER))
|
|
m_pVehicle->ResetCamera();
|
|
|
|
InitCameraTransition( PCM_LEAVINVEHICLE );
|
|
|
|
if(m_pVehicle->m_WeaponUser == m_pEntity->GetId())
|
|
m_pVehicle->ReleaseWeaponUser();
|
|
|
|
//filippo reminder: ReleaseWeaponUser call MakeWeaponAvailable that select the first weapon and not the last weapon
|
|
//before enter into the vehicle , so below "ReleaseWeaponUser" we force to select the lastweaponid.
|
|
|
|
// restore weapon you had before entering vehicle
|
|
//[kirill] if this user had autoWeapon - always restore prevWeapon.
|
|
// otherwise - only if there is prev Weapon - to save changed weapon
|
|
if( GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName(m_pVehicle->GetWeaponName(m_stats.inVehicleState)) != -1 )
|
|
{
|
|
//GetISystem()->GetILog()->Log("selecting weap id: %i\n", m_PrevWeaponID );
|
|
SelectWeapon( m_PrevWeaponID );
|
|
}
|
|
else if(m_PrevWeaponID!=-1)
|
|
SelectWeapon( m_PrevWeaponID );
|
|
|
|
|
|
|
|
// if it's gunner leaving the vehicle - enable driver to use autoWeapon
|
|
if( m_stats.inVehicleState == PVS_GUNNER )
|
|
{
|
|
CPlayer *pDriver = m_pVehicle->GetUserInState( PVS_DRIVER );
|
|
if( pDriver )
|
|
m_pVehicle->SetWeaponUser( pDriver->GetEntity()->GetId() );
|
|
}
|
|
|
|
m_stats.inVehicleState = PVS_OUT;
|
|
|
|
m_pVehicle->RemoveUser( GetEntity()->GetId() );
|
|
|
|
// don't have vehicle anymore
|
|
m_pVehicle = NULL;
|
|
}
|
|
|
|
|
|
void DemperAngl( Vec3d& current, const Vec3d& target, float tScale )
|
|
{
|
|
//Vec3d v = (target - current)*tScale*dempCoeff;
|
|
Vec3d diff = (target - current);//*tScale*dempCoeff;
|
|
Vec3d v;
|
|
|
|
diff.x = Snap_s180(diff.x);
|
|
diff.y = Snap_s180(diff.y);
|
|
diff.z = Snap_s180(diff.z);
|
|
|
|
float maxDelta = fabs(diff.x);
|
|
if(maxDelta < fabs(diff.y) )
|
|
maxDelta = fabs(diff.y);
|
|
if(maxDelta < fabs(diff.z) )
|
|
maxDelta = fabs(diff.z);
|
|
tScale *= maxDelta;
|
|
|
|
v = diff;
|
|
v.Normalize();
|
|
v*=tScale;
|
|
if( fabs(diff.x)<fabs(v.x) )
|
|
current.x = target.x;
|
|
else
|
|
current.x += v.x;
|
|
if( fabs(diff.y)<fabs(v.y) )
|
|
current.y = target.y;
|
|
else
|
|
current.y += v.y;
|
|
if( fabs(diff.z)<fabs(v.z) )
|
|
current.z = target.z;
|
|
else
|
|
current.z += v.z;
|
|
}
|
|
|
|
|
|
void DemperVec( Vec3d& current, const Vec3d& target, float tScale )
|
|
{
|
|
//Vec3d v = (target - current)*tScale*dempCoeff;
|
|
Vec3d diff = (target - current);//*tScale*dempCoeff;
|
|
Vec3d v;
|
|
|
|
// float maxDelta = fabs(diff.x);
|
|
// if(maxDelta < fabs(diff.y) )
|
|
// maxDelta = fabs(diff.y);
|
|
// if(maxDelta < fabs(diff.z) )
|
|
// maxDelta = fabs(diff.z);
|
|
// tScale *= maxDelta;
|
|
|
|
v = diff;
|
|
v.Normalize();
|
|
v*=tScale;
|
|
if( fabs(diff.x)<fabs(v.x) )
|
|
current.x = target.x;
|
|
else
|
|
current.x += v.x;
|
|
if( fabs(diff.y)<fabs(v.y) )
|
|
current.y = target.y;
|
|
else
|
|
current.y += v.y;
|
|
if( fabs(diff.z)<fabs(v.z) )
|
|
current.z = target.z;
|
|
else
|
|
current.z += v.z;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::UpdateBoatCamera()
|
|
{
|
|
IEntityCamera *camera = m_pEntity->GetCamera();
|
|
IEntity *car = m_pVehicle->GetEntity();
|
|
Vec3d pos = car->GetPos();
|
|
Vec3d angles = car->GetAngles();
|
|
//static Vec3d prevCarAng=Vec3d(0,0,0);
|
|
|
|
if (m_bFirstPerson)
|
|
{
|
|
// first person
|
|
|
|
// set default in case we miss the helper for first person
|
|
Vec3d vEyePos=m_vEyePos;
|
|
|
|
if (car)
|
|
{
|
|
//Vec3d vPos;
|
|
|
|
// check if we are the driver or the passenger
|
|
// and set the camera position accordingly
|
|
/*if (m_stats.inVehicleState == PVS_DRIVER) // this is a driver
|
|
car->GetHelperPosition("eye_pos",vPos);
|
|
else if (m_stats.inVehicleState == PVS_PASSENGER) // this is a passenger
|
|
car->GetHelperPosition("passenger_eye_pos",vPos); */
|
|
|
|
//vPos = m_pVehicle->GetCamPos();
|
|
if (m_stats.inVehicleState==PVS_DRIVER || m_stats.inVehicleState==PVS_PASSENGER)
|
|
//vPos = m_pVehicle->GetCamPos();
|
|
vEyePos = m_pVehicle->GetCamPos();
|
|
else
|
|
{ // this is gunner at mounted weapon
|
|
//[kirill] ok - no any additional extracalculations for camera position of gunner
|
|
/*
|
|
// m_vEyeAngles=m_pEntity->GetAngles();
|
|
Vec3d pos = camera->GetCamOffset();
|
|
if(m_pVehicle->IsBoat())
|
|
pos.z = 1.3f;
|
|
|
|
Matrix44 matParent;
|
|
matParent.SetIdentity();
|
|
matParent=GetRotationZYX44(-gf_DEGTORAD*m_pVehicle->GetEntity()->GetAngles())*matParent; //NOTE: angles in radians and negated
|
|
pos = matParent.TransformVectorOLD( pos );
|
|
|
|
Vec3d posWpn = Vec3(0,.5,0);
|
|
Matrix44 matWpn;
|
|
matWpn.SetIdentity();
|
|
matWpn=GetRotationZYX44(-gf_DEGTORAD*GetEntity()->GetAngles())*matWpn; //NOTE: angles in radians and negated
|
|
posWpn = matWpn.TransformVectorOLD( posWpn );
|
|
|
|
camera->SetPos(m_pEntity->GetPos() + pos + posWpn);
|
|
*/
|
|
//vPos = m_vEyePos;
|
|
vEyePos = m_vEyePos;//filippo:smooth camera also for gunner.
|
|
//camera->SetPos(m_vEyePos);
|
|
//camera->SetAngles(m_vEyeAngles);
|
|
//return;
|
|
// car->GetHelperPosition("passenger_eye_pos",vPos);
|
|
}
|
|
|
|
// if (vPos!=Vec3d(0,0,0))
|
|
//if (!IsEquivalent(vPos,Vec3d(0,0,0)))
|
|
// vEyePos=vPos;
|
|
}
|
|
|
|
// camera->SetPos(vEyePos);
|
|
// camera->SetAngles(m_vEyeAngles);
|
|
|
|
|
|
switch(m_CameraMode)
|
|
{
|
|
case PCM_ENTERINGVEHICLE:
|
|
UpdateCameraTransition( vEyePos );
|
|
break;
|
|
case PCM_INVEHICLE:
|
|
{
|
|
float fCurTime = m_pGame->GetSystem()->GetIPhysicalWorld()->GetPhysicsTime();
|
|
if (m_pGame->IsMultiplayer() && m_pGame->UseFixedStep())
|
|
m_pGame->SnapTime(fCurTime);
|
|
float timeScale = min(0.1f,fCurTime-m_fLastCamUpdateTime);//m_pTimer->GetFrameTime();
|
|
m_fLastCamUpdateTime = fCurTime;
|
|
Vec3 targetAngle = car->GetAngles();
|
|
targetAngle.x = Snap_s180(targetAngle.x);
|
|
targetAngle.y = Snap_s180(targetAngle.y);
|
|
targetAngle.z = Snap_s180(targetAngle.z);
|
|
|
|
m_vCurAngleParent.x = Snap_s180(m_vCurAngleParent.x);
|
|
m_vCurAngleParent.y = Snap_s180(m_vCurAngleParent.y);
|
|
m_vCurAngleParent.z = Snap_s180(m_vCurAngleParent.z);
|
|
|
|
DemperAngl( m_vCurAngleParent, targetAngle, timeScale*m_pGame->p_CameraSmoothScale->GetFVal() );
|
|
// do all the bound entity calculations again - to applay newely set parents angles
|
|
Matrix44 mat=Matrix34::CreateRotationXYZ( Deg2Rad(m_vCurAngleParent),car->GetPos());
|
|
mat=GetTransposed44(mat);
|
|
GetEntity()->SetParentLocale(mat);
|
|
GetEntity()->CalculateInWorld();
|
|
m_vEyeAngles = GetEntity()->GetAngles();
|
|
|
|
m_vCurCamposVhcl = vEyePos;
|
|
m_vCurAngleVhcl = m_vEyeAngles + m_walkParams.shakeAOffset;
|
|
|
|
/*
|
|
// m_vCurCamposVhcl = vEyePos;
|
|
// DemperVec( m_vCurCamposVhcl, vEyePos, timeScale*20.0f );
|
|
|
|
// DemperVec( m_vCurCamposVhcl, vEyePos, timeScale*10.0f );
|
|
Vec3 delta = vEyePos - m_vCurCamposVhcl;
|
|
float fDelta = delta.len2();
|
|
float maxD=2.2f;
|
|
|
|
if(fDelta>maxD*maxD )
|
|
{
|
|
delta.normalize();
|
|
m_vCurCamposVhcl = vEyePos-delta*maxD;
|
|
}
|
|
else if(fDelta>0.0f)
|
|
{
|
|
fDelta = fDelta*timeScale*10.0f;
|
|
if(fDelta > 1.0f)
|
|
m_vCurCamposVhcl = vEyePos;
|
|
else
|
|
m_vCurCamposVhcl += delta*fDelta;
|
|
// m_vCurCamposVhcl += delta*timeScale*100.0f;
|
|
// m_vCurCamposVhcl += delta;
|
|
|
|
// m_vCurCamposVhcl = vEyePos;
|
|
/*
|
|
float timeTotal = .1f/(fDelta + 1.0f);
|
|
|
|
if( timeTotal<timeScale )
|
|
m_vCurCamposVhcl = vEyePos;
|
|
else
|
|
{
|
|
Vec3 dDelta = (delta/timeTotal)*timeScale;
|
|
if(fabs(dDelta.x)>fabs(delta.x) || fabs(dDelta.y)>fabs(delta.y) ||fabs(dDelta.z)>fabs(delta.z))
|
|
m_vCurCamposVhcl = vEyePos;
|
|
else
|
|
m_vCurCamposVhcl += dDelta;
|
|
}
|
|
*/
|
|
/*
|
|
}
|
|
// m_vCurCamposVhcl = vEyePos;
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
|
|
|
|
m_walkParams.shakeLElapsedTime += m_pTimer->GetFrameTime();
|
|
if(m_walkParams.shakeLElapsedTime < m_walkParams.shakeLTime)
|
|
{
|
|
float amplScale = ( 1.0f - ( m_walkParams.shakeLElapsedTime / m_walkParams.shakeLTime ) );
|
|
|
|
m_walkParams.shakeLOffset.x = m_walkParams.shakeLAmpl.x*amplScale*Fsin(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.x*6.283185307179586476925286766559f);
|
|
m_walkParams.shakeLOffset.y = m_walkParams.shakeLAmpl.y*amplScale*Fcos(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.y*6.283185307179586476925286766559f);
|
|
m_walkParams.shakeLOffset.z = m_walkParams.shakeLAmpl.z*amplScale*Fsin(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.z*6.283185307179586476925286766559f + 1.13f);
|
|
|
|
Vec3d shakeAAmpl=Vec3d(60, 30, 30);
|
|
shakeAAmpl = shakeAAmpl*m_walkParams.shakeLAmpl.z;
|
|
|
|
m_walkParams.shakeAOffset.x = shakeAAmpl.x*amplScale*Fsin(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.x*6.283185307179586476925286766559f);
|
|
m_walkParams.shakeAOffset.y = shakeAAmpl.y*amplScale*Fcos(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.y*6.283185307179586476925286766559f);
|
|
m_walkParams.shakeAOffset.z = shakeAAmpl.z*amplScale*Fsin(m_walkParams.shakeLElapsedTime*m_walkParams.shakeLFreq.z*6.283185307179586476925286766559f + 1.13f);
|
|
}
|
|
else
|
|
{
|
|
m_walkParams.shakeAOffset = Vec3d(0,0,0);
|
|
m_walkParams.shakeLOffset = Vec3d(0,0,0);
|
|
m_walkParams.shakeLElapsedTime = m_walkParams.shakeLTime;
|
|
}
|
|
|
|
// m_vCurCamposVhcl = vEyePos + m_walkParams.shakeLOffset;
|
|
m_vCurAngleVhcl = m_vEyeAngles + m_walkParams.shakeAOffset;
|
|
*/
|
|
}
|
|
break;
|
|
}
|
|
camera->SetPos(m_vCurCamposVhcl);
|
|
|
|
camera->SetAngles(m_vCurAngleVhcl);
|
|
|
|
//camera->SetAngles(m_vEyeAngles);
|
|
|
|
return;
|
|
}
|
|
|
|
// third person mode uses one of the different cameras
|
|
switch(m_pGame->b_camera->GetIVal())
|
|
{
|
|
case 0:
|
|
{
|
|
angles.x = 1;
|
|
angles.y = 1;
|
|
IPhysicalEntity *physEnt = car->GetPhysics();
|
|
camera->SetCameraOffset(Vec3d(0,m_pGame->cl_ThirdPersonRange->GetFVal(),m_pGame->cl_ThirdPersonRange->GetFVal()));
|
|
camera->SetCameraMode(pos,angles+m_pEntity->GetAngles(), physEnt);
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
camera->SetAngles(angles+m_pEntity->GetAngles());
|
|
pos.z += 4;
|
|
camera->SetPos(pos);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
Vec3d camPos;
|
|
Vec3d cang;
|
|
angles=ConvertToRadAngles(angles);
|
|
angles.z=0;
|
|
angles.Normalize();
|
|
camPos = pos - Vec3d(angles.y, -angles.x, 0.0f)*25;
|
|
camPos.z = m_pGame->GetSystem()->GetI3DEngine()->GetWaterLevel(m_pEntity) + 8.0f;
|
|
cang = pos - camPos;
|
|
cang=ConvertVectorToCameraAngles(cang);
|
|
camera->SetAngles(cang+m_pEntity->GetAngles());
|
|
camera->SetPos(camPos);
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
Vec3d camPos;
|
|
Vec3d cang;
|
|
angles=ConvertToRadAngles(angles);
|
|
angles.z=0;
|
|
angles.Normalize();
|
|
camPos = pos - Vec3d(angles.x, angles.y, 0.0f)*25;
|
|
camPos.z = m_pGame->GetSystem()->GetI3DEngine()->GetWaterLevel(m_pEntity) + 8.0f;
|
|
cang = pos - camPos;
|
|
cang=ConvertVectorToCameraAngles(cang);
|
|
camera->SetAngles(cang+m_pEntity->GetAngles());
|
|
camera->SetPos(camPos);
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
if(!UpdateBonesPtrs( ))
|
|
return;
|
|
|
|
Matrix44 m;
|
|
m.SetIdentity();
|
|
m=Matrix44::CreateRotationZYX(-angles*gf_DEGTORAD)*m; //NOTE: angles in radians and negated
|
|
|
|
angles.x = 0.0f;
|
|
angles.y = 0.0f;
|
|
camera->SetAngles(angles+m_pEntity->GetAngles());
|
|
pos = m_pBoneHead->GetBonePosition();
|
|
pos.z += .2f;
|
|
pos.y += .3f;
|
|
|
|
pos = m.TransformVectorOLD( pos );
|
|
//pos = GetTransposed44(m)*( pos );
|
|
|
|
pos += GetEntity()->GetPos();
|
|
pos.z += .3f;
|
|
camera->SetPos(pos);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::InitCameraTransition( e_PCM mode, bool OnlyZtransition)
|
|
{
|
|
m_bCameraTransitionOnlyZ = OnlyZtransition;
|
|
|
|
switch( mode )
|
|
{
|
|
case PCM_ENTERINGVEHICLE:
|
|
|
|
m_CameraMode = PCM_ENTERINGVEHICLE;
|
|
m_fCameraTime = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
// m_fCameraTime = 0.0f;
|
|
|
|
|
|
// check if camera will go through something while transmitting. If yes - make
|
|
// transmition very fast (immidiate)
|
|
{
|
|
Vec3 vEyeDestPos = m_pVehicle->GetCamPos();
|
|
if (m_stats.inVehicleState==PVS_GUNNER)
|
|
vEyeDestPos = CalcLeanOffset(0.0f);
|
|
ray_hit RayHit;
|
|
if (m_pGame->GetSystem()->GetIPhysicalWorld()->RayWorldIntersection(vEyeDestPos, m_vEyePos - vEyeDestPos,
|
|
ent_all,0, &RayHit, 1, GetEntity()->GetPhysics()))
|
|
m_fCameraTime = 0.1f;
|
|
}
|
|
|
|
//filippo:if m_bLastDeltaEyeVehicle is true means the player is changing sit position, so use the right eye position.
|
|
if (m_bLastDeltaEyeVehicle && m_pVehicle)
|
|
{
|
|
m_vCurCamposVhcl = m_pVehicle->GetEntity()->GetPos() - m_vDeltaEyeVehicle;
|
|
m_bLastDeltaEyeVehicle = false;
|
|
}
|
|
else
|
|
m_vCurCamposVhcl = m_vEyePos;
|
|
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
|
|
//filippo
|
|
if (m_pVehicle)
|
|
m_vDeltaEyeVehicle = m_pVehicle->GetEntity()->GetPos() - m_vCurCamposVhcl;
|
|
|
|
//m_vCurCamposVhcl = GetEntity()->GetPos();
|
|
|
|
break;
|
|
case PCM_LEAVINVEHICLE:
|
|
{
|
|
//filippo:when leave the vehicle store the delta from car pos and eye pos; because if we are changing sit position we need to know the last eye position for a smooth view transition.
|
|
if (m_pVehicle)
|
|
{
|
|
m_vDeltaEyeVehicle = m_pVehicle->GetEntity()->GetPos() - m_vCurCamposVhcl;
|
|
m_bLastDeltaEyeVehicle = true;
|
|
}
|
|
|
|
m_CameraMode = PCM_CASUAL;
|
|
|
|
float velScale = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
IPhysicalEntity *icar = m_pVehicle->GetEntity()->GetPhysics();
|
|
|
|
if(icar) // is phisycalized
|
|
{
|
|
float timeVelCoeff=m_pGame->p_CameraSmoothVLimit->GetFVal();
|
|
pe_status_dynamics status;
|
|
icar->GetStatus(&status);
|
|
velScale = status.v.len();
|
|
if(velScale>timeVelCoeff)
|
|
velScale = timeVelCoeff;
|
|
velScale = m_pGame->p_CameraSmoothTime->GetFVal()*(timeVelCoeff-velScale)/timeVelCoeff;
|
|
}
|
|
// m_fCameraTime = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
m_fCameraTime = velScale;
|
|
}
|
|
break;
|
|
case PCM_CASUAL:
|
|
{
|
|
m_CameraMode = PCM_CASUAL;
|
|
|
|
if(m_fCameraTime >= 0.1f)
|
|
break;
|
|
float velScale = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
m_vCurCamposVhcl = m_vEyePos;
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
// m_fCameraTime = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
m_fCameraTime = velScale*.5f;
|
|
}
|
|
break;
|
|
}
|
|
/*
|
|
if( bEntering )
|
|
{
|
|
m_CameraMode = PCM_ENTERINGVEHICLE;
|
|
m_fCameraTime = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
m_vCurCamposVhcl = m_vEyePos;
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
}
|
|
else
|
|
{
|
|
m_CameraMode = PCM_LEAVINVEHICLE;
|
|
|
|
float velScale = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
IPhysicalEntity *icar = m_pVehicle->GetEntity()->GetPhysics();
|
|
|
|
if(icar) // is phisycalized
|
|
{
|
|
float timeVelCoeff=m_pGame->p_CameraSmoothVLimit->GetFVal();
|
|
pe_status_dynamics status;
|
|
icar->GetStatus(&status);
|
|
velScale = status.v.len();
|
|
if(velScale>timeVelCoeff)
|
|
velScale = timeVelCoeff;
|
|
velScale = m_pGame->p_CameraSmoothTime->GetFVal()*(timeVelCoeff-velScale)/timeVelCoeff;
|
|
}
|
|
// m_fCameraTime = m_pGame->p_CameraSmoothTime->GetFVal();
|
|
m_fCameraTime = velScale;
|
|
// m_fCameraTime = .6f;
|
|
// m_vCurCamposVhcl = m_vEyePos;
|
|
// m_vCurAngleVhcl = m_vEyeAngles;
|
|
}
|
|
*/
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::UpdateCameraTransition( const Vec3& vEyePos )
|
|
{
|
|
float timeScale = m_pTimer->GetFrameTime();
|
|
if( timeScale>.1f )
|
|
timeScale = .1f;
|
|
|
|
//filippo: smooth only Z eyepos component if player is outside vehicles;
|
|
//this because otherwise when you crouch/standup your view (position&rotaion) would lag because the smoothing,
|
|
//for vehicles this is OK, but not for standard player movement.
|
|
/*bool bSmoothOnlyZ = false;
|
|
if(m_CameraMode == PCM_CASUAL && !m_bLastDeltaEyeVehicle)
|
|
bSmoothOnlyZ = true;*/
|
|
|
|
//filippo
|
|
if (m_pVehicle)
|
|
m_vCurCamposVhcl = m_pVehicle->GetEntity()->GetPos() - m_vDeltaEyeVehicle;
|
|
|
|
Vec3 delta = vEyePos - m_vCurCamposVhcl;
|
|
//Vec3 deltap = delta;
|
|
|
|
// do not smooth if it's too far
|
|
// just set the position/angles
|
|
if( delta.len2()>100 )
|
|
m_fCameraTime = timeScale*.1f;
|
|
|
|
m_vCurCamposVhcl += (delta/m_fCameraTime)*timeScale;
|
|
//m_vCurCamposVhcl += delta*5.0f*timeScale;
|
|
|
|
//filippo
|
|
if (m_pVehicle)
|
|
m_vDeltaEyeVehicle = m_pVehicle->GetEntity()->GetPos() - m_vCurCamposVhcl;
|
|
|
|
m_vEyeAngles.x = Snap_s180(m_vEyeAngles.x);
|
|
m_vEyeAngles.y = Snap_s180(m_vEyeAngles.y);
|
|
m_vEyeAngles.z = Snap_s180(m_vEyeAngles.z);
|
|
|
|
//if (!bSmoothOnlyZ)
|
|
if (!m_bCameraTransitionOnlyZ)
|
|
{
|
|
m_vCurAngleVhcl.x = Snap_s180(m_vCurAngleVhcl.x);
|
|
m_vCurAngleVhcl.y = Snap_s180(m_vCurAngleVhcl.y);
|
|
m_vCurAngleVhcl.z = Snap_s180(m_vCurAngleVhcl.z);
|
|
|
|
delta = (m_vEyeAngles - m_vCurAngleVhcl);//*tScale*dempCoeff;
|
|
|
|
delta.x = Snap_s180(delta.x);
|
|
delta.y = Snap_s180(delta.y);
|
|
delta.z = Snap_s180(delta.z);
|
|
|
|
m_vCurAngleVhcl += (delta/m_fCameraTime)*timeScale;
|
|
//m_vCurAngleVhcl += delta*5.0f*timeScale;
|
|
}
|
|
else
|
|
{
|
|
//just use the player angles and the smoothed pos.Z component
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
m_vCurCamposVhcl.x = vEyePos.x;
|
|
m_vCurCamposVhcl.y = vEyePos.y;
|
|
}
|
|
|
|
if( (m_fCameraTime -= timeScale) <= 0 )
|
|
//if(deltap.len2()<=0.001f)
|
|
{
|
|
m_vCurCamposVhcl = vEyePos;
|
|
m_vCurAngleVhcl = m_vEyeAngles;
|
|
|
|
if(m_CameraMode == PCM_ENTERINGVEHICLE)
|
|
{
|
|
m_vCurAngleParent = m_pVehicle->GetEntity()->GetAngles();
|
|
m_CameraMode = PCM_INVEHICLE;
|
|
|
|
//filippo
|
|
if (m_pVehicle)
|
|
m_vDeltaEyeVehicle = m_pVehicle->GetEntity()->GetPos() - m_vCurCamposVhcl;
|
|
}
|
|
else if(m_CameraMode == PCM_CASUAL)
|
|
{
|
|
m_CameraMode = PCM_OUTVEHICLE;
|
|
|
|
//filippo
|
|
m_bLastDeltaEyeVehicle = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::UpdateAutoCenter()
|
|
{
|
|
// it works only in vehicles
|
|
if(!m_pVehicle)
|
|
return;
|
|
|
|
float timeScale = m_pTimer->GetFrameTime();
|
|
Vec3 curAngl = m_pEntity->GetAngles(1);
|
|
|
|
m_fProcessTime += timeScale;
|
|
|
|
curAngl.x = Snap_s180(curAngl.x);
|
|
curAngl.y = Snap_s180(curAngl.y);
|
|
curAngl.z = Snap_s180(curAngl.z);
|
|
|
|
if(m_AutoCenter == 0)
|
|
{
|
|
if(!m_bMouseMoved)
|
|
m_fNoChangeangleTime += timeScale;
|
|
else
|
|
m_fNoChangeangleTime = 0.0f;
|
|
|
|
if(m_fNoChangeangleTime>m_pGame->p_AutoCenterDelay->GetFVal())
|
|
StartAutoCenter( true );
|
|
return;
|
|
}
|
|
if(m_bMouseMoved)
|
|
{
|
|
ResetAutoCenter();
|
|
return;
|
|
}
|
|
float trh=.10f;
|
|
if( curAngl.x < trh && curAngl.x > -trh &&
|
|
curAngl.y < trh && curAngl.y > -trh &&
|
|
(m_AutoCenter==2 && curAngl.z < trh && curAngl.z > -trh ||
|
|
m_AutoCenter==1 && curAngl.z > 180.0f-trh && curAngl.z < -180.0f+trh)
|
|
)
|
|
{
|
|
curAngl.Set(0,0,0);
|
|
m_pEntity->SetAngles( curAngl );
|
|
ResetAutoCenter();
|
|
return;
|
|
}
|
|
|
|
timeScale *= m_pGame->p_AutoCenterSpeed->GetFVal();
|
|
float velScale = m_pGame->p_AutoCenterSpeed->GetFVal();
|
|
velScale = 100.0f - velScale;
|
|
if(velScale<0.0f)
|
|
velScale = 0.0f;
|
|
else if(velScale>=100.0f)
|
|
velScale = 99.9f;
|
|
|
|
velScale = (70.0f + velScale*0.3f)/100.0f;
|
|
|
|
|
|
timeScale = m_pGame->p_AutoCenterSpeed->GetFVal()/100.0f;
|
|
// don't want to move too slow
|
|
if( timeScale>.999f )
|
|
timeScale = .999f;
|
|
|
|
timeScale = velScale;
|
|
|
|
|
|
if(m_AutoCenter == 1) // going to z 180
|
|
{
|
|
curAngl.x = curAngl.x*timeScale;
|
|
curAngl.y = curAngl.y*timeScale;
|
|
if(curAngl.z<0.0f)
|
|
curAngl.z += (-180.0f-curAngl.z)*(1.0f-timeScale);
|
|
else
|
|
curAngl.z += (180.0f-curAngl.z)*(1.0f-timeScale);
|
|
}
|
|
else // going to z 0
|
|
curAngl = curAngl*timeScale;
|
|
|
|
m_pEntity->SetAngles( curAngl );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::StartAutoCenter(bool forward)
|
|
{
|
|
Vec3 curAngl = m_pEntity->GetAngles(1);
|
|
|
|
// we don't want it to flip back and forth - so make time thrashold
|
|
if( m_fProcessTime < .5f)
|
|
return;
|
|
|
|
m_fProcessTime = 0.0f;
|
|
curAngl.x = Snap_s180(curAngl.x);
|
|
curAngl.y = Snap_s180(curAngl.y);
|
|
curAngl.z = Snap_s180(curAngl.z);
|
|
|
|
if(forward)
|
|
m_AutoCenter = 1;
|
|
else
|
|
{
|
|
//[kirill] if angles are limited - only autorotate forward
|
|
if( m_AngleLimitHFlag )
|
|
m_AutoCenter = 1;
|
|
else if( fabs(curAngl.z)<90.0f )
|
|
m_AutoCenter = 1;
|
|
else
|
|
m_AutoCenter = 2;
|
|
}
|
|
|
|
// make it flip randomly in different direstions if it's 180 turn
|
|
// if(curAngl.z == 0.0f)
|
|
if(curAngl.z<0.5f && curAngl.z>-0.5f)
|
|
{
|
|
if(rand()%100<50)
|
|
curAngl.z += .01f;
|
|
else
|
|
curAngl.z -= .01f;
|
|
}
|
|
else if(curAngl.z > 179.5f)
|
|
{
|
|
if(rand()%100<50)
|
|
curAngl.z = -179.99f;
|
|
else
|
|
curAngl.z -= .01f;
|
|
}
|
|
else if(curAngl.z < -179.5f)
|
|
{
|
|
if(rand()%100<50)
|
|
curAngl.z = 179.99f;
|
|
else
|
|
curAngl.z += .01f;
|
|
}
|
|
// m_pEntity->SetAngles( curAngl );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CPlayer::ResetAutoCenter()
|
|
{
|
|
m_AutoCenter = 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CXGame::InitVehicleCvars()
|
|
{
|
|
IConsole *pConsole = m_pSystem->GetIConsole();
|
|
|
|
//*
|
|
//Dumprot 9000.4
|
|
//Dumpv 1500.4
|
|
//Turn 12000.0
|
|
//Speedv 35000.0
|
|
//Speedturnmin 5.0
|
|
|
|
b_dump = pConsole->CreateVariable("b_dump","2000.4",0,"This variable is not used.");
|
|
b_dumpRot = pConsole->CreateVariable("b_dumprot","9000.4",0,"This variable is not used.");
|
|
b_dumpV = pConsole->CreateVariable("b_dumpv","1500.4",0,"This variable is not used.");
|
|
b_dumpVH = pConsole->CreateVariable("b_dumpvh","10000.4",0,"This variable is not used.");
|
|
b_stand = pConsole->CreateVariable("b_stand","10000.5",0,"This variable is not used.");
|
|
b_turn = pConsole->CreateVariable("b_turn","12000.0",0,"This variable is not used.");
|
|
b_tilt = pConsole->CreateVariable("b_tilt","2.0",0,"This variable is not used.");
|
|
b_speedV = pConsole->CreateVariable("b_speedv","35000.0",0,"This variable is not used.");
|
|
b_accelerationV = pConsole->CreateVariable("b_accelerationv","100000.0",0,"This variable is not used.");
|
|
b_speedMinTurn = pConsole->CreateVariable("b_speedminturn","5.0",0,"This variable is not used.");
|
|
b_float = pConsole->CreateVariable("b_float","7",0,"This variable is not used.");
|
|
b_wscale = pConsole->CreateVariable("b_wscale","2.1",0,"This variable is not used.");
|
|
b_wscalew = pConsole->CreateVariable("b_wscalew","2.1",0,"This variable is not used.");
|
|
b_wmomentum = pConsole->CreateVariable("b_wmomentum","500.5",0,"This variable is not used.");
|
|
//*/
|
|
b_camera = pConsole->CreateVariable("b_camera","0",0,"This variable is not used.");
|
|
|
|
p_CameraSmoothTime = pConsole->CreateVariable("p_camerasmoothtime",".6",0,"when entering/leaving vehicles.");
|
|
p_CameraSmoothScale = pConsole->CreateVariable("p_camerasmoothscale","5",0,"when driving vehicles.");
|
|
p_CameraSmoothVLimit = pConsole->CreateVariable("p_camerasmoothvlimit","20",0,"camera transition scale to vehicle speed when leaving moving vehicles.");
|
|
|
|
p_LeaveVehicleImpuls = pConsole->CreateVariable("p_leavevehicleimpuls","20",0,"impilse scale to vehicle speed when leaving moving vehicles.");
|
|
p_LeaveVehicleBrake = pConsole->CreateVariable("p_leavevehiclebrake","10",0,"speed thrashold to have breaks on when driver is out");
|
|
p_LeaveVehicleBrakeDelay = pConsole->CreateVariable("p_leavevehiclebrakedelay","2",0,"delay before wehicle stops after driver out is out");
|
|
|
|
p_AutoCenterDelay = pConsole->CreateVariable("p_autocenterdelay","30",0,"idle time before force autoCenter");
|
|
p_AutoCenterSpeed = pConsole->CreateVariable("p_autocenterspeed","20",0,"speed of autoCentering - inverted (the bigger - the slower)");
|
|
|
|
// show bboxes for static objects below helicopter
|
|
h_drawbelow = pConsole->CreateVariable("h_drawbelow","0",0,
|
|
"Toggles bounding boxes below helicopters.\n"
|
|
"Usage: h_drawbelow [0/1]\n"
|
|
"Default is 0 (off). Set 1 to display the bounding\n"
|
|
"boxes of obstacles currently below a helicopter.");
|
|
}
|
|
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------
|
|
// draving weapon on the vehicle here - weapon is a character in slot 0
|
|
void CVehicle::OnDraw(const SRendParams & rParms)
|
|
{
|
|
// draw animated component
|
|
|
|
ICryCharInstance *cmodel = m_pEntity->GetCharInterface()->GetCharacter(0);
|
|
if (cmodel && (cmodel->GetFlags()&CS_FLAG_DRAW_MODEL))
|
|
{
|
|
SRendParams RenderParams = rParms;
|
|
// we want it to recalculate the matrix
|
|
RenderParams.pMatrix = NULL;
|
|
RenderParams.vAngles = m_vWpnAng;
|
|
//RenderParams.vAngles.z = 90.0f;
|
|
// RenderParams.vAngles.x = -RenderParams.vAngles.x;
|
|
// RenderParams.vAngles.y = -RenderParams.vAngles.y;
|
|
// RenderParams.vAngles = m_vWpnAng;
|
|
GetEntity()->GetHelperPosition("gun",RenderParams.vPos,false);
|
|
// RenderParams.vPos = m_pEntity->GetPos() + Vec3(0,0,3);
|
|
cmodel->Draw(RenderParams,Vec3(zero));
|
|
}
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------------------------------------
|
|
CPlayer* CVehicle::GetUserInState( CPlayer::eInVehiclestate state )
|
|
{
|
|
UsersList::iterator curUser;
|
|
for(curUser=m_UsersList.begin(); curUser!=m_UsersList.end(); ++curUser)
|
|
{
|
|
IEntity *pCurUserEntity = m_pGame->GetSystem()->GetIEntitySystem()->GetEntity( *curUser );
|
|
CPlayer *pCurUserPlayer;
|
|
if( pCurUserEntity &&
|
|
pCurUserEntity->GetContainer() &&
|
|
pCurUserEntity->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&pCurUserPlayer) &&
|
|
pCurUserPlayer->m_stats.inVehicleState == state)
|
|
return pCurUserPlayer;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------------------------------------
|
|
CPlayer* CVehicle::GetWeaponUser( )
|
|
{
|
|
IEntity *pCurUserEntity = m_pGame->GetSystem()->GetIEntitySystem()->GetEntity( m_WeaponUser );
|
|
CPlayer *pCurUserPlayer;
|
|
if( pCurUserEntity &&
|
|
pCurUserEntity->GetContainer() &&
|
|
pCurUserEntity->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&pCurUserPlayer) )
|
|
return pCurUserPlayer;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------
|
|
void CVehicle::SetWeaponUser(int entId)
|
|
{
|
|
CPlayer *shooter = GetWeaponUser();
|
|
// there is a gunner - has priority on weapon usage
|
|
if( shooter && shooter->m_stats.inVehicleState == CPlayer::PVS_GUNNER )
|
|
return;
|
|
ReleaseWeaponUser( true );
|
|
|
|
m_WeaponUser = entId;
|
|
IEntity *pCurUserEntity = m_pGame->GetSystem()->GetIEntitySystem()->GetEntity( m_WeaponUser );
|
|
if( pCurUserEntity &&
|
|
pCurUserEntity->GetContainer() &&
|
|
pCurUserEntity->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&shooter) )
|
|
{
|
|
int wpnId = GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName( GetWeaponName( shooter->m_stats.inVehicleState ) );
|
|
if( wpnId != -1 )
|
|
{
|
|
// shooter->m_PrevWeaponID=shooter->GetSelectedWeaponId();
|
|
shooter->MakeWeaponAvailable(wpnId, true);
|
|
shooter->SelectWeapon(wpnId);
|
|
//[kirill]
|
|
//this is needed to fix problem with quickLoad - the weapon was reset to 0 firemode
|
|
//- Mounted guns on vehicles that have 2 firemodes are reset to MG after ql even if rockets were used
|
|
if(m_pGame->m_bIsLoadingLevelFromFile)
|
|
shooter->SwitchFiremode(shooter->m_stats.firemode);
|
|
else
|
|
shooter->SwitchFiremode(0);
|
|
}
|
|
|
|
if( shooter->m_stats.inVehicleState == CPlayer::PVS_GUNNER ) // when driver - can't use any weapon
|
|
{
|
|
// set to gunner agle limits from the weapon
|
|
shooter->SetAngleLimitBase( Vec3(0,0,180) );
|
|
if(m_AngleLimitVFlag)
|
|
{
|
|
shooter->EnableAngleLimitV(1);
|
|
shooter->SetMinAngleLimitV(m_MinVAngle);
|
|
shooter->SetMaxAngleLimitV(m_MaxVAngle);
|
|
}
|
|
if(m_AngleLimitHFlag)
|
|
{
|
|
shooter->EnableAngleLimitH(1);
|
|
shooter->SetMinAngleLimitH(m_MinHAngle);
|
|
shooter->SetMaxAngleLimitH(m_MaxHAngle);
|
|
}
|
|
}
|
|
}
|
|
|
|
shooter->GetEntity()->SendScriptEvent(ScriptEvent_InVehicleAmmo,1);
|
|
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------
|
|
void CVehicle::ReleaseWeaponUser( bool bDeselectWeapon )
|
|
{
|
|
CPlayer *shooter;
|
|
IEntity *pCurUserEntity = m_pGame->GetSystem()->GetIEntitySystem()->GetEntity( m_WeaponUser );
|
|
if( pCurUserEntity &&
|
|
pCurUserEntity->GetContainer() &&
|
|
pCurUserEntity->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&shooter) )
|
|
{
|
|
m_WeaponUser = 0;
|
|
//
|
|
// remove the vehicle's weapon from player
|
|
int wpnId = GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName( GetWeaponName( shooter->m_stats.inVehicleState ) );
|
|
if( wpnId != -1 )
|
|
shooter->MakeWeaponAvailable(wpnId, 0);
|
|
|
|
shooter->GetEntity()->SendScriptEvent(ScriptEvent_InVehicleAmmo,0);
|
|
|
|
if(bDeselectWeapon)
|
|
shooter->SelectWeapon(-1);
|
|
}
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------
|
|
void CVehicle::UpdateWeaponPosAngl( )
|
|
{
|
|
//const char *pszBoneName="Bip01 Head\0";
|
|
const char *pszBoneName="Bip01 Spine1\0";
|
|
Vec3 Position;
|
|
Vec3 Center;
|
|
Vec3 bestPoint3D;
|
|
Vec3 bestPointScreen;
|
|
float autoaimWndSize = 0.0f;
|
|
float minDist = 0.0f;
|
|
bool bAutoAim=false;
|
|
CPlayer *shooter = GetUserInState( CPlayer::PVS_GUNNER );
|
|
float timeScale = m_pGame->GetSystem()->GetITimer()->GetFrameTime()*2.0f;
|
|
|
|
m_bTargetIsLocked = false;
|
|
// m_vWpnPos = GetEntity()->GetPos()+Vec3(0,0,3.5);
|
|
GetEntity()->GetHelperPosition("gun",m_vWpnPos);
|
|
|
|
if(shooter)
|
|
{
|
|
// if there is a gunner - use he's angles
|
|
m_vWpnAng = shooter->GetEntity()->GetAngles();
|
|
m_bCrossOnScreen = true;
|
|
shooter->m_stats.crosshairOnScreen = true;
|
|
return;
|
|
}
|
|
else
|
|
shooter = GetUserInState( CPlayer::PVS_DRIVER );
|
|
if(!shooter)
|
|
{
|
|
//[kirill] nobody using weapon - smoothly return it to "zero" position
|
|
Vec3 vTargetAngl = m_pEntity->GetAngles() + Vec3(0,0,180);
|
|
vTargetAngl.x = -vTargetAngl.x;
|
|
vTargetAngl.y = -vTargetAngl.y;
|
|
Vec3 vDiff = vTargetAngl - m_vWpnAng ;
|
|
float trh=1.0f;
|
|
if( vDiff.x<trh && vDiff.x>-trh &&
|
|
vDiff.y<trh && vDiff.y>-trh &&
|
|
vDiff.z<trh && vDiff.z>-trh )
|
|
m_vWpnAng = vTargetAngl;
|
|
else
|
|
{
|
|
vDiff.x = Snap_s180(vDiff.x);
|
|
vDiff.y = Snap_s180(vDiff.y);
|
|
vDiff.z = Snap_s180(vDiff.z);
|
|
m_vWpnAng = m_vWpnAng + vDiff*.1f;
|
|
}
|
|
m_bCrossOnScreen = true;
|
|
m_vWpnAngDelta.z = 0.0f;
|
|
return;
|
|
}
|
|
|
|
//filippo: shift the weapon position up, to get a better firing position for the mounted weapon.
|
|
//TODO?: make this shift customizable by scripts?
|
|
Vec3 wpnPosOffset(0,0,0.3f);
|
|
|
|
Matrix44 tm = Matrix44::CreateRotationZYX(-m_vWpnAng*gf_DEGTORAD); //NOTE: angles in radians and negated
|
|
wpnPosOffset = GetTransposed44(tm)*wpnPosOffset;
|
|
m_vWpnPos += wpnPosOffset;
|
|
//
|
|
|
|
// shooter->m_stats.crosshairOnScreen = true;
|
|
|
|
// check autoaim properties of the weapon
|
|
WeaponParams wp;
|
|
CWeaponClass* pSelectedWeapon = shooter->GetSelectedWeapon();
|
|
// no autoaming in MP
|
|
if(!m_pGame->IsMultiplayer())
|
|
if(pSelectedWeapon)
|
|
{
|
|
pSelectedWeapon->GetModeParams(shooter->m_stats.firemode, wp);
|
|
bAutoAim = (wp.fAutoAimDist>0.0f);
|
|
autoaimWndSize = wp.fAutoAimDist;
|
|
minDist = autoaimWndSize*autoaimWndSize*2.0f;// 30000;
|
|
}
|
|
|
|
// we aim always in the center of the screen
|
|
m_vCrossScreen.x = 400.0f;
|
|
m_vCrossScreen.y = 300.0f;
|
|
|
|
Vec3 vCrossHair3Dpos;
|
|
|
|
//fixme - add the check if it's on screen
|
|
m_bCrossOnScreen = true;
|
|
|
|
//do autoaiming
|
|
if(bAutoAim && m_bCrossOnScreen)
|
|
{
|
|
//
|
|
//so, here goes autoaiming stuff - getting screen coordinates and finding closest to the center of
|
|
//screen entity - then snapping on it
|
|
IEntityItPtr It=m_pGame->GetSystem()->GetIEntitySystem()->GetEntityInFrustrumIterator( true );
|
|
CCamera Cam=m_pGame->GetSystem()->GetViewCamera();
|
|
IEntity *pEnt;
|
|
ray_hit RayHit;
|
|
IEntity *pLocal=m_pGame->GetMyPlayer();
|
|
while (pEnt=It->Next())
|
|
{
|
|
if (pEnt==m_pEntity)
|
|
continue;
|
|
if (!pEnt->IsTrackable())
|
|
continue;
|
|
//
|
|
//don't lock on people in this vehicle
|
|
if ( std::find(m_UsersList.begin(), m_UsersList.end(), pEnt->GetId() ) != m_UsersList.end() )
|
|
continue;
|
|
CPlayer *pPlayer;
|
|
if( pEnt->GetContainer() &&
|
|
pEnt->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&pPlayer) &&
|
|
!pPlayer->IsAlive() )
|
|
continue;
|
|
|
|
IPhysicalEntity *pPE=pEnt->GetPhysics();
|
|
if (!pPE)
|
|
continue;
|
|
|
|
if (pszBoneName) // if we want a bone instead of bbox-center lets do so...
|
|
{
|
|
IEntityCharacter *pIChar=pEnt->GetCharInterface();
|
|
if (pIChar)
|
|
{
|
|
ICryCharInstance *cmodel=pIChar->GetCharacter(0);
|
|
if (cmodel)
|
|
{
|
|
ICryBone *pBone = cmodel->GetBoneByName(pszBoneName);
|
|
if (pBone)
|
|
{
|
|
Center=pBone->GetBonePosition();
|
|
|
|
Matrix44 m;
|
|
m.SetIdentity();
|
|
m=GetTranslationMat(pEnt->GetPos())*m;
|
|
m=Matrix44::CreateRotationZYX(-pEnt->GetAngles()*gf_DEGTORAD)*m; //NOTE: angles in radians and negated
|
|
Center=m.TransformPointOLD(Center);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Center=pEnt->GetPos();
|
|
}
|
|
}
|
|
|
|
Vec3 diff(Center-m_vWpnPos);
|
|
|
|
float length2=GetLengthSquared(diff);
|
|
if(length2>250*250 || length2<3*3)
|
|
continue;
|
|
|
|
float px, py, pz;
|
|
m_pGame->GetSystem()->GetIRenderer()->ProjectToScreen(Center.x, Center.y, Center.z, &px, &py, &pz);
|
|
Position.x=(float)px*8.0f;
|
|
Position.y=(float)py*6.0f;
|
|
Position.z=(float)pz;
|
|
|
|
if ((Position.x>=m_vCrossScreen.x-autoaimWndSize) &&
|
|
(Position.y>=m_vCrossScreen.y-autoaimWndSize) &&
|
|
(Position.x<=m_vCrossScreen.x+autoaimWndSize) &&
|
|
(Position.y<=m_vCrossScreen.y+autoaimWndSize) &&
|
|
(Position.z>0.0f))
|
|
{
|
|
float dist = (Position.x-400)*(Position.x-400) + (Position.y-300)*(Position.y-300);
|
|
if( dist<minDist )
|
|
{
|
|
Vec3 offset = diff.normalized()*2.0f; // trace not from the weapon position - to skip windows
|
|
if (m_pGame->GetSystem()->GetIPhysicalWorld()->RayWorldIntersection(vectorf(m_vWpnPos + offset), diff,
|
|
ent_terrain|ent_static,0, &RayHit, 1,pPE, GetEntity()->GetPhysics()))
|
|
continue;
|
|
minDist = dist;
|
|
bestPoint3D = Center;
|
|
bestPointScreen = Position;
|
|
m_bTargetIsLocked = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//define world positionof the target/crosshair, calculate weapon angles
|
|
if( m_bTargetIsLocked )
|
|
vCrossHair3Dpos = bestPoint3D;
|
|
else
|
|
{
|
|
Vec3 shooterPos, shooterAng;
|
|
if ( shooter->IsMyPlayer())
|
|
{
|
|
if(shooter->m_bFirstPerson)
|
|
{
|
|
shooterAng = shooter->m_vCurAngleVhcl;
|
|
shooterPos = shooter->m_vCurCamposVhcl;
|
|
}
|
|
else
|
|
{
|
|
IEntityCamera *camera = shooter->GetEntity()->GetCamera();
|
|
shooterAng = camera->GetAngles();//shooter->GetEntity()->GetAngles();
|
|
shooterPos = camera->GetPos();//shooter->GetEntity()->GetPos();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
shooterAng = shooter->GetEntity()->GetAngles();
|
|
GetEntity()->GetHelperPosition("eye_pos",shooterPos);
|
|
}
|
|
|
|
// get trace direction
|
|
Matrix44 tm = Matrix44::CreateRotationZYX(-shooterAng*gf_DEGTORAD); //NOTE: angles in radians and negated
|
|
Vec3 dir = GetTransposed44(tm)*(Vec3d(0,-1,0));
|
|
|
|
Vec3 offset = dir*3.5f; // trace not from the weapon position - to skip windows
|
|
dir*=150;
|
|
|
|
// find 3d postiton of crosshair
|
|
ray_hit hits[1];
|
|
int hit=m_pGame->GetSystem()->GetIPhysicalWorld()->RayWorldIntersection(shooterPos + offset, dir, ent_all&~ent_living, rwi_stop_at_pierceable,
|
|
hits,1, GetEntity()->GetPhysics(), shooter->GetEntity()->GetPhysics() );
|
|
if(hit == 0)
|
|
vCrossHair3Dpos = shooterPos + dir;
|
|
else
|
|
vCrossHair3Dpos = hits[0].pt;
|
|
}
|
|
Matrix33 VehicleMat = Matrix33::CreateRotationXYZ( m_pEntity->GetAngles()*gf_DEGTORAD );
|
|
//this is the only place where we need the parent matrix
|
|
//frist we translate the Target into the space of the Gun,
|
|
//second we tranform this vector with the transposed vehicle-matrix
|
|
//from know on we treat the gun like on object where the parent has no rotation.
|
|
Vec3 GunViewDirection = GetNormalized(VehicleMat.T()*(vCrossHair3Dpos-m_vWpnPos));
|
|
|
|
float l = GetLength( Vec3(GunViewDirection.x, GunViewDirection.y, 0.0f ) );
|
|
assert(l); //throw assert if length=0
|
|
m_AngleLimitBase = Vec3(0,0,180);
|
|
|
|
//calculate the sine&cosine and matrix for rotation around the X-axis
|
|
float angleX = RAD2DEG(atan2_tpl(-GunViewDirection.z,l)); //angle for up-down movement
|
|
if(m_AngleLimitVFlag)
|
|
//check vertical limits
|
|
{
|
|
float original = angleX;
|
|
angleX = ClampAngle( Snap_s360(m_AngleLimitBase.x + m_MinVAngle),
|
|
Snap_s360(m_AngleLimitBase.x + m_MaxVAngle),
|
|
Snap_s360(angleX));
|
|
angleX = Snap_s180(angleX);
|
|
if( fabs(original - angleX) > .05f )
|
|
m_bCrossOnScreen = false;
|
|
}
|
|
angleX = DEG2RAD(angleX);
|
|
|
|
|
|
// if (angleX>+0.60f) angleX=+0.60f; //limit up-movement of gun
|
|
// if (angleX<-0.40f) angleX=-0.40f; //limit down-movement of gun
|
|
Matrix33 UpDownMat=Matrix33::CreateRotationX(angleX);
|
|
|
|
//calculate the sine&cosine and matrix for rotation around the Z-axis
|
|
float angleZ = RAD2DEG( atan2_tpl(GunViewDirection.x/l,-GunViewDirection.y/l)); //angle for left-right movement
|
|
bool bClamped=false;
|
|
if(m_AngleLimitHFlag)
|
|
{
|
|
//check horizontal limits
|
|
float original = angleZ;
|
|
angleZ = ClampAngle( Snap_s360(m_AngleLimitBase.z + m_MinHAngle),
|
|
Snap_s360(m_AngleLimitBase.z + m_MaxHAngle),
|
|
Snap_s360(angleZ));
|
|
angleZ = Snap_s180(angleZ);
|
|
if( fabs(original - angleZ) > .05f )
|
|
{
|
|
m_bCrossOnScreen = false;
|
|
bClamped = true;
|
|
}
|
|
}
|
|
angleZ = DEG2RAD(angleZ);
|
|
Matrix33 LeftRightMat=Matrix33::CreateRotationZ(angleZ);;
|
|
|
|
//we concatenate all 3 matrices to get the final gun-matrix in world-space
|
|
Matrix33 FinalGunMat=VehicleMat*LeftRightMat*UpDownMat;
|
|
m_vWpnAng = RAD2DEG(Ang3::GetAnglesXYZ( FinalGunMat ));
|
|
|
|
// shooter->m_stats.crosshairOnScreen = m_bCrossOnScreen;
|
|
int wpnId = GetGame()->GetWeaponSystemEx()->GetWeaponClassIDByName( GetWeaponName( shooter->m_stats.inVehicleState ) );
|
|
if( wpnId == -1 )
|
|
{
|
|
shooter->m_stats.crosshairOnScreen = true;
|
|
}
|
|
else if(!m_bCrossOnScreen)
|
|
{
|
|
// stop firing - stop sounds
|
|
// stop animation
|
|
if(shooter->m_stats.crosshairOnScreen)
|
|
{
|
|
CWeaponClass *pSelectedWeapon = shooter->GetSelectedWeapon();
|
|
if(pSelectedWeapon)
|
|
{
|
|
pSelectedWeapon->ScriptOnStopFiring(shooter->GetEntity());
|
|
WeaponState( shooter->GetEntity()->GetId(), false );
|
|
}
|
|
}
|
|
shooter->m_stats.crosshairOnScreen = false;
|
|
shooter->SetWaitForFireRelease(true);
|
|
}
|
|
else
|
|
{
|
|
shooter->SetWaitForFireRelease(false);
|
|
shooter->m_stats.crosshairOnScreen = true;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
void CVehicle::UpdateWeaponLimitRotation( Vec3& unlimitedPos, bool bClamped )
|
|
{
|
|
if( bClamped )
|
|
{
|
|
if( m_vWpnAngNoSnap.z*unlimitedPos.z>=0 || fabs(unlimitedPos.z)<20.0f )
|
|
{
|
|
m_vWpnAngDelta.z = 0.0f;
|
|
m_vWpnAng = m_vWpnAngNoSnap;
|
|
return;
|
|
}
|
|
if(m_vWpnAngNoSnap.z >0 )
|
|
m_vWpnAngDelta.z=1.0f;
|
|
else
|
|
m_vWpnAngDelta.z=-1.0f;
|
|
}
|
|
if( m_vWpnAngDelta.z == 0.0f )
|
|
{
|
|
m_vWpnAng = m_vWpnAngNoSnap;
|
|
return;
|
|
}
|
|
|
|
float timeScale = m_pGame->GetSystem()->GetITimer()->GetFrameTime();
|
|
timeScale*=730.0f;
|
|
if( fabs(Snap_s360(m_vWpnAngNoSnap.z) - Snap_s360(m_vWpnAng.z)) < timeScale*7.0f )
|
|
{
|
|
m_vWpnAngDelta.z = 0.0f;
|
|
m_vWpnAng = m_vWpnAngNoSnap;
|
|
return;
|
|
}
|
|
|
|
m_vWpnAng.x = m_vWpnAngNoSnap.x;
|
|
m_vWpnAng.y = m_vWpnAngNoSnap.y;
|
|
if(m_vWpnAngDelta.z>0)
|
|
m_vWpnAng.z += timeScale;
|
|
else
|
|
m_vWpnAng.z -= timeScale;
|
|
|
|
return;
|
|
/*
|
|
// m_vWpnAngNoSnap = curPos;
|
|
// return;
|
|
|
|
if( bClamped )
|
|
{
|
|
m_vWpnAngDelta.z = Snap_s360(curPos.z) - Snap_s360(m_vWpnAngNoSnap.z);
|
|
}
|
|
if( m_vWpnAngDelta.z == 0.0f )
|
|
{
|
|
m_vWpnAngNoSnap = curPos;
|
|
return;
|
|
}
|
|
float timeScale = m_pGame->GetSystem()->GetITimer()->GetFrameTime();
|
|
timeScale*=730.0f;
|
|
if( fabs(m_vWpnAngNoSnap.z - curPos.z) < timeScale*7.0f )
|
|
{
|
|
m_vWpnAngDelta.z = 0.0f;
|
|
m_vWpnAngNoSnap = curPos;
|
|
return;
|
|
}
|
|
|
|
m_vWpnAngNoSnap.x = curPos.x;
|
|
m_vWpnAngNoSnap.y = curPos.y;
|
|
if(m_vWpnAngDelta.z>0)
|
|
m_vWpnAngNoSnap.z += timeScale;
|
|
else
|
|
m_vWpnAngNoSnap.z -= timeScale;
|
|
*/
|
|
}
|
|
|
|
|
|
bool CVehicle::AnglesToLimit( Vec3& angl )
|
|
{
|
|
m_AngleLimitBase = Vec3(0,0,180);
|
|
m_bCrossOnScreen = true;
|
|
|
|
if(m_AngleLimitVFlag)
|
|
//check vertical limits
|
|
{
|
|
float original = angl.x;
|
|
angl.x = ClampAngle( Snap_s360(m_AngleLimitBase.x + m_MinVAngle),
|
|
Snap_s360(m_AngleLimitBase.x + m_MaxVAngle),
|
|
Snap_s360(angl.x));
|
|
angl.x = Snap_s180(angl.x);
|
|
if( fabs(original - angl.x) > .05f )
|
|
m_bCrossOnScreen = false;
|
|
|
|
}
|
|
if(m_AngleLimitHFlag)
|
|
{
|
|
//check horizontal limits
|
|
float original = angl.z;
|
|
angl.z = ClampAngle( Snap_s360(m_AngleLimitBase.z + m_MinHAngle),
|
|
Snap_s360(m_AngleLimitBase.z + m_MaxHAngle),
|
|
Snap_s360(angl.z));
|
|
angl.z = Snap_s180(angl.z);
|
|
if( fabs(original - angl.z) > .05f )
|
|
{
|
|
m_bCrossOnScreen = false;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|