Files
FC1/CryGame/XPlayerLight.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

428 lines
10 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Game Source Code
//
// File: XPlayerLight.cpp
// Description: Entity player class.
// flashlight funtionality
//
// History:
// - apr 17,2003: Created by Kirill - splitting Xplayer.cpp in multiple files
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "XPlayer.h"
#include <IAgent.h>
// <<FIXME>> look above
#include "I3DEngine.h"
// remove this
#include <IAISystem.h>
//
//-----------------------------------------------------------------
Vec3d CPlayer::GetFLightPos( )
{
if(IsMyPlayer())
{
Vec3d pos;
Vec3d ang;
GetFirePosAngles(pos, ang);
ang = ConvertToRadAngles(ang);
return pos - ang;
}
if(m_pGame->pl_head->GetIVal()==0)
{
ICryCharInstance *pChar = m_pEntity->GetCharInterface()->GetCharacter(0);
if(pChar)
{
ICryBone * bone = pChar->GetBoneByName("weapon_bone"); // find bone in the list of bones;
if(bone)
{
Matrix44 mat;
mat.SetIdentity();
Vec3d rot = m_pEntity->GetAngles();
rot.x=0;
//mat.RotateMatrix_fix(angles);
mat=Matrix44::CreateRotationZYX(-gf_DEGTORAD*rot)*mat; //NOTE: angles in radians and negated
return m_pEntity->GetPos() + mat.TransformPointOLD(bone->GetBonePosition()) - Vec3d(0,0,0.3f);
}
}
}
else
{
Vec3d pos;
Vec3d ang;
GetFirePosAngles(pos, ang);
return pos + Vec3d(0.f,0.f,.3f);
/*
if(m_pBoneHead)
{
// light->m_Origin = m_pEntity->GetPos() + m_pBoneHead->GetBonePosition();
Matrix44 mat;
mat.Identity();
Vec3d rot = m_pEntity->GetAngles();
rot.x=0;
//mat.RotateMatrix_fix(angles);
mat=GetRotationZYX44(-gf_DEGTORAD*rot)*mat; //NOTE: angles in radians and negated
return m_pEntity->GetPos() + mat.TransformPoint(m_pBoneHead->GetBonePosition());
}
*/
}
return m_pEntity->GetPos() + Vec3d(0,0,2);
}
//
//-----------------------------------------------------------------
void CPlayer::ProceedFLight( )
{
if(!m_bLightOn)
return;
if( !m_pDynLight )
return;
FUNCTION_PROFILER( GetISystem(),PROFILE_GAME );
float totalLightScale = 1.0f - m_pGame->GetSystem( )->GetI3DEngine()->GetAmbientLightAmountForEntity(m_pEntity)*2.0f;
// for local player make it always bright
if( IsMyPlayer() )
totalLightScale = 1.0f;
if(totalLightScale<.2f)
totalLightScale = .2f;
//
// fixme - this causes crach in destructor
m_pDynLight->m_Flags = DLF_PROJECT;
if(IsMyPlayer())
m_pDynLight->m_fLightFrustumAngle = 30;
else
m_pDynLight->m_fLightFrustumAngle = m_pGame->p_lightfrustum->GetFVal(); // for other players - more light
m_pDynLight->m_fRadius = m_pGame->p_lightrange->GetFVal();
m_pDynLight->m_Origin = GetFLightPos();
// light->m_ProjAngles = m_pEntity->GetAngles();
m_pDynLight->m_ProjAngles = Vec3d(m_pEntity->GetAngles().y,m_pEntity->GetAngles().x,m_pEntity->GetAngles().z-90);
m_pDynLight->m_Color = CFColor(totalLightScale,totalLightScale,totalLightScale, 1.0f);
m_pDynLight->m_SpecColor = CFColor(totalLightScale,totalLightScale,totalLightScale);
// m_pDynLight->m_Color = CFColor(.45f,.45f,.45f, 1.0f);
// m_pDynLight->m_SpecColor = CFColor(.45f,.45f,.45f);
m_pDynLight->m_Flags |= (DLF_LIGHTSOURCE | DLF_SPECULAR_ONLY_FOR_HIGHSPEC);
/*
light->m_pShader = 0;
if (!light->m_pLightImage)
{
//Light.m_pLightImage = m_IndInterface.m_pRenderer->EF_LoadTexture("FlashLightCube", 0, FT2_FORCECUBEMAP, eTT_Cubemap);
light->m_pLightImage = m_pGame->GetSystem()->GetIRenderer()->EF_LoadTexture("Textures/Lights/Light_testgrid", 0, FT2_FORCECUBEMAP, eTT_Cubemap);
}
*/
// m_pGame->GetSystem()->GetIRenderer()->EF_UpdateDLight(light);
m_pGame->GetSystem()->GetI3DEngine()->AddDynamicLightSource(*m_pDynLight, GetEntity());
if (m_pLightTarget)
{
ray_hit hit;
Vec3d dir = ConvertToRadAngles(m_pEntity->GetAngles());
dir*=20;
int colliders = m_pGame->GetSystem()->GetIPhysicalWorld()->RayWorldIntersection(GetFLightPos(),dir,ent_all,0,&hit,1,m_pEntity->GetPhysics());
if (colliders)
{
hit.pt.z +=float (rand()%100/1000);
Vec3d newPos = hit.pt -m_pEntity->GetPos();
// move it about 10 cm away from the point of collision
float fDIST = newPos.Length();
newPos *= 1.f - 0.1f/fDIST;
m_pLightTarget->SetPos(m_pEntity->GetPos()+newPos);
}
}
}
//
//
void CPlayer::UpdateLightBlinding()
{
FUNCTION_PROFILER( GetISystem(),PROFILE_GAME );
//return;
if (m_pGame->m_PlayersWithLighs.empty() &&
((IsMyPlayer()&&m_vBlindingList.empty()) || (m_bIsAI&&!m_stats.bIsBlinded)) )
return;
ListOfPlayers::iterator pl = m_pGame->m_PlayersWithLighs.begin();
Vec3d tmp;
Vec3d thisForward;
float totalLightScale = m_pGame->GetSystem( )->GetI3DEngine()->GetAmbientLightAmountForEntity(m_pEntity);
totalLightScale*=3.0f;
if(totalLightScale>1.0f)
totalLightScale=1.0f;
//GetLightAmountForEntity( m_pEntity );
//if( m_bIsAI )
//m_pGame->GetSystem()->GetILog()->Log("\003 lScale %.3f", totalLightScale );
GetFirePosAngles(tmp, thisForward);
thisForward=ConvertToRadAngles(thisForward);
thisForward.normalize();
m_stats.curBlindingValue = 0.0f;
for( ; pl!=m_pGame->m_PlayersWithLighs.end(); pl++ )
{
if( (*pl)==this )
continue;
CPlayer *curPlayer = (*pl);
Vec3d blindingPos = curPlayer->GetFLightPos();
Vec3d direction = blindingPos - m_vEyePos;
Vec3d curForward;
float blindingValue=0.0f;
float dist2 = 0;
curPlayer->GetFirePosAngles(tmp, curForward);
curForward=ConvertToRadAngles(curForward);
curForward.normalize();
dist2 = direction.len2();
direction.normalize();
blindingValue = direction*thisForward;
if(blindingValue<0.0f)
continue;
direction = -direction;
//dist2 = (direction*curForward);
blindingValue = blindingValue*(direction*curForward);
blindingValue *= blindingValue;
blindingValue *= blindingValue;
blindingValue *= blindingValue;
// blindingValue = blindingValue*blindingValue*blindingValue;
dist2 = m_pGame->pl_dist->GetFVal()/dist2;
if(dist2 > 1.0f)
dist2 = cry_sqrtf(dist2);
blindingValue *= dist2;
blindingValue *= m_pGame->pl_intensity->GetFVal();
blindingValue *= (1.0f - totalLightScale);
if(blindingValue<.2f)
continue;
ray_hit hit;
IPhysicalEntity *physic = curPlayer->m_pEntity->GetPhysics();
if( m_pGame->GetSystem()->GetIPhysicalWorld()->
RayWorldIntersection(blindingPos,m_vEyePos-blindingPos,ent_terrain | ent_static,
rwi_stop_at_pierceable,&hit,1, physic))
continue;
if(IsMyPlayer())
{
Vec3d scrPos;
GetGame()->GetSystem()->GetIRenderer()->ProjectToScreen( blindingPos.x, blindingPos.y, blindingPos.z,
&scrPos.x,&scrPos.y,&scrPos.z);
scrPos.z = blindingValue;
scrPos.x *= 8.0f;
scrPos.y *= 6.0f;
// m_vBlindingPosList.push_back(scrPos);
BlindingList::iterator curB = m_vBlindingList.find(curPlayer);
if( curB == m_vBlindingList.end() )
{
m_vBlindingList[curPlayer] = scrPos;
}
else
{
(curB->second).x = scrPos.x;
(curB->second).y = scrPos.y;
if((curB->second).z < scrPos.z)
(curB->second).z = scrPos.z;
}
}
if(m_bIsAI && m_stats.curBlindingValue < blindingValue)
{
m_stats.curBlindingValue = blindingValue;
}
}
float fade = m_pTimer->GetFrameTime()*m_pGame->pl_fadescale->GetFVal();
BlindingList::iterator curB = m_vBlindingList.begin();
for( ; curB != m_vBlindingList.end(); )
{
(curB->second).z -= fade;
if((curB->second).z<=0.0f) // remove
{
BlindingList::iterator nextB = curB;
nextB++;
m_vBlindingList.erase( curB );
curB = nextB;
continue;
}
curB++;
}
m_LastUsed = m_vBlindingList.begin();
if( m_bIsAI )
{
IAIObject *pObject = m_pEntity->GetAI();
IPuppet *pPuppet=0;
if (pObject->CanBeConvertedTo(AIOBJECT_PUPPET,(void**)&pPuppet))
{
if(m_stats.curBlindingValue > 1.6f)
{
if(!m_stats.bIsBlinded)
{
pObject->SetSignal(0, "SHARED_BLINDED");
m_stats.bIsBlinded = true;
}
}
else
{
if(m_stats.bIsBlinded)
{
pObject->SetSignal(0, "SHARED_UNBLINDED");
m_stats.bIsBlinded = false;
}
}
}
}
//if(m_stats.curBlindingValue > .1f)
//m_pGame->GetSystem()->GetILog()->Log("\003 blind %.3f", m_stats.curBlindingValue );
}
//
//
void CPlayer::SwitchFlashLight( bool on )
{
// only perform switch, if the player actually has a flashlight
// or if switching off
if (!m_stats.has_flashlight && !m_bLightOn)
return;
if(m_bLightOn == on)
return;
FUNCTION_PROFILER( GetISystem(),PROFILE_GAME );
m_bLightOn = on;
m_pEntity->SendScriptEvent( ScriptEvent_FlashLightSwitch , (int)(m_bLightOn));
if( m_bLightOn )
m_pGame->m_PlayersWithLighs.push_back( this );
else
{
ListOfPlayers::iterator self = std::find(m_pGame->m_PlayersWithLighs.begin(), m_pGame->m_PlayersWithLighs.end(), this);
if(self!=m_pGame->m_PlayersWithLighs.end())
m_pGame->m_PlayersWithLighs.erase(self);
}
if (on && !m_bIsAI)
{
m_pLightTarget = m_pGame->GetSystem()->GetAISystem()->CreateAIObject(AIOBJECT_ATTRIBUTE,0);
if (m_pLightTarget)
{
m_pLightTarget->Bind(m_pEntity->GetAI());
m_pLightTarget->SetPos(m_pEntity->GetPos());
}
}
else
{
if (m_pLightTarget)
{
m_pGame->GetSystem()->GetAISystem()->RemoveObject(m_pLightTarget);
m_pLightTarget = 0;
}
}
}
//
//--------------------------------------------------------------------------------------
bool CPlayer::InitLight( const char* sImg, const char* sShader )
{
if (m_pDynLight)
delete m_pDynLight;
m_pDynLight = new CDLight();
if(sImg && sImg[0])
{
m_pDynLight->m_fAnimSpeed = 0;
int nFlags2 = FT2_FORCECUBEMAP;
// if (bUseAsCube)
// nFlags2 |= FT2_REPLICATETOALLSIDES;
// if (fAnimSpeed)
// nFlags2 |= FT2_CHECKFORALLSEQUENCES;
m_pDynLight->m_pLightImage = m_pGame->GetSystem()->GetIRenderer()->EF_LoadTexture(sImg, 0, nFlags2, eTT_Cubemap);
m_pDynLight->m_Flags = DLF_PROJECT;
}
else
m_pDynLight->m_Flags = DLF_POINT;
if(sShader && sShader[0])
m_pDynLight->m_pShader = m_pGame->GetSystem()->GetIRenderer()->EF_LoadShader((char*)sShader, eSH_World);
return true;
}
void CPlayer::GiveFlashLight(bool val)
{
if (m_stats.has_flashlight == val)
return;
m_stats.has_flashlight = val;
// make sure we turn off the flashlight, if we take it away
if (val == false && m_bLightOn)
{
SwitchFlashLight(false);
}
}
float CPlayer::GetLightRadius()
{
if(m_pDynLight && m_bLightOn)
return m_pDynLight->m_fRadius;
return 0;
}
//GetLightAmountForEntity
//
//-----------------------------------------------------------------