mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-13 23:37:58 +03:00
Added an entity factory manager for custom weapons
This commit is contained in:
parent
f8a8d49be7
commit
5a0c406dbf
178
sp/src/game/server/mapbase/custom_weapon_factory.cpp
Normal file
178
sp/src/game/server/mapbase/custom_weapon_factory.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include "cbase.h"
|
||||||
|
#include "custom_weapon_factory.h"
|
||||||
|
|
||||||
|
#define GENERIC_MANIFEST_FILE "scripts/mapbase_default_manifest.txt"
|
||||||
|
#define AUTOLOADED_MANIFEST_FILE UTIL_VarArgs("maps/%s_manifest.txt", MapName())
|
||||||
|
|
||||||
|
extern ConVar mapbase_load_default_manifest;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CCustomWeaponSystem::CCustomWeaponSystem() : CAutoGameSystem("CustomWeaponFactorySystem")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::LevelInitPreEntity()
|
||||||
|
{
|
||||||
|
// Check for a generic "mapname_manifest.txt" file and load it.
|
||||||
|
if (filesystem->FileExists(AUTOLOADED_MANIFEST_FILE, "GAME"))
|
||||||
|
{
|
||||||
|
AddManifestFile(AUTOLOADED_MANIFEST_FILE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load the generic script instead.
|
||||||
|
ParseGenericManifest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a generic, hardcoded manifest with hardcoded names.
|
||||||
|
void CCustomWeaponSystem::ParseGenericManifest()
|
||||||
|
{
|
||||||
|
if (!mapbase_load_default_manifest.GetBool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
KeyValues* pKV = new KeyValues("DefaultManifest");
|
||||||
|
pKV->LoadFromFile(filesystem, GENERIC_MANIFEST_FILE);
|
||||||
|
|
||||||
|
AddManifestFile(pKV/*, true*/);
|
||||||
|
|
||||||
|
pKV->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::AddManifestFile(const char* file)
|
||||||
|
{
|
||||||
|
KeyValues* pKV = new KeyValues(file);
|
||||||
|
if (!pKV->LoadFromFile(filesystem, file))
|
||||||
|
{
|
||||||
|
Warning("Mapbase Manifest: \"%s\" is unreadable or missing (can't load KV, check for syntax errors)\n", file);
|
||||||
|
pKV->deleteThis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGMsg(1, CON_GROUP_MAPBASE_MISC, "===== Mapbase Manifest: Loading manifest file %s =====\n", file);
|
||||||
|
|
||||||
|
AddManifestFile(pKV, false);
|
||||||
|
|
||||||
|
CGMsg(1, CON_GROUP_MAPBASE_MISC, "==============================================================================\n");
|
||||||
|
|
||||||
|
pKV->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::AddManifestFile(KeyValues* pKV, bool bDontWarn)
|
||||||
|
{
|
||||||
|
KeyValues* pKey = pKV->FindKey("weapons");
|
||||||
|
|
||||||
|
if (pKey)
|
||||||
|
{
|
||||||
|
char value[MAX_PATH];
|
||||||
|
// Parse %mapname%, etc.
|
||||||
|
bool inparam = false;
|
||||||
|
CUtlStringList outStrings;
|
||||||
|
V_SplitString(pKey->GetString(), "%", outStrings);
|
||||||
|
for (int i = 0; i < outStrings.Count(); i++)
|
||||||
|
{
|
||||||
|
if (inparam)
|
||||||
|
{
|
||||||
|
if (FStrEq(outStrings[i], "mapname"))
|
||||||
|
{
|
||||||
|
Q_strncat(value, MapName(), sizeof(value));
|
||||||
|
}
|
||||||
|
else if (FStrEq(outStrings[i], "language"))
|
||||||
|
{
|
||||||
|
#ifdef CLIENT_DLL
|
||||||
|
char uilanguage[64];
|
||||||
|
engine->GetUILanguage(uilanguage, sizeof(uilanguage));
|
||||||
|
Q_strncat(value, uilanguage, sizeof(value));
|
||||||
|
#else
|
||||||
|
// Give up, use English
|
||||||
|
Q_strncat(value, "english", sizeof(value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_strncat(value, outStrings[i], sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
inparam = !inparam;
|
||||||
|
}
|
||||||
|
|
||||||
|
outStrings.PurgeAndDeleteElements();
|
||||||
|
bDontWarn = pKV->GetBool("NoErrors", bDontWarn);
|
||||||
|
|
||||||
|
LoadCustomWeaponsManifest(value, bDontWarn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Factory CustomWeaponsFactoryDictionary()
|
||||||
|
void CCustomWeaponSystem::LoadCustomWeaponsManifest(const char* file, bool bDontWarn)
|
||||||
|
{
|
||||||
|
KeyValuesAD pKV("weapons_manifest");
|
||||||
|
if (pKV->LoadFromFile(filesystem, file, "GAME"))
|
||||||
|
{
|
||||||
|
for (KeyValues *pkvWeapon = pKV->GetFirstValue(); pkvWeapon != nullptr; pkvWeapon = pkvWeapon->GetNextValue())
|
||||||
|
{
|
||||||
|
const char* pszClassname = pkvWeapon->GetName();
|
||||||
|
KeyValuesAD pkvWeaponScript("WeaponData");
|
||||||
|
if (pkvWeaponScript->LoadFromFile(filesystem, pkvWeapon->GetString(), "GAME"))
|
||||||
|
{
|
||||||
|
const char* pszFactory = pkvWeaponScript->GetString("custom_factory", nullptr);
|
||||||
|
unsigned short FactoryIndex = Factory.Find(pszFactory);
|
||||||
|
if (Factory.IsValidIndex(FactoryIndex))
|
||||||
|
{
|
||||||
|
unsigned short ClassIndex = m_ClassFactories.Find(pszClassname);
|
||||||
|
if (!m_ClassFactories.IsValidIndex(ClassIndex))
|
||||||
|
{
|
||||||
|
ClassIndex = m_ClassFactories.Insert(pszClassname);
|
||||||
|
m_ClassFactories[ClassIndex].pOldFactory = EntityFactoryDictionary()->FindFactory(pszClassname);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClassFactories[ClassIndex].sDataFile = file;
|
||||||
|
m_ClassFactories[ClassIndex].pNewFactory = Factory.Element(FactoryIndex);
|
||||||
|
EntityFactoryDictionary()->UninstallFactory(pszClassname);
|
||||||
|
EntityFactoryDictionary()->InstallFactory(m_ClassFactories[ClassIndex].pNewFactory, pszClassname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef Factory
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::LevelShutdownPostEntity()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_ClassFactories.Count(); i++)
|
||||||
|
{
|
||||||
|
EntityFactoryDictionary()->UninstallFactory(m_ClassFactories.GetElementName(i));
|
||||||
|
const CustomClassName_t& entry = m_ClassFactories.Element(i);
|
||||||
|
if (entry.pOldFactory)
|
||||||
|
EntityFactoryDictionary()->InstallFactory(entry.pOldFactory, m_ClassFactories.GetElementName(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClassFactories.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::ParseWeapon(CBaseCombatWeapon* pWeapon, const char* pClassName)
|
||||||
|
{
|
||||||
|
ICustomWeapon* pCustom = dynamic_cast<ICustomWeapon*> (pWeapon);
|
||||||
|
if (!pCustom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned short i = m_ClassFactories.Find(pClassName);
|
||||||
|
if (!m_ClassFactories.IsValidIndex(i))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pCustom->ParseCustomFromWeaponFile(m_ClassFactories[i].sDataFile.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlDict<IEntityFactory*, unsigned short>& CustomWeaponsFactoryDictionary()
|
||||||
|
{
|
||||||
|
static CUtlDict<IEntityFactory*, unsigned short> dict;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CCustomWeaponSystem g_CustomWeaponsSystem;
|
||||||
|
CCustomWeaponSystem* CustomWeaponSystem()
|
||||||
|
{
|
||||||
|
return &g_CustomWeaponsSystem;
|
||||||
|
}
|
76
sp/src/game/server/mapbase/custom_weapon_factory.h
Normal file
76
sp/src/game/server/mapbase/custom_weapon_factory.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef CUSTOM_WEAPON_FACTORY_H
|
||||||
|
#define CUSTOM_WEAPON_FACTORY_H
|
||||||
|
#pragma once
|
||||||
|
#include "utldict.h"
|
||||||
|
#include "utlsymbol.h"
|
||||||
|
|
||||||
|
CUtlDict< IEntityFactory*, unsigned short >& CustomWeaponsFactoryDictionary();
|
||||||
|
|
||||||
|
class ICustomWeapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void ParseCustomFromWeaponFile(const char* pFileName) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCustomWeaponSystem : public CAutoGameSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCustomWeaponSystem();
|
||||||
|
|
||||||
|
// Level init, shutdown
|
||||||
|
virtual void LevelInitPreEntity();
|
||||||
|
virtual void LevelShutdownPostEntity();
|
||||||
|
|
||||||
|
void ParseWeapon(CBaseCombatWeapon* pWeapon, const char* pClassName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ParseGenericManifest();
|
||||||
|
void AddManifestFile(const char* file);
|
||||||
|
void AddManifestFile(KeyValues* pKV, bool bDontWarn = false);
|
||||||
|
void LoadCustomWeaponsManifest(const char* file, bool bDontWarn = false);
|
||||||
|
|
||||||
|
typedef struct CustomClassName_s
|
||||||
|
{
|
||||||
|
CUtlSymbol sDataFile;
|
||||||
|
IEntityFactory* pNewFactory;
|
||||||
|
IEntityFactory* pOldFactory;
|
||||||
|
} CustomClassName_t;
|
||||||
|
CUtlDict<CustomClassName_t, unsigned short> m_ClassFactories;
|
||||||
|
};
|
||||||
|
|
||||||
|
CCustomWeaponSystem* CustomWeaponSystem();
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CCustomWeaponEntityFactory : public IEntityFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCustomWeaponEntityFactory(const char* pFactoryClass)
|
||||||
|
{
|
||||||
|
CustomWeaponsFactoryDictionary().Insert(pFactoryClass, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IServerNetworkable* Create(const char* pClassName)
|
||||||
|
{
|
||||||
|
T* pEnt = _CreateEntityTemplate((T*)NULL, pClassName);
|
||||||
|
CustomWeaponSystem()->ParseWeapon(pEnt, pClassName);
|
||||||
|
return pEnt->NetworkProp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy(IServerNetworkable* pNetworkable)
|
||||||
|
{
|
||||||
|
if (pNetworkable)
|
||||||
|
{
|
||||||
|
pNetworkable->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t GetEntitySize()
|
||||||
|
{
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_CUSTOM_WEAPON_FACTORY(factoryName, DLLClassName) \
|
||||||
|
static CCustomWeaponEntityFactory<DLLClassName> custom_weapon_##factoryName##_factory( #factoryName );
|
||||||
|
|
||||||
|
#endif // !CUSTOM_WEAPON_FACTORY_H
|
@ -63,6 +63,8 @@ $Project
|
|||||||
$File "mapbase\ai_grenade.h"
|
$File "mapbase\ai_grenade.h"
|
||||||
$File "mapbase\ai_monitor.cpp"
|
$File "mapbase\ai_monitor.cpp"
|
||||||
$File "mapbase\ai_weaponmodifier.cpp"
|
$File "mapbase\ai_weaponmodifier.cpp"
|
||||||
|
$File "mapbase\custom_weapon_factory.cpp"
|
||||||
|
$File "mapbase\custom_weapon_factory.h"
|
||||||
$File "mapbase\closecaption_entity.cpp"
|
$File "mapbase\closecaption_entity.cpp"
|
||||||
$File "mapbase\datadesc_mod.cpp"
|
$File "mapbase\datadesc_mod.cpp"
|
||||||
$File "mapbase\datadesc_mod.h"
|
$File "mapbase\datadesc_mod.h"
|
||||||
|
@ -76,6 +76,10 @@ public:
|
|||||||
virtual const char *GetCannonicalName( const char *pClassName );
|
virtual const char *GetCannonicalName( const char *pClassName );
|
||||||
void ReportEntitySizes();
|
void ReportEntitySizes();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void UninstallFactory(const char* pClassName);
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IEntityFactory *FindFactory( const char *pClassName );
|
IEntityFactory *FindFactory( const char *pClassName );
|
||||||
public:
|
public:
|
||||||
@ -203,6 +207,11 @@ void CEntityFactoryDictionary::ReportEntitySizes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
void CEntityFactoryDictionary::UninstallFactory(const char* pClassName)
|
||||||
|
{
|
||||||
|
m_Factories.Remove(pClassName);
|
||||||
|
}
|
||||||
|
|
||||||
int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 )
|
int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 )
|
||||||
{
|
{
|
||||||
CEntityFactoryDictionary *pFactoryDict = (CEntityFactoryDictionary*)EntityFactoryDictionary();
|
CEntityFactoryDictionary *pFactoryDict = (CEntityFactoryDictionary*)EntityFactoryDictionary();
|
||||||
|
@ -100,6 +100,9 @@ public:
|
|||||||
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
|
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
|
||||||
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
|
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
|
||||||
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
|
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void UninstallFactory(const char* pClassName) = 0;
|
||||||
|
#endif // MAPBASE
|
||||||
};
|
};
|
||||||
|
|
||||||
IEntityFactoryDictionary *EntityFactoryDictionary();
|
IEntityFactoryDictionary *EntityFactoryDictionary();
|
||||||
|
@ -581,6 +581,12 @@ int CWeaponCustomScripted::WeaponMeleeAttack2Condition( float flDot, float flDis
|
|||||||
|
|
||||||
return BaseClass::WeaponMeleeAttack2Condition( flDot, flDist );
|
return BaseClass::WeaponMeleeAttack2Condition( flDot, flDist );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_CUSTOM_WEAPON_FACTORY(vscript, CWeaponCustomScripted);
|
||||||
|
void CWeaponCustomScripted::ParseCustomFromWeaponFile(const char* pFileName)
|
||||||
|
{
|
||||||
|
Q_FileBase(pFileName, m_iszWeaponScriptName.GetForModify(), 256);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "basecombatweapon_shared.h"
|
#include "basecombatweapon_shared.h"
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
#include "vscript_client.h"
|
#include "vscript_client.h"
|
||||||
|
#else
|
||||||
|
#include "mapbase/custom_weapon_factory.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The base class of the scripted weapon is game-specific.
|
// The base class of the scripted weapon is game-specific.
|
||||||
@ -32,6 +34,9 @@
|
|||||||
HSCRIPT m_Func_##name;
|
HSCRIPT m_Func_##name;
|
||||||
|
|
||||||
class CWeaponCustomScripted : public SCRIPTED_WEAPON_DERIVED_FROM
|
class CWeaponCustomScripted : public SCRIPTED_WEAPON_DERIVED_FROM
|
||||||
|
#ifndef CLIENT_DLL
|
||||||
|
, public ICustomWeapon
|
||||||
|
#endif // !CLIENT_DLL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DECLARE_CLASS( CWeaponCustomScripted, SCRIPTED_WEAPON_DERIVED_FROM );
|
DECLARE_CLASS( CWeaponCustomScripted, SCRIPTED_WEAPON_DERIVED_FROM );
|
||||||
@ -106,6 +111,9 @@ public:
|
|||||||
int WeaponRangeAttack2Condition( float flDot, float flDist );
|
int WeaponRangeAttack2Condition( float flDot, float flDist );
|
||||||
int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
||||||
int WeaponMeleeAttack2Condition( float flDot, float flDist );
|
int WeaponMeleeAttack2Condition( float flDot, float flDist );
|
||||||
|
|
||||||
|
// Inherited via ICustomWeapon
|
||||||
|
virtual void ParseCustomFromWeaponFile(const char* pFileName) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ALLOW_SCRIPT_ACCESS();
|
ALLOW_SCRIPT_ACCESS();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user