source-sdk-2013-mapbase/sp/src/game/server/mapbase/logic_externaldata.cpp

366 lines
11 KiB
C++
Raw Normal View History

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "filesystem.h"
#include "KeyValues.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CLogicExternalData : public CLogicalEntity
{
DECLARE_CLASS( CLogicExternalData, CLogicalEntity );
DECLARE_DATADESC();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
public:
~CLogicExternalData();
void LoadFile();
void SaveFile();
void SetBlock(string_t iszNewTarget, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL);
void Activate();
// Inputs
void InputWriteKeyValue( inputdata_t &inputdata );
void InputRemoveKeyValue( inputdata_t &inputdata );
void InputReadKey( inputdata_t &inputdata );
void InputSetBlock( inputdata_t &inputdata );
void InputSave( inputdata_t &inputdata );
void InputReload( inputdata_t &inputdata );
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetKeyValues( void );
HSCRIPT ScriptGetKeyValueBlock( void );
void ScriptSetKeyValues( HSCRIPT hKV );
void ScriptSetKeyValueBlock( HSCRIPT hKV );
void ScriptSetBlock( const char *szNewBlock, HSCRIPT hActivator = NULL, HSCRIPT hCaller = NULL );
#endif
char m_iszFile[MAX_PATH];
// Root file
KeyValues *m_pRoot;
// Our specific block
KeyValues *m_pBlock;
//string_t m_iszBlock; // Use m_target
bool m_bSaveEachChange;
bool m_bReloadBeforeEachAction;
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
string_t m_iszMapname;
COutputString m_OutValue;
};
LINK_ENTITY_TO_CLASS(logic_externaldata, CLogicExternalData);
BEGIN_DATADESC( CLogicExternalData )
// Keys
//DEFINE_KEYFIELD( m_iszBlock, FIELD_STRING, "Block" ),
DEFINE_KEYFIELD( m_bSaveEachChange, FIELD_BOOLEAN, "SaveEachChange" ),
DEFINE_KEYFIELD( m_bReloadBeforeEachAction, FIELD_BOOLEAN, "ReloadBeforeEachAction" ),
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
DEFINE_KEYFIELD( m_iszMapname, FIELD_STRING, "Mapname" ),
// This should be cached each load
//DEFINE_ARRAY( m_iszFile, FIELD_CHARACTER, MAX_PATH ),
// Inputs
DEFINE_INPUTFUNC( FIELD_STRING, "WriteKeyValue", InputWriteKeyValue ),
DEFINE_INPUTFUNC( FIELD_STRING, "RemoveKeyValue", InputRemoveKeyValue ),
DEFINE_INPUTFUNC( FIELD_STRING, "ReadKey", InputReadKey ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetBlock", InputSetBlock ),
DEFINE_INPUTFUNC( FIELD_VOID, "Save", InputSave ),
DEFINE_INPUTFUNC( FIELD_VOID, "Reload", InputReload ),
// Outputs
DEFINE_OUTPUT(m_OutValue, "OutValue"),
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( CLogicExternalData, CBaseEntity, "An entity which loads keyvalues from an external data file." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValues, "GetKeyValues", "Gets the external data expressed in CScriptKeyValues." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueBlock, "GetKeyValueBlock", "Gets the current external data block expressed in CScriptKeyValues." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValues, "SetKeyValues", "Sets the external data from a CScriptKeyValues object." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetKeyValueBlock, "SetKeyValues", "Sets the current external data block from a CScriptKeyValues object." )
DEFINE_SCRIPTFUNC( LoadFile, "Loads external data from the external file." )
DEFINE_SCRIPTFUNC( SaveFile, "Saves the external data to the external file." )
END_SCRIPTDESC();
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CLogicExternalData::~CLogicExternalData()
{
if (m_pRoot)
m_pRoot->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::LoadFile()
{
if (m_pRoot)
m_pRoot->deleteThis();
m_pRoot = new KeyValues( m_iszFile );
m_pRoot->LoadFromFile(g_pFullFileSystem, m_iszFile, "MOD");
// This shold work even if the file didn't load.
if (m_target != NULL_STRING)
{
m_pBlock = m_pRoot->FindKey(STRING(m_target), true);
}
else
{
// Just do things from root
m_pBlock = m_pRoot;
}
if (!m_pBlock)
{
Warning("WARNING! %s has NULL m_pBlock! Removing...\n", GetDebugName());
UTIL_Remove(this);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::SaveFile()
{
DevMsg("Saving to %s...\n", m_iszFile);
m_pRoot->SaveToFile(g_pFullFileSystem, m_iszFile, "MOD", false, true);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::SetBlock(string_t iszNewTarget, CBaseEntity *pActivator, CBaseEntity *pCaller)
{
if (STRING(iszNewTarget)[0] == '!')
{
if (FStrEq(STRING(iszNewTarget), "!self"))
iszNewTarget = GetEntityName();
else if (pActivator && FStrEq(STRING(iszNewTarget), "!activator"))
iszNewTarget = pActivator->GetEntityName();
else if (pCaller && FStrEq(STRING(iszNewTarget), "!caller"))
iszNewTarget = pCaller->GetEntityName();
}
m_target = iszNewTarget;
LoadFile();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::Activate()
{
BaseClass::Activate();
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
if (m_iszMapname == NULL_STRING || STRING(m_iszMapname)[0] == '\0')
m_iszMapname = gpGlobals->mapname;
Q_snprintf(m_iszFile, sizeof(m_iszFile), "maps/%s_externaldata.txt", STRING(m_iszMapname));
DevMsg("LOGIC_EXTERNALDATA: %s\n", m_iszFile);
// This handles !self, etc. even though the end result could just be assigning to itself.
// Also calls LoadFile() for initial load.
SetBlock(m_target);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputWriteKeyValue( inputdata_t &inputdata )
{
const char *szValue = inputdata.value.String();
char key[256];
char value[256];
// Separate key from value
char *delimiter = Q_strstr(szValue, " ");
if (delimiter)
{
Q_strncpy(key, szValue, MIN((delimiter - szValue) + 1, sizeof(key)));
Q_strncpy(value, delimiter + 1, sizeof(value));
}
else
{
// Assume the value is just supposed to be null
Q_strncpy(key, szValue, sizeof(key));
}
if (m_bReloadBeforeEachAction)
LoadFile();
m_pBlock->SetString(key, value);
if (m_bSaveEachChange)
SaveFile();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputRemoveKeyValue( inputdata_t &inputdata )
{
if (m_bReloadBeforeEachAction)
LoadFile();
KeyValues *pKV = m_pBlock->FindKey(inputdata.value.String());
if (pKV)
{
m_pBlock->RemoveSubKey(pKV);
if (m_bSaveEachChange)
SaveFile();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputReadKey( inputdata_t &inputdata )
{
if (m_bReloadBeforeEachAction)
LoadFile();
m_OutValue.Set(AllocPooledString(m_pBlock->GetString(inputdata.value.String())), inputdata.pActivator, this);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputSetBlock( inputdata_t &inputdata )
{
SetBlock(inputdata.value.StringID(), inputdata.pActivator, inputdata.pCaller);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputSave( inputdata_t &inputdata )
{
SaveFile();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicExternalData::InputReload( inputdata_t &inputdata )
{
LoadFile();
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
{
if (m_bReloadBeforeEachAction)
LoadFile();
HSCRIPT hScript = NULL;
if (m_pRoot)
{
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
CScriptKeyValues *pKV = new CScriptKeyValues( m_pRoot );
hScript = g_pScriptVM->RegisterInstance( pKV );
}
return hScript;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void )
{
if (m_bReloadBeforeEachAction)
LoadFile();
HSCRIPT hScript = NULL;
if (m_pBlock)
{
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
CScriptKeyValues *pKV = new CScriptKeyValues( m_pBlock );
hScript = g_pScriptVM->RegisterInstance( pKV );
}
return hScript;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CLogicExternalData::ScriptSetKeyValues( HSCRIPT hKV )
{
if (m_pRoot)
{
m_pRoot->deleteThis();
m_pRoot = NULL;
}
CScriptKeyValues *pKV = HScriptToClass<CScriptKeyValues>( hKV );
if (pKV)
{
m_pRoot = pKV->m_pKeyValues;
}
}
void CLogicExternalData::ScriptSetKeyValueBlock( HSCRIPT hKV )
{
if (m_pBlock)
{
m_pBlock->deleteThis();
m_pBlock = NULL;
}
CScriptKeyValues *pKV = HScriptToClass<CScriptKeyValues>( hKV );
if (pKV)
{
m_pBlock = pKV->m_pKeyValues;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CLogicExternalData::ScriptSetBlock( const char *szNewBlock, HSCRIPT hActivator, HSCRIPT hCaller )
{
CBaseEntity *pActivator = ToEnt( hActivator );
CBaseEntity *pCaller = ToEnt( hCaller );
string_t iszNewTarget = AllocPooledString(szNewBlock);
if (STRING(iszNewTarget)[0] == '!')
{
if (FStrEq(STRING(iszNewTarget), "!self"))
iszNewTarget = GetEntityName();
else if (pActivator && FStrEq(STRING(iszNewTarget), "!activator"))
iszNewTarget = pActivator->GetEntityName();
else if (pCaller && FStrEq(STRING(iszNewTarget), "!caller"))
iszNewTarget = pCaller->GetEntityName();
}
m_target = iszNewTarget;
LoadFile();
}
#endif