This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

460
CryGame/GameMisc.cpp Normal file
View File

@@ -0,0 +1,460 @@
//////////////////////////////////////////////////////////////////////
//
// Game source code (c) Crytek 2001-2003
//
// File: GameMisc.cpp
//
// History:
// -October 31,2003: created
//
//////////////////////////////////////////////////////////////////////
#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"
#include "ScriptObjectBoids.h"
#include "Flock.h"
#include "WeaponClass.h"
#include "ScriptObjectRenderer.h"
#include "ScriptTimerMgr.h"
//////////////////////////////////////////////////////////////////////////
void CXGame::EnableUIOverlay(bool bEnable, bool bExclusiveInput)
{
if (!m_bEditor)
{
m_bUIOverlay = bEnable;
if ((bExclusiveInput) && (!m_bUIExclusiveInput))
{
m_pIActionMapManager->Disable();
m_pSystem->GetIInput()->SetExclusiveListener(m_pUISystem);
m_bUIExclusiveInput = 1;
}
else if ((!bExclusiveInput) && (m_bUIExclusiveInput))
{
m_pIActionMapManager->Enable();
m_pSystem->GetIInput()->SetExclusiveListener(0);
m_bUIExclusiveInput = 0;
}
}
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::IsUIOverlay()
{
return m_bUIOverlay;
}
//////////////////////////////////////////////////////////////////////////
//! Check if a sound is potentially hearable (used to check if loading a dialog is needed)
bool CXGame::IsSoundPotentiallyHearable(Vec3d &SoundPos, float fClipRadius)
{
ASSERT(m_pSystem);
ISoundSystem *pSoundSystem=m_pSystem->GetISoundSystem();
if (!pSoundSystem)
return false;
if (pSoundSystem->UsingDirectionalAttenuation())
return true;
CCamera &Cam=m_pSystem->GetViewCamera();
float fDist=(Cam.GetPos()-SoundPos).GetLengthSquared();
if (fDist<fClipRadius)
return true;
return false;
}
//////////////////////////////////////////////////////////////////////
//! Retrieve the server-rules.
CXServerRules* CXGame::GetRules() const
{
if (m_pServer)
return m_pServer->GetRules();
// if not server.
return 0;
}
//////////////////////////////////////////////////////////////////////
//!Force the view camera of the player
//!
//!(NOTE: this function is here because the editor needs it here)
void CXGame::SetViewAngles(const Vec3d &angles)
{
if (m_pClient)
m_pClient->m_PlayerProcessingCmd.SetDeltaAngles(angles);
}
//////////////////////////////////////////////////////////////////////
//! Retrieve the local player-entity
IEntity *CXGame::GetMyPlayer()
{
if (m_pClient)
return m_pClient->m_pISystem->GetLocalPlayer();
return NULL;
}
//////////////////////////////////////////////////////////////////////////
//! Selects the current UI (hud etc.)
void CXGame::SetCurrentUI(CUIHud *pUI)
{
if (pUI!=m_pCurrentUI) // new ui has been selected
{
// shutdown the old one
if (m_pCurrentUI)
m_pCurrentUI->ShutDown();
// init the new one
m_pCurrentUI = pUI;
m_pCurrentUI->Init(m_pScriptSystem);
}
}
// changes in and out of third person
//////////////////////////////////////////////////////////////////////////
void CXGame::SetViewMode(bool bThirdPerson)
{
if (GetMyPlayer())
{
CPlayer *pPlayer;
if (GetMyPlayer()->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&pPlayer))
{
// prevent player from going into third person mode when he is aiming
if (pPlayer->m_stats.aiming)
return;
// disable third person view when not in vehicle AND not in devmode
if(!IsDevModeEnable() && bThirdPerson && !pPlayer->GetVehicle())
return;
/*
if (pPlayer->GetVehicle() && bThirdPerson)
{
// do not allow the player to switch to 3rd person
// mode when driving a vehicle
return;
}
*/
pPlayer->m_bFirstPerson = !bThirdPerson;
// don't hide player - need to call CPlayer::OnDraw always for mounted weapons
// use pPlayer->m_bFirstPerson to not draw player
// if (bThirdPerson)
pPlayer->GetEntity()->DrawCharacter(0,ETY_DRAW_NORMAL);
// else
// pPlayer->GetEntity()->DrawCharacter(0,ETY_DRAW_NONE);
pPlayer->SetViewMode(bThirdPerson);
}
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::HideLocalPlayer( bool hide,bool bEditor )
{
m_bHideLocalPlayer = hide;
if (GetMyPlayer())
{
CPlayer *pPlayer;
if (GetMyPlayer()->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**)&pPlayer))
{
// [Marco K] weapons are now drawn through the player Entity
if(pPlayer->GetSelectedWeapon()){
if(hide){
pPlayer->GetEntity()->DrawCharacter(1, 0);
}
else{
pPlayer->GetEntity()->DrawCharacter(1, CS_FLAG_DRAW_NEAR);
}
}
if (!bEditor)
{
// Dont do this in editor.
pPlayer->GetEntity()->EnablePhysics(!hide);
if (!hide)
{
// Force player positin on physics if it was desynced.
Vec3 pos = pPlayer->GetEntity()->GetPos();
pPlayer->GetEntity()->SetPos(pos+Vec3(0,0,0.1f)); // Force change of position.
pPlayer->GetEntity()->SetPos(pos);
}
}
// hide actual player
if(hide)
{
pPlayer->GetEntity()->DrawCharacter(0,0);
}
else //if (!pPlayer->IsFirstPerson())
pPlayer->SetViewMode(!pPlayer->IsFirstPerson());
//GetEntity()->DrawCharacter(0,1);
}
}
}
//////////////////////////////////////////////////////////////////////////
void CXGame::ReloadScripts()
{
// includes the physical material properties (e.g. friction)
m_XSurfaceMgr.ReloadMaterials();
}
//////////////////////////////////////////////////////////////////////////
void CXGame::OnSetVar(ICVar *pVar)
{
IXSystem *pS=GetXSystem();
if (pS && IsMultiplayer())
pS->OnSetVar(pVar);
}
//////////////////////////////////////////////////////////////////////////
void CXGame::CreateExplosion(const Vec3& pos,float fDamage,float rmin,float rmax,float radius,float fImpulsivePressure,
float fShakeFactor,float fDeafnessRadius,float fDeafnessTime,
float fImpactForceMul,float fImpactForceMulFinal,float fImpactForceMulFinalTorso,
float rMinOcc,int nOccRes,int nOccGrow, IEntity *pShooter, int shooterSSID, IEntity *pWeapon,
float fTerrainDefSize,int nTerrainDecalId, bool bScheduled)
{
if (!bScheduled && IsMultiplayer() && UseFixedStep())
{
if (IsServer())
ScheduleEvent(-1, pos,fDamage,rmin,rmax,radius,fImpulsivePressure,fShakeFactor,fDeafnessRadius,fDeafnessTime,fImpactForceMul,
fImpactForceMulFinal,fImpactForceMulFinalTorso,rMinOcc,nOccRes,nOccGrow, pShooter,shooterSSID,pWeapon, fTerrainDefSize,nTerrainDecalId);
return;
}
IPhysicalWorld *pWorld = m_pSystem->GetIPhysicalWorld();
int iTypes = ent_rigid|ent_sleeping_rigid|ent_living;
if (m_pSystem->GetIConsole()->GetCVar("physics_quality")->GetIVal()>=2)
iTypes |= ent_independent;
//simulate the first explosion only for applying damage(0 as impulse and -1 as occlusion res)
// [Anton] the first explosion is a normal one: it builds occlusion map and applies impulse
pWorld->SimulateExplosion(pos,pos, rmin,rmax,rmin, fImpulsivePressure, nOccRes,nOccGrow,rMinOcc, 0,0, iTypes);
float force = fDamage*.0173f;
float falloff, curDamage;
if( force > 2.0f )
force = 2.0f;
m_pSystem->GetI3DEngine()->ApplyForceToEnvironment(pos,radius,force);
IPhysicalEntity **ppList = NULL;
int iNumEntites;
int i;
IEntity *pIEntity = NULL;
vectorf vMin(pos.x - radius, pos.y - radius, pos.z - radius);
vectorf vMax(pos.x + radius, pos.y + radius, pos.z + radius);
_SmartScriptObject pGR(m_pScriptSystem,true);
m_pScriptSystem->GetGlobalValue("GameRules",*pGR);
//////////////////////////////////////////////////////////////////////////
// Check independent entities.
//////////////////////////////////////////////////////////////////////////
ppList = NULL;
iNumEntites = pWorld->GetEntitiesInBox(vMin, vMax, ppList, ent_independent|ent_allocate_list);
for (i=0; i<iNumEntites; i++)
{
int physType = ppList[i]->GetiForeignData();
if (physType == OT_BOID)
{
// Check if boid hit.
CBoidObject *pBoid = (CBoidObject*)ppList[i]->GetForeignData(OT_BOID);
if (pBoid)
{
string surfaceName;
pBoid->Kill( pos,(pBoid->m_pos-pos)*10.0f,surfaceName );
}
}
}
pWorld->GetPhysUtils()->DeletePointer(ppList);
//////////////////////////////////////////////////////////////////////////
ppList = NULL;
iNumEntites = pWorld->GetEntitiesInBox(vMin, vMax, ppList, (ent_all&~(ent_terrain|ent_independent))|ent_allocate_list);
for (i=0; i<iNumEntites; i++)
{
pIEntity = (IEntity *) ppList[i]->GetForeignData();
if (!pIEntity)
{
continue;
}
// to take big objects into account be measure the distance to the bounding sphere surface
float fPhyEntityRad = pIEntity->GetRadiusPhys();
float fDistance = (pos - pIEntity->GetPos()).Length()-fPhyEntityRad;
if(fDistance<0)
fDistance=0; // the objects interpenetrate
if (fDistance > radius)
continue;
falloff = 1.0f - fDistance / radius;
curDamage = fDamage*falloff;
Vec3 bbox[2]; pIEntity->GetBBox(bbox[0],bbox[1]);
Vec3 dir=(bbox[0]+bbox[1])*0.5f-pos;//pIEntity->GetPos()-pos;
dir.Normalize();
CScriptObjectVector oDir(m_pScriptSystem),oPos(m_pScriptSystem);
oDir=dir; oPos=pIEntity->GetPos();
// send DEAFENED event is needed...
if (fDeafnessRadius>0.0f)
{
float fDeafenedTime=fDeafnessTime*(1.0f-fDistance/fDeafnessRadius);;
_SmartScriptObject pObj(m_pScriptSystem);
pObj->SetValue("fTime", fDeafenedTime);
pIEntity->SendScriptEvent(ScriptEvent_Deafened, *pObj);
}
// send DAMAGE event
_SmartScriptObject pTable(m_pScriptSystem);
if (pWeapon)
pTable->SetValue("weapon",pWeapon->GetScriptObject());
if (pIEntity->GetScriptObject())
pTable->SetValue("target",pIEntity->GetScriptObject());
pTable->SetValue( "explosion",true );
if (pShooter && !IsMultiplayer()) // in Multiplayer it's not save to send the shooter - the EntityId might be reused already
pTable->SetValue("shooter",pShooter->GetScriptObject());
if(shooterSSID!=-1) // -1 means unknown ClientID
pTable->SetValue("shooterSSID",shooterSSID); // in Multiplayer this is the save way to get the shooter
pTable->SetValue("dir",*oDir);
pTable->SetValue("damage",curDamage);
pTable->SetValue("damage_type", "normal");
pTable->SetValue("weapon_death_anim_id", 0);
pTable->SetValue("pos",*oPos);
pTable->SetValue("ipart", -1);
pTable->SetValue("impact_force_mul",fImpactForceMul*falloff);
pTable->SetValue("impact_force_mul_final",fImpactForceMulFinal*falloff);
pTable->SetValue("impact_force_mul_final_torso",fImpactForceMulFinalTorso*falloff);
//_SmartScriptObject pMat(m_pScriptSystem, true);
//if (m_pScriptSystem->GetGlobalValue("mat_flesh", pMat))
IScriptObject *pMat = NULL;
pMat = m_XSurfaceMgr.GetMaterialByName("mat_flesh");
if (pMat)
pTable->SetValue("target_material", pMat);
pIEntity->OnDamage(pTable);
}
pWorld->GetPhysUtils()->DeletePointer(ppList);
//
//shake the camera from explosion
pIEntity = GetMyPlayer();
if( pIEntity )
{
CPlayer* pPlayer=NULL;
CXClient *pClient=GetClient();
if (pIEntity->GetContainer())
pIEntity->GetContainer()->QueryContainerInterface(CIT_IPLAYER,(void**) &pPlayer);
if(pPlayer && pClient)
{
// float distCoeff = damage/(pIEntity->GetPos()-pos).Length();
// float distCoeff = damage*(1.0f - (pIEntity->GetPos()-pos).Length()*pClient->cl_explShakeDCoef->GetFVal());
float distCoeff = (1.0f - (pIEntity->GetPos()-pos).Length()*pClient->cl_explShakeDCoef);
if( distCoeff>1.0f )
distCoeff = 1.0f;
if( distCoeff>0.0f )
{
distCoeff *= fShakeFactor;
pPlayer->SetShakeL( Vec3(fDamage*distCoeff*pClient->cl_explShakeAmplH,
fDamage*distCoeff*pClient->cl_explShakeAmplH,
fDamage*distCoeff*pClient->cl_explShakeAmplV),
Vec3(pClient->cl_explShakeFreq, pClient->cl_explShakeFreq, pClient->cl_explShakeFreq),
distCoeff*pClient->cl_explShakeTime);
}
}
}
//simulate the explosion for adding impulse .
// [Anton] the 2nd explosion has nOccRes=-1, meaning it will reuse the occlusion map from the previous explosion
// and add impulse only to the objects that were not affected by the previous explosion
pWorld->SimulateExplosion(pos,pos, rmin, rmax, rmin, fImpulsivePressure, -1,nOccGrow,rMinOcc, 0,0,iTypes);
if (fTerrainDefSize>0)
{
bool bDeform = false;
//check if e_deformable_terrain for some reason is NULL, maybe at the init time it wasnt already created.
if (!e_deformable_terrain)
e_deformable_terrain = m_pSystem->GetIConsole()->GetCVar("e_deformable_terrain");
// always make it false, when e_deformable_terrain is set to 0
if (e_deformable_terrain)
bDeform = e_deformable_terrain->GetIVal()!=0?true:false;
Vec3d vHitDir = (pShooter->GetPos() - pos).GetNormalized();
m_pSystem->GetI3DEngine()->OnExplosion(pos,vHitDir,fTerrainDefSize,nTerrainDecalId,bDeform);
}
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::GoreOn() const
{
return (g_Gore->GetIVal()==2);
}
//////////////////////////////////////////////////////////////////////////
IBitStream *CXGame::GetIBitStream()
{
if(IsMultiplayer())
return &m_BitStreamCompressed;
return &m_BitStreamBase;
}
//////////////////////////////////////////////////////////////////////////
bool CXGame::ExecuteScript(const char *sPath,bool bForceReload)
{
string temp=sPath;
string::size_type n;
n=temp.find("$GT$");
if(n!=string::npos){
temp.replace(n,4,g_GameType->GetString());
if(!m_pScriptSystem->ExecuteFile(temp.c_str(),false,bForceReload))
{
temp=sPath;
temp.replace(n,4,"Default");
return m_pScriptSystem->ExecuteFile(temp.c_str(),true,bForceReload);
}
return true;
}
//no special path
return m_pScriptSystem->ExecuteFile(sPath,true);
}
//////////////////////////////////////////////////////////////////////////
void CXGame::OnCollectUserData(INT_PTR nValue,int nCookie) //AMD Port
{
switch(nCookie){
case USER_DATA_SCRIPTOBJRENDERER:{
CScriptObjectRenderer *pSS=(CScriptObjectRenderer *)nValue;
delete pSS;
}
break;
default:
break;
}
}
//////////////////////////////////////////////////////////////////////////
int CXGame::AddTimer(IScriptObject *pTable,unsigned int nStartTimer,unsigned int nTimer,IScriptObject *pUserData,bool bUpdateDuringPause)
{
return (m_pScriptTimerMgr->AddTimer(pTable,nStartTimer,nTimer,pUserData,bUpdateDuringPause));
}