450 lines
11 KiB
C++
450 lines
11 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Source code
|
|
// Copyright (c) Crytek 2001-2004
|
|
//
|
|
// History:
|
|
// - May 2003: Created by MarcoK
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
#include "StdAfx.h"
|
|
#include "WeaponSystemEx.h"
|
|
#include "WeaponClass.h"
|
|
#include "Game.h"
|
|
#include "XPlayer.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Iterator class for weapon names
|
|
|
|
class CNameIterator : public INameIterator
|
|
{
|
|
public:
|
|
CNameIterator() { m_itPos = m_lNames.end(); };
|
|
~CNameIterator() { };
|
|
void AddNameString(const string strName)
|
|
{ m_lNames.push_back(strName); MoveFirst(); };
|
|
// INameInterator Implementation
|
|
void Release() { delete this; };
|
|
void MoveFirst() { m_itPos = m_lNames.begin(); };
|
|
bool MoveNext() {
|
|
if (m_itPos != m_lNames.end()) {
|
|
m_itPos++;
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
bool Get(char *pszBuffer, INT *pSize) {
|
|
if (m_itPos == m_lNames.end())
|
|
return false;
|
|
if ((INT) (* m_itPos).length() >= *pSize) {
|
|
*pSize = -1;
|
|
return false;
|
|
}
|
|
strcpy(pszBuffer, (* m_itPos).c_str());
|
|
*pSize = (* m_itPos).length();
|
|
return true;
|
|
}
|
|
protected:
|
|
std::list<string> m_lNames;
|
|
std::list<string>::iterator m_itPos;
|
|
};
|
|
|
|
|
|
CWeaponSystemEx::CWeaponSystemEx()
|
|
{
|
|
m_pScriptSystem = NULL;
|
|
m_bRaiseScriptError = true;
|
|
m_soWeaponClassesTable = NULL;
|
|
m_soProjectileTable = NULL;
|
|
m_pGame = NULL;
|
|
}
|
|
|
|
CWeaponSystemEx::~CWeaponSystemEx()
|
|
{
|
|
// free memory
|
|
Reset();
|
|
}
|
|
|
|
bool CWeaponSystemEx::AddWeaponClass(CWeaponClass *weaponClass)
|
|
{
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
// check if we have a duplicate weapon class
|
|
if ((*i)->GetName() == weaponClass->GetName())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// no duplicates found, so append the new weapon class to the back
|
|
m_vWeaponClasses.push_back(weaponClass);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
INameIterator * CWeaponSystemEx::GetAvailableWeapons()
|
|
{
|
|
CNameIterator *pIterator = new CNameIterator;
|
|
for (TWeaponClasses::iterator it=m_vWeaponClasses.begin(); it!=m_vWeaponClasses.end(); it++)
|
|
pIterator->AddNameString((* it)->GetName().c_str());
|
|
return (INameIterator *) pIterator;
|
|
}
|
|
|
|
INameIterator * CWeaponSystemEx::GetAvailableProjectiles()
|
|
{
|
|
CNameIterator *pIterator = new CNameIterator;
|
|
for (TProjectileClasses::iterator it=m_vProjectileClasses.begin(); it!=m_vProjectileClasses.end(); it++)
|
|
pIterator->AddNameString((* it)->m_sName.c_str());
|
|
return (INameIterator *) pIterator;
|
|
}
|
|
|
|
bool CWeaponSystemEx::Init(CXGame *pGame, bool bRaiseError)
|
|
{
|
|
Reset();
|
|
|
|
m_pGame = pGame;
|
|
m_pScriptSystem = m_pGame->GetScriptSystem();
|
|
m_sGameType = m_pGame->g_GameType->GetString();
|
|
m_bRaiseScriptError = bRaiseError;
|
|
|
|
// Add some global variables
|
|
RegisterScriptConstants();
|
|
|
|
if (!ExecuteScript("Weapons/WeaponsParams.lua"))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!ExecuteScript("Weapons/WeaponSystem.lua"))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_soWeaponClassesTable = m_pScriptSystem->CreateEmptyObject();
|
|
// now, we can load the weapon classes and firemode descriptions
|
|
if (!m_pScriptSystem->GetGlobalValue("WeaponClassesEx", m_soWeaponClassesTable))
|
|
{
|
|
TRACE("Cannot access WeaponClassesEx");
|
|
return false;
|
|
}
|
|
|
|
// iterate over all weapon classes
|
|
m_soWeaponClassesTable->BeginIteration();
|
|
while(m_soWeaponClassesTable->MoveNext())
|
|
{
|
|
// we assume that the WeaponParams table always contains 'key = subtable' pairs
|
|
assert(m_soWeaponClassesTable->GetCurrentType() == svtObject);
|
|
const char *sWeaponClassName;
|
|
|
|
m_soWeaponClassesTable->GetCurrentKey(sWeaponClassName);
|
|
|
|
// create a new weapon class
|
|
CWeaponClass *pWeaponClass = new CWeaponClass(*this);
|
|
if (pWeaponClass->Init(sWeaponClassName))
|
|
{
|
|
//TRACE("WeaponSystemEx: ADDING %s", sWeaponClassName);
|
|
AddWeaponClass(pWeaponClass);
|
|
// for multiplayer we always want to load all classes immediately (bug 5825)
|
|
if (GetGame()->IsMultiplayer())
|
|
{
|
|
pWeaponClass->Load();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete pWeaponClass;
|
|
}
|
|
}
|
|
m_soWeaponClassesTable->EndIteration();
|
|
|
|
m_soProjectileTable = m_pScriptSystem->CreateEmptyObject();
|
|
// now, we can load the weapon classes and firemode descriptions
|
|
if (!m_pScriptSystem->GetGlobalValue("Projectiles", m_soProjectileTable))
|
|
{
|
|
TRACE("Cannot access Projectiles");
|
|
return false;
|
|
}
|
|
|
|
// iterate over all weapon classes
|
|
m_soProjectileTable->BeginIteration();
|
|
while(m_soProjectileTable->MoveNext())
|
|
{
|
|
// we assume that the Projectiles table always contains 'key = subtable' pairs
|
|
assert(m_soProjectileTable->GetCurrentType() == svtObject);
|
|
const char *sProjectileName;
|
|
|
|
_SmartScriptObject soProjectile(m_pScriptSystem);
|
|
m_soProjectileTable->GetCurrentKey(sProjectileName);
|
|
m_soProjectileTable->GetCurrent(*soProjectile);
|
|
|
|
{
|
|
const char *model="";
|
|
bool bOk=soProjectile->GetValue("model",model); assert(bOk);
|
|
|
|
if(!bOk)continue;
|
|
|
|
IStatObj *pObj = GetGame()->GetSystem()->GetI3DEngine()->MakeObject(model);
|
|
|
|
IEntityClassRegistry *pReg=GetGame()->GetClassRegistry();
|
|
|
|
EntityClass *pClass = pReg->GetByClass(sProjectileName); assert(pClass);
|
|
|
|
if (pClass)
|
|
{
|
|
GetGame()->GetClassRegistry()->LoadRegistryEntry(pClass); // load the associated script object
|
|
m_vProjectileClasses.push_back(new CProjectileClass(pClass->ClassId, sProjectileName, pObj, *this));
|
|
}
|
|
}
|
|
}
|
|
m_soProjectileTable->EndIteration();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CWeaponSystemEx::AddProjectileClass( int classid )
|
|
{
|
|
// currently not needed
|
|
}
|
|
|
|
void CWeaponSystemEx::Reset()
|
|
{
|
|
if(m_pGame && m_pGame->GetMyPlayer())
|
|
{
|
|
IEntityContainer *pCnt;
|
|
CPlayer *pPlayer = NULL;
|
|
|
|
pCnt=m_pGame->GetMyPlayer()->GetContainer();
|
|
|
|
if(pCnt)
|
|
{
|
|
pCnt->QueryContainerInterface(CIT_IPLAYER,(void **) &pPlayer);
|
|
if(pPlayer)
|
|
{
|
|
pPlayer->SelectWeapon(-1, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// kill registered weapon classes
|
|
while (!m_vWeaponClasses.empty())
|
|
{
|
|
delete m_vWeaponClasses.back();
|
|
m_vWeaponClasses.pop_back();
|
|
}
|
|
|
|
SAFE_RELEASE(m_soWeaponClassesTable);
|
|
|
|
// kill registered projectile classes
|
|
while (!m_vProjectileClasses.empty())
|
|
{
|
|
delete m_vProjectileClasses.back();
|
|
m_vProjectileClasses.pop_back();
|
|
}
|
|
|
|
SAFE_RELEASE(m_soProjectileTable);
|
|
|
|
// kill the CGF cache
|
|
while (!m_vCachedObjects.empty())
|
|
{
|
|
GetGame()->GetSystem()->GetI3DEngine()->ReleaseObject(m_vCachedObjects.back());
|
|
m_vCachedObjects.pop_back();
|
|
}
|
|
|
|
UnloadScript("Weapons/WeaponsParams.lua");
|
|
}
|
|
|
|
bool CWeaponSystemEx::ExecuteScript(const string& sScriptName)
|
|
{
|
|
if (m_pScriptSystem == NULL)
|
|
return false;
|
|
|
|
string sFilename = "Scripts\\" + m_sGameType + "\\Entities\\" + sScriptName;
|
|
m_pGame->GetSystem()->GetILog()->Log("WEAPONEX : Loading %s",sFilename.c_str());
|
|
if (!m_pScriptSystem->ExecuteFile(sFilename.c_str(), m_bRaiseScriptError))
|
|
{
|
|
sFilename = "Scripts\\Default\\Entities\\" + sScriptName;
|
|
m_pGame->GetSystem()->GetILog()->Log("WEAPONEX : Loading %s",sFilename.c_str());
|
|
if (!m_pScriptSystem->ExecuteFile(sFilename.c_str(), true))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CWeaponSystemEx::UnloadScript(const string& sScriptName)
|
|
{
|
|
if (m_pScriptSystem == NULL)
|
|
return;
|
|
|
|
string sFilename = "Scripts\\" + m_sGameType + "\\Entities\\" + sScriptName;
|
|
|
|
m_pGame->GetSystem()->GetILog()->Log("WEAPONEX : UNLoading %s",sFilename.c_str());
|
|
m_pScriptSystem->UnloadScript(sFilename.c_str());
|
|
|
|
sFilename = "Scripts\\Default\\Entities\\" + sScriptName;
|
|
m_pGame->GetSystem()->GetILog()->Log("WEAPONEX : UNLoading %s",sFilename.c_str());
|
|
|
|
m_pScriptSystem->UnloadScript(sFilename.c_str());
|
|
}
|
|
|
|
CWeaponClass* CWeaponSystemEx::GetWeaponClassByID(int ID) const
|
|
{
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
if ((*i)->GetID() == ID)
|
|
return (*i);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int CWeaponSystemEx::GetWeaponClassIDByName(const string& name) const
|
|
{
|
|
CWeaponClass *pWC = GetWeaponClassByName(name);
|
|
|
|
if (pWC)
|
|
return pWC->GetID();
|
|
|
|
return -1;
|
|
}
|
|
|
|
CWeaponClass* CWeaponSystemEx::GetWeaponClassByName(const string& name) const
|
|
{
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
if ((*i)->GetName() == name)
|
|
return (*i);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
unsigned CWeaponSystemEx::MemStats() const
|
|
{
|
|
unsigned memSize = sizeof *this;
|
|
|
|
memSize += m_sGameType.capacity();
|
|
|
|
memSize += m_vWeaponClasses.capacity() * sizeof(void*);
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
memSize += (*i)->MemStats();
|
|
}
|
|
|
|
memSize += m_vProjectileClasses.capacity() * sizeof(void*);
|
|
for (TProjectileClasses::const_iterator i = m_vProjectileClasses.begin(); i != m_vProjectileClasses.end(); ++i)
|
|
{
|
|
memSize += sizeof(CProjectileClass);
|
|
memSize += (*i)->m_sName.capacity();
|
|
}
|
|
|
|
memSize += m_vCachedObjects.capacity() * sizeof(void*);
|
|
|
|
return memSize;
|
|
}
|
|
|
|
void CWeaponSystemEx::Read(CStream &stm)
|
|
{
|
|
// reset our internal state
|
|
Reset();
|
|
|
|
BYTE n;
|
|
|
|
// get number of weapon classes
|
|
stm.Read(n);
|
|
|
|
// get weapon classes
|
|
for (int i = 0; i < n; ++i)
|
|
{
|
|
CWeaponClass *pWeaponClass = new CWeaponClass(*this);
|
|
pWeaponClass->Read(stm);
|
|
|
|
AddWeaponClass(pWeaponClass);
|
|
}
|
|
}
|
|
|
|
void CWeaponSystemEx::Write(CStream &stm) const
|
|
{
|
|
assert(m_vWeaponClasses.size() <= 255);
|
|
|
|
// number of weapon classes
|
|
stm.Write((BYTE)m_vWeaponClasses.size());
|
|
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
(*i)->Write(stm);
|
|
}
|
|
}
|
|
|
|
bool CWeaponSystemEx::AddWeapon(const string& name)
|
|
{
|
|
for (TWeaponClasses::const_iterator i = m_vWeaponClasses.begin(); i != m_vWeaponClasses.end(); ++i)
|
|
{
|
|
if ((*i)->GetName() == name && !(*i)->IsLoaded())
|
|
{
|
|
if((*i)->Load())
|
|
{
|
|
_SmartScriptObject cWeaponLoadedTable(m_pScriptSystem, true);
|
|
|
|
if (m_pScriptSystem->GetGlobalValue("WeaponsLoaded", cWeaponLoadedTable))
|
|
{
|
|
cWeaponLoadedTable->SetValue(name.c_str(), true);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CWeaponSystemEx::IsLeftHanded ()
|
|
{
|
|
return m_pGame->g_LeftHanded->GetIVal() != 0;
|
|
}
|
|
|
|
void CWeaponSystemEx::CacheObject(const string& name)
|
|
{
|
|
IStatObj *pObject = GetGame()->GetSystem()->GetI3DEngine()->MakeObject(name.c_str());
|
|
if (pObject)
|
|
{
|
|
m_vCachedObjects.push_back(pObject);
|
|
}
|
|
}
|
|
|
|
bool CWeaponSystemEx::IsProjectileClass( const EntityClassId clsid )
|
|
{
|
|
for (unsigned int i=0;i<m_vProjectileClasses.size();i++)
|
|
{
|
|
if (m_vProjectileClasses[i]->m_ClassID == clsid)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CWeaponClass* CWeaponSystemEx::GetWeaponClass(unsigned int index) const
|
|
{
|
|
if (index < m_vWeaponClasses.size())
|
|
return m_vWeaponClasses[index];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
void CWeaponSystemEx::RegisterScriptConstants() const
|
|
{
|
|
// Add some global variables
|
|
#define SET_GLOBAL(name)\
|
|
m_pScriptSystem->SetGlobalValue(#name, name);
|
|
|
|
SET_GLOBAL(FireMode_Instant);
|
|
SET_GLOBAL(FireMode_Projectile);
|
|
SET_GLOBAL(FireMode_Melee);
|
|
SET_GLOBAL(FireMode_EngineerTool);
|
|
|
|
#undef SET_GLOBAL
|
|
}
|