123
This commit is contained in:
460
CryGame/GameMisc.cpp
Normal file
460
CryGame/GameMisc.cpp
Normal 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));
|
||||
}
|
||||
Reference in New Issue
Block a user