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

463 lines
14 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Game source code (c) Crytek 2001-2003
//
// File: GameRadar.cpp
//
// History:
// -December 11,2001: created
// -October 31,2003: split from GameLoading.cpp and other files
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Game.h"
#include "XNetwork.h"
#include "XServer.h"
#include "XClient.h"
#include "UIHud.h"
#include "XPlayer.h"
#include "PlayerSystem.h"
#include "XServer.h"
#include "WeaponSystemEx.h"
#include "ScriptObjectGame.h"
#include "ScriptObjectInput.h"
#include <IEntitySystem.h>
#include "UISystem.h"
#include "ScriptObjectUI.h"
// render game radar
// notes: clean up/optimize code, lots of redundant stuff
//////////////////////////////////////////////////////////////////////////
void CXGame::DrawRadar(float x, float y, float w, float h, float fRange, INT_PTR *pRadarTextures, _SmartScriptObject *pEntities, char *pRadarObjective)
{
// 0 - Radar
// 1 - RadarMask
// 2 - RadarPlayerIcon
// 3 - RadarEnemyInRangeIcon
// 4 - RadarEnemyOutRangeIcon
// 5 - RadarSoundIcon
// 6 - RadarObjectiveIcon
// check if data ok
if (!m_pRenderer || !pRadarTextures || !pRadarObjective)
{
return;
}
IEntity *pPlayer=GetMyPlayer();
if (!pPlayer)
{
return;
}
// clamp minimum value
if(fRange<10.0f)
{
fRange=10.0f;
}
ICVar *pFadeAmount=0;
if(m_pSystem && m_pSystem->GetIConsole())
{
pFadeAmount=m_pSystem->GetIConsole()->GetCVar("hud_fadeamount");
}
float fFadeAmount=1;
if(pFadeAmount)
{
fFadeAmount=pFadeAmount->GetFVal();
}
// set render state
m_pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
m_pRenderer->Set2DMode(true, 800, 600);
// radar texture id's
INT_PTR iRadarID=pRadarTextures[0],
iRadarMaskID=pRadarTextures[1],
iPlayerIconID=pRadarTextures[2],
iEnemyInRangeIconID=pRadarTextures[3],
iEnemyOutRangeIconID=pRadarTextures[4],
iSoundIconID=pRadarTextures[5],
iObjectiveIconID=pRadarTextures[6];
// last radar alpha/used to mask out sound events
static float fLastAlpha=0.0f, fLastAvgDist=0.0f;
ITimer *pTimer=m_pSystem->GetITimer();
float fCurrPosStep=fLastAlpha*5.0f;
if(fCurrPosStep>1.0f)
{
fCurrPosStep=1.0f;
}
Vec3d fMapCenter(x+w*0.5f, y+h*0.5f, 0.5f);
// render radar/compass
int iPx=0, iPy=0, iW=0, iH=0;
m_pRenderer->GetViewport(&iPx, &iPy, &iW, &iH);
// used to scale y coordinates correctly acoording to aspect ratio
float fScaleY=((float)iW/(float)iH)*0.75f;
// get radar mask data
float fMaskPosX=fMapCenter.x-0.5f*186.0f;
float fMaskPosY=fMapCenter.y-(0.5f*186.0f)*fScaleY;
float fMaskW=186.0f;
float fMaskH=186.0f*fScaleY;
// clear radar background alpha
m_pRenderer->SetState(GS_BLSRC_ONE | GS_BLDST_ZERO | GS_NODEPTHTEST | GS_COLMASKONLYALPHA);
m_pRenderer->Draw2dImage(fMaskPosX, fMaskPosY, fMaskW, fMaskH, iRadarMaskID, 0, 0.1f, 0.1f, 0, 0, 1, 1, 1, 1);
// get radar data
float fRadarPosX=fMapCenter.x-0.5f*130.0f;
float fRadarPosY=fMapCenter.y-(0.5f*130.0f)*fScaleY;
float fRadarW=130.0f;
float fRadarH=(130.0f)*fScaleY;
// render radar mask into alpha channel
m_pRenderer->Draw2dImage(fRadarPosX, fRadarPosY, fRadarW, fRadarH, iRadarMaskID, 0, 1, 1, 0, 0, 1,1, 1, 1);
// add the radar
m_pRenderer->SetState(GS_BLSRC_ONEMINUSDSTALPHA | GS_BLDST_DSTALPHA | GS_NODEPTHTEST);
static float fCurrCompassAngle=pPlayer->GetAngles().z;
float fCurrAngle=pPlayer->GetAngles().z;
fCurrCompassAngle+=(pPlayer->GetAngles().z-fCurrCompassAngle)*pTimer->GetFrameTime()*8.0f;
m_pRenderer->Draw2dImage(fRadarPosX, fRadarPosY, fRadarW, fRadarH, iRadarID, 0, 1, 1, 0, fCurrCompassAngle+90.0f, fFadeAmount,fFadeAmount, fFadeAmount, 1);
// add radar noise..
static float fNoiseMove=0.0f;
fNoiseMove+=pTimer->GetFrameTime()*2.0f;
m_pRenderer->Draw2dImage(fRadarPosX, fRadarPosY, fRadarW, fRadarH, iRadarMaskID, 0+fNoiseMove, 0, 0.1f+fNoiseMove, 1.5f, 0, 1, 1.0f, 1.0f, 1.0f);
// render player icon
float fPlayerSize=16.0f;
float fTexOffset=0.5f/fPlayerSize;
m_pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
float fPlayerAlpha=(fLastAlpha<=0.6f)? 0.6f: fLastAlpha;
m_pRenderer->Draw2dImage(fMapCenter.x-fPlayerSize*0.5f, fMapCenter.y-fPlayerSize*0.5f,
fPlayerSize, fPlayerSize, iPlayerIconID, fTexOffset, 1-fTexOffset, 1-fTexOffset, fTexOffset, 0, fPlayerAlpha*fFadeAmount, fPlayerAlpha*fFadeAmount, fPlayerAlpha*fFadeAmount, fPlayerAlpha);
// get player position
Vec3d pPlayerPos=pPlayer->GetPos();
// draw sound-events
CXClient *pClient=GetClient();
m_pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
if (pClient) //&& fLastAlpha>0.0f)
{
TSoundList SoundList=pClient->GetSoundEventList();
float fScale=(w*0.5f); ///fRange;
Matrix33 mtxTransformNoMove;
mtxTransformNoMove.SetScale(Vec3(fScale , (fScale)*fScaleY, 0.0f));
mtxTransformNoMove=mtxTransformNoMove*Matrix33::CreateRotationZ(DEG2RAD(-pPlayer->GetAngles().z));
Matrix34 mtxTransform=mtxTransformNoMove;
Matrix34 TransferVector;
TransferVector.SetTranslationMat(-pPlayer->GetPos());
mtxTransform=mtxTransform*TransferVector;
for (TSoundListIt It=SoundList.begin();It!=SoundList.end();++It)
{
SSoundInfo &SoundInfo=(*It);
if (SoundInfo.fThread==0.0f)
{
// only display threatening sounds
continue;
}
Vec3d pPos=mtxTransform*SoundInfo.Pos;
Vec3d pSoundPos=SoundInfo.Pos;
float fCurrDist=cry_sqrtf((pPlayerPos.x-pSoundPos.x)*(pPlayerPos.x-pSoundPos.x)+(pPlayerPos.y-pSoundPos.y)*(pPlayerPos.y-pSoundPos.y)+(pPlayerPos.z-pSoundPos.z)*(pPlayerPos.z-pSoundPos.z));
float fRadius=fScale*SoundInfo.fRadius/fRange;
float fPhase=SoundInfo.fTimeout/pClient->cl_sound_event_timeout->GetFVal();
pPos.x=-pPos.x;
float fSoundIconSize;
if(fCurrDist>fRange)
{
if(fCurrDist==0.0f)
{
fCurrDist=1.0f;
}
fSoundIconSize=20.0f*(1.0f-fPhase);
fCurrDist=1.0f/fCurrDist;
m_pRenderer->Draw2dImage(fMapCenter.x+pPos.x*fCurrDist-fSoundIconSize*0.5f, fMapCenter.y+pPos.y*fCurrDist-fSoundIconSize*0.5f,
fSoundIconSize, fSoundIconSize, iSoundIconID, 0, 0, 1, 1, 0, fFadeAmount, fFadeAmount, fFadeAmount, fPhase);
}
else
{
fCurrDist/=15.0f;
if(fCurrDist<1.2f && fCurrDist>0.0f)
{
fCurrDist=1.2f;
}
else
if(fCurrDist==0.0f)
{
fCurrDist=1.0f;
}
fSoundIconSize=fRadius*(1.0f-fPhase);
fCurrDist=1.0f/fCurrDist;
m_pRenderer->Draw2dImage(fMapCenter.x+(pPos.x/fRange)-fSoundIconSize*0.5f*fCurrDist, fMapCenter.y+(pPos.y/fRange)-fSoundIconSize*0.5f*fCurrDist, fSoundIconSize*fCurrDist, fSoundIconSize*fCurrDist, iSoundIconID, 0, 0, 1, 1, 0, fFadeAmount, fFadeAmount, fFadeAmount, fPhase);
}
}
}
// draw players
float PlayerZAngle=pPlayer->GetAngles().z;
int nCount=1;
_SmartScriptObject pEntitySO(m_pScriptSystem, true);
_SmartScriptObject pColor(m_pScriptSystem, true);
(*pEntities)->BeginIteration();
// compute average distance to player, for dinamyc radar scale adjustment
float fAvgDist=0.0f;
int iTotalEntities=1;
float fScale=(w*0.5f);
ASSERT(fScale>0.0f);
Matrix33 mtxTransformNoMove;
mtxTransformNoMove.SetScale(Vec3(fScale, (fScale)*fScaleY, 0.0f));
mtxTransformNoMove=mtxTransformNoMove*Matrix33::CreateRotationZ(DEG2RAD(-pPlayer->GetAngles().z));
Matrix34 mtxTransform=mtxTransformNoMove;
Matrix34 TransferVector;
TransferVector.SetTranslationMat(-pPlayer->GetPos());
mtxTransform=mtxTransform*TransferVector;
m_pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
// show radar objective direction
// get radar objective position
Vec3d pObjectivePos(0,0,0);
int iHaveObjective= strcmp("NoObjective", pRadarObjective);
if(iHaveObjective)
{
if(sscanf(pRadarObjective, "%f %f %f", &pObjectivePos.x, &pObjectivePos.y, &pObjectivePos.z)!=3)
{
return;
}
Vec3d pObjectiveScreenPos=mtxTransform*pObjectivePos;
pObjectiveScreenPos.x=-pObjectiveScreenPos.x;// invert x due to different mapping
// compute distance and sum values
float fCurrDist=cry_sqrtf((pPlayerPos.x-pObjectivePos.x)*(pPlayerPos.x-pObjectivePos.x)+(pPlayerPos.y-pObjectivePos.y)*(pPlayerPos.y-pObjectivePos.y));
float r=0.0f, g=1.0f, b=1.0f, a=1.0f;
if(fCurrDist>fRange)
{
float fPosX=pObjectiveScreenPos.x, fPosY=pObjectiveScreenPos.y;
float fLen=cry_sqrtf(fPosX*fPosX + fPosY*fPosY);
if(fLen)
{
fPosX/=fLen;
fPosY/=fLen;
}
float fOutRangeAngle=0;
if(fPosX<0.0f)
{
fOutRangeAngle=RAD2DEG(cry_acosf(fPosY));
}
else
{
fOutRangeAngle=360.0f-RAD2DEG(cry_acosf(fPosY));
}
m_pRenderer->Draw2dImage(fMapCenter.x+fPosX*52.0f-10.0f*0.5f, fMapCenter.y+fPosY*52.0f*fScaleY-10.0f*0.5f,
10.0f, 10.0f, iEnemyOutRangeIconID, 0, 0, 1, 1, fOutRangeAngle, r*fFadeAmount, g*fFadeAmount, b*fFadeAmount, a*0.5f);
}
else
{
float r=0.0f, g=1.0f, b=1.0f, a=1.0f;
fCurrDist/=15.0f;
if(fCurrDist<1.2f && fCurrDist>0.0f)
{
fCurrDist=1.2f;
}
else
if(fCurrDist==0.0f)
{
fCurrDist=1.0f;
}
fCurrDist=1.0f/fCurrDist;
float fVerticalDist=fabsf(pPlayerPos.z-pObjectivePos.z);
// to distant on vertical range, must be on diferent floor/level, put icons gray
if(fVerticalDist>fRange*0.15f)
{
r*=0.5f;
g*=0.5f;
b*=0.5f;
}
static float fCurrSize=0.0f;
fCurrSize+=pTimer->GetFrameTime()*2.0f;
if(fCurrSize>1.0f)
{
fCurrSize=0.0f;
}
m_pRenderer->Draw2dImage(fMapCenter.x+(pObjectiveScreenPos.x/fRange)-10.0f*fCurrSize*0.5f, fMapCenter.y+(pObjectiveScreenPos.y/fRange)-10.0f*fCurrSize*0.5f,
10.0f*fCurrSize, 10.0f*fCurrSize, iObjectiveIconID, 0, 0, 1, 1, 0.0f, r*a*fFadeAmount, g*a*fFadeAmount, b*a*fFadeAmount, a);
}
}
// render entities
while ((*pEntities)->MoveNext())
{
if (!(*pEntities)->GetCurrent(*pEntitySO))
{
continue;
}
int nId;
if (!pEntitySO->GetValue("nId", nId))
{
continue;
}
IEntity *pEntity=m_pEntitySystem->GetEntity(nId);
if (!pEntity)
{
continue;
}
Vec3d Pos=mtxTransform*pEntity->GetPos();
Pos.x=-Pos.x;// invert x due to different mapping
float r=1.0f, g=1.0f, b=1.0f, a=1.0f;
if (pEntitySO->GetValue("Color", *pColor))
{
pColor->GetValue("r", r);
pColor->GetValue("g", g);
pColor->GetValue("b", b);
pColor->GetValue("a", a);
}
fLastAlpha=a;
// no need to do more stuff..
if(fLastAlpha==0.0f)
{
continue;
}
Matrix33 IconMatrix;
float fAngleZ=PlayerZAngle-pEntity->GetAngles(true).z;
// [marco] temporay fix to be able
// to run a version with debug info
// on and do not get an assert every frame
if (fAngleZ<-360.0f)
{
fAngleZ+=360;
}
else
if (fAngleZ>360.0f)
{
fAngleZ-=360;
}
float fEnemyInRangeSize=10.0f,
fEnemyOutRangeSize=5.0f;
// compute distance and sum values
Vec3d pEntityPos=pEntity->GetPos();
float fCurrDist=cry_sqrtf((pPlayerPos.x-pEntityPos.x)*(pPlayerPos.x-pEntityPos.x)+(pPlayerPos.y-pEntityPos.y)*(pPlayerPos.y-pEntityPos.y));
// skip player..
if(fCurrDist<0.01)
{
continue;
}
// render enemy icons
if(fCurrDist>fRange)
{
if(fCurrDist==0.0f)
{
fCurrDist=1.0f;
}
fCurrDist=1.0f/fCurrDist;
float fPosX=Pos.x, fPosY=Pos.y;
float fLen=cry_sqrtf(fPosX*fPosX + fPosY*fPosY);
if(fLen)
{
fPosX/=fLen;
fPosY/=fLen;
}
float fOutRangeAngle=0;
if(fPosX<0.0f)
{
fOutRangeAngle=RAD2DEG(cry_acosf(fPosY));
}
else
{
fOutRangeAngle=360.0f-RAD2DEG(cry_acosf(fPosY));
}
m_pRenderer->Draw2dImage(fMapCenter.x+Pos.x*fCurrDist*0.98f-fEnemyOutRangeSize*0.5f, fMapCenter.y+Pos.y*fCurrDist*0.98f-fEnemyOutRangeSize*0.5f,
fEnemyOutRangeSize, fEnemyOutRangeSize, iEnemyOutRangeIconID, 0, 0, 1, 1, fOutRangeAngle, 0, a*fFadeAmount, 0, a);
}
else
{
fCurrDist/=15.0f;
if(fCurrDist<1.2f && fCurrDist>0.0f)
{
fCurrDist=1.2f;
}
else
if(fCurrDist==0.0f)
{
fCurrDist=1.0f;
}
fCurrDist=1.0f/fCurrDist;
float fVerticalDist=fabsf(pPlayerPos.z-pEntityPos.z);
// to distant on vertical range, must be on diferent floor/level, put icons gray
if(fVerticalDist>fRange*0.15f)
{
r*=0.5f;
g*=0.5f;
b*=0.5f;
}
m_pRenderer->Draw2dImage(fMapCenter.x+(Pos.x*0.98f/fRange)-fEnemyInRangeSize*0.5f*fCurrDist, fMapCenter.y+(Pos.y*0.98f/fRange)-fEnemyInRangeSize*0.5f*fCurrDist,
fEnemyInRangeSize*fCurrDist, fEnemyInRangeSize*fCurrDist, iEnemyInRangeIconID, 0, 0, 1, 1, fAngleZ+180.0f, r*a*fFadeAmount, g*a*fFadeAmount, b*a*fFadeAmount, a);
}
}
(*pEntities)->EndIteration();
// reset states
m_pRenderer->SetState(GS_NODEPTHTEST);
m_pRenderer->Set2DMode(false, 800, 600);
}