CBreakable: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Moved KIOs and up and put them next to each other.)
mNo edit summary
 
(2 intermediate revisions by the same user not shown)
Line 2: Line 2:
{{Linked entities|func_breakable}}
{{Linked entities|func_breakable}}


==Keyvalues / Inputs / Outputs==
== Keyvalues ==
 
=== KeyValue method ===
{{note|Those defined in [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/func_break.cpp#L193 CBreakable::KeyValue] function that may have custom behavior set instead of just setting a single field, {{cmd|ent_dump}} won't show these}}
{{note|Descriptions based on {{src13mp|4}}}}
{{KV|material|intn=0|int|Sets m_Material to values 0 up 3 (0:glass, 1:metal, 2:flesh, 3:wood), if value outside this range is used it will be set to 0}}
{{KV|deadmodel|intn=0}}
{{KV|shards|intn=0}}
{{KV|lip|intn=0||Does nothing which also means that if a subclass were to have a keyfield of the same name it would be end here instead of setting its linked field.}}
{{KV|gibmodel|intn=0|string|Sets m_iszGibModel}}
{{KV|spawnobject|intn=0|int|Takes index to array of strings pSpawnObjects and sets m_iszSpawnObject to the chosen element}}
{{KV|propdata|intn=0|int|Takes index to array of strings pFGDPropData and sets m_iszPropData to the chosen element. Gives <code>Warning("func_breakable with invalid propdata %d.\n", pdata );</code> if value out of range given}}
{{KV|<anything else>|intn=0|any|Use [[CBaseEntity#KeyValue method]]}}
 
=== Keyfields ===
=== Keyfields ===
{{DEFINE_KEYFIELD|m_ExplosionMagnitude|FIELD_INTEGER|explodemagnitude}}
{{DEFINE_KEYFIELD|m_ExplosionMagnitude|FIELD_INTEGER|explodemagnitude}}
Line 14: Line 27:
{{DEFINE_KEYFIELD|m_breakableType|FIELD_INTEGER|BreakableType}}
{{DEFINE_KEYFIELD|m_breakableType|FIELD_INTEGER|BreakableType}}


=== Keyvalues ===
== Inputs ==
{{note|Those defined in [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/func_break.cpp#L193 CBreakable::KeyValue] function that may have custom behavior set instead of just setting a single field, {{cmd|ent_dump}} won't show these}}
=== Input keys ===
{{note|Descriptions based on {{src13mp|4}}}}
{{KV|material|intn=0|int|Sets m_Material to values 0 up 3 (0:glass, 1:metal, 2:flesh, 3:wood), if value outside this range is used it will be set to 0}}
{{KV|deadmodel|intn=0||Does nothing}}
{{KV|shards|intn=0||Does nothing}}
{{KV|lip|intn=0||Does nothing}}
{{KV|gibmodel|intn=0|string|Sets m_iszGibModel}}
{{KV|spawnobject|intn=0|int|Takes index to array of strings pSpawnObjects and sets m_iszSpawnObject to the chosen element}}
{{KV|propdata|intn=0|int|Takes index to array of strings pFGDPropData and sets m_iszPropData to the chosen element. Gives <code>Warning("func_breakable with invalid propdata %d.\n", pdata );</code> if value out of range given}}
 
=== Inputs ===
{{Input field note}}
{{Input field note}}
{{DEFINE_INPUT|m_impactEnergyScale|FIELD_FLOAT|physdamagescale}}
{{DEFINE_INPUT|m_impactEnergyScale|FIELD_FLOAT|physdamagescale}}
Line 36: Line 39:
{{DEFINE_INPUTFUNC|FIELD_FLOAT|SetMass|InputSetMass}}
{{DEFINE_INPUTFUNC|FIELD_FLOAT|SetMass|InputSetMass}}


=== Outputs ===
== Outputs ==
{{O|m_OnBreak|OnBreak}} <!-- DEFINE_OUTPUT -->
{{DEFINE_OUTPUT|m_OnBreak|OnBreak|COutputEvent}}
{{O|m_OnHealthChanged|OnHealthChanged}}
{{DEFINE_OUTPUT|m_OnHealthChanged|OnHealthChanged|COutputFloat}}
 
== Fields ==


== Other fields ==
=== Keyless fields ===
{{DEFINE_FIELD|m_Material|FIELD_INTEGER}}
{{DEFINE_FIELD|m_Material|FIELD_INTEGER}}
{{DEFINE_FIELD|m_hBreaker|FIELD_EHANDLE}}
{{DEFINE_FIELD|m_hBreaker|FIELD_EHANDLE}}

Latest revision as of 12:37, 13 April 2025

C++ Class hierarchy
CBreakable
CBaseEntity
C++ func_break.cpp

Entities linked to this class

Keyvalues

KeyValue method

Note.pngNote:Those defined in CBreakable::KeyValue function that may have custom behavior set instead of just setting a single field, ent_dump won't show these
Note.pngNote:Descriptions based on Source 2013 Multiplayer Source 2013 Multiplayer
material <integer>
Sets m_Material to values 0 up 3 (0:glass, 1:metal, 2:flesh, 3:wood), if value outside this range is used it will be set to 0
deadmodel
shards
lip
Does nothing which also means that if a subclass were to have a keyfield of the same name it would be end here instead of setting its linked field.
gibmodel <string>
Sets m_iszGibModel
spawnobject <integer>
Takes index to array of strings pSpawnObjects and sets m_iszSpawnObject to the chosen element
propdata <integer>
Takes index to array of strings pFGDPropData and sets m_iszPropData to the chosen element. Gives Warning("func_breakable with invalid propdata %d.\n", pdata ); if value out of range given
<anything else> <any>
Use CBaseEntity#KeyValue method

Keyfields

m_ExplosionMagnitude <FIELD_INTEGER> (explodemagnitude)

m_flPressureDelay <FIELD_FLOAT> (PressureDelay)

m_iMinHealthDmg <FIELD_INTEGER> (minhealthdmg)

m_Explosion <FIELD_INTEGER> (explosion)

m_GibDir <FIELD_VECTOR> (gibdir)

m_PerformanceMode <FIELD_INTEGER> (PerformanceMode)


Left 4 Dead seriesLeft 4 Dead series Left 4 Dead series

m_breakableType <FIELD_INTEGER> (BreakableType)


Inputs

Input keys

Note.pngNote:Usable as both keyvalue or input. ent_fire doesn't autocomplete these

m_impactEnergyScale <FIELD_FLOAT> (physdamagescale)


Input functions

Break <FIELD_VOID> linked function: InputBreak

description todo

SetHealth <FIELD_INTEGER> linked function: InputSetHealth

description todo

AddHealth <FIELD_INTEGER> linked function: InputAddHealth

description todo

RemoveHealth <FIELD_INTEGER> linked function: InputRemoveHealth

description todo

SetMass <FIELD_FLOAT> linked function: InputSetMass

description todo

Outputs

m_OnBreak <COutputEvent> (OnBreak)

m_OnHealthChanged <COutputFloat> (OnHealthChanged)


Other fields

Keyless fields

m_Material <FIELD_INTEGER>

m_hBreaker <FIELD_EHANDLE>

m_angle <FIELD_FLOAT>

m_iszGibModel <FIELD_STRING>

m_iszSpawnObject <FIELD_STRING>

m_bTookPhysicsDamage <FIELD_BOOLEAN>

m_iszPropData <FIELD_STRING>

m_flDmgModBullet <FIELD_FLOAT>

m_flDmgModClub <FIELD_FLOAT>

m_flDmgModExplosive <FIELD_FLOAT>

m_iszPhysicsDamageTableName <FIELD_STRING>

m_iszBreakableModel <FIELD_STRING>

m_iBreakableSkin <FIELD_INTEGER>

m_iBreakableCount <FIELD_INTEGER>

m_iMaxBreakableSize <FIELD_INTEGER>

m_iszBasePropData <FIELD_STRING>

m_iInteractions <FIELD_INTEGER>

m_explodeRadius <FIELD_FLOAT>

m_iszModelName <FIELD_STRING>

m_hPhysicsAttacker <FIELD_EHANDLE>

m_flLastPhysicsInfluenceTime <FIELD_TIME>


Touch think function

BreakTouch <FIELD_VOID>

Has checks for 'Break on Touch', 'Break on Pressure' flags

Think function

Die <FIELD_VOID>

Used as think function for delaying breaking of breakable after PressureDelay seconds after it was stood on

C++ definitions from Source 2013 Multiplayer Source 2013 Multiplayer [edit]

Serverside

func_break.h

#define	NUM_SHARDS 6 // this many shards spawned when breakable objects break;

// Spawnflags for func breakable
#define SF_BREAK_TRIGGER_ONLY				0x0001	// may only be broken by trigger
#define	SF_BREAK_TOUCH						0x0002	// can be 'crashed through' by running player (plate glass)
#define SF_BREAK_PRESSURE					0x0004	// can be broken by a player standing on it
#define SF_BREAK_PHYSICS_BREAK_IMMEDIATELY	0x0200	// the first physics collision this breakable has will immediately break it
#define SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE	0x0400	// this breakable doesn't take damage from physics collisions
#define SF_BREAK_NO_BULLET_PENETRATION		0x0800  // don't allow bullets to penetrate

// Spawnflags for func_pushable (it's also func_breakable, so don't collide with those flags)
#define SF_PUSH_BREAKABLE					0x0080
#define SF_PUSH_NO_USE						0x0100	// player cannot +use pickup this ent

class CBreakable : public CBaseEntity, public IBreakableWithPropData, public CDefaultPlayerPickupVPhysics
{
public:
	DECLARE_CLASS( CBreakable, CBaseEntity );

	// basic functions
	virtual void Spawn( void );
	void ParsePropData( void );
	bool CreateVPhysics( void );
	virtual void Precache( void );
	virtual bool KeyValue( const char *szKeyName, const char *szValue );
	virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent );

	void BreakTouch( CBaseEntity *pOther );
	void DamageSound( void );
	void Break( CBaseEntity *pBreaker );

	// Input handlers
	void InputAddHealth( inputdata_t &inputdata );
	void InputBreak( inputdata_t &inputdata );
	void InputRemoveHealth( inputdata_t &inputdata );
	void InputSetHealth( inputdata_t &inputdata );
	void InputSetMass( inputdata_t &inputdata );


	// breakables use an overridden takedamage
	virtual int OnTakeDamage( const CTakeDamageInfo &info );

	// To spark when hit
	void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );

	bool IsBreakable( void );
	bool SparkWhenHit( void );

	char const		*DamageDecal( int bitsDamageType, int gameMaterial );

	virtual void	Die( void );
	void			ResetOnGroundFlags(void);

	inline bool		Explodable( void ) { return GetExplosiveRadius() > 0; }

	Materials		GetMaterialType( void ) { return m_Material; }
	static void MaterialSoundRandom( int entindex, Materials soundMaterial, float volume );
	static const char *MaterialSound( Materials precacheMaterial );

	static const char *pSpawnObjects[];

	int DrawDebugTextOverlays(void);

	DECLARE_DATADESC();

public:
// IBreakableWithPropData
	void			SetDmgModBullet( float flDmgMod ) { m_flDmgModBullet = flDmgMod; }
	void			SetDmgModClub( float flDmgMod ) { m_flDmgModClub = flDmgMod; }
	void			SetDmgModExplosive( float flDmgMod ) { m_flDmgModExplosive = flDmgMod; }
	float			GetDmgModBullet( void ) { return m_flDmgModBullet; }
	float			GetDmgModClub( void ) { return m_flDmgModClub; }
	float			GetDmgModExplosive( void ) { return m_flDmgModExplosive; }
	void			SetExplosiveRadius( float flRadius ) { m_explodeRadius = flRadius; }
	void			SetExplosiveDamage( float flDamage ) { m_ExplosionMagnitude = flDamage; }
	float			GetExplosiveRadius( void ) { return m_explodeRadius; }
	float			GetExplosiveDamage( void ) { return m_ExplosionMagnitude; }
	void			SetPhysicsDamageTable( string_t iszTableName ) { m_iszPhysicsDamageTableName = iszTableName; }
	string_t		GetPhysicsDamageTable( void ) { return m_iszPhysicsDamageTableName; }
	void			SetBreakableModel( string_t iszModel ) { m_iszBreakableModel = iszModel; }
	string_t 		GetBreakableModel( void ) { return m_iszBreakableModel; }
	void			SetBreakableSkin( int iSkin ) { m_iBreakableSkin = iSkin; }
	int				GetBreakableSkin( void ) { return m_iBreakableSkin; }
	void			SetBreakableCount( int iCount ) { m_iBreakableCount = iCount; }
	int				GetBreakableCount( void ) { return m_iBreakableCount; }
	void			SetMaxBreakableSize( int iSize ) { m_iMaxBreakableSize = iSize; }
	int				GetMaxBreakableSize( void ) { return m_iMaxBreakableSize; }
	void			SetPropDataBlocksLOS( bool bBlocksLOS ) { SetBlocksLOS( bBlocksLOS ); }
	void			SetPropDataIsAIWalkable( bool bBlocksLOS ) { SetAIWalkable( bBlocksLOS ); }
	void			SetBasePropData( string_t iszBase ) { m_iszBasePropData = iszBase; }
	string_t		GetBasePropData( void ) { return m_iszBasePropData; }
	void			SetInteraction( propdata_interactions_t Interaction ) { m_iInteractions |= (1 << Interaction); }
	bool			HasInteraction( propdata_interactions_t Interaction ) { return ( m_iInteractions & (1 << Interaction) ) != 0; }
	void			SetPhysicsMode(int iMode){}
	int				GetPhysicsMode() { return PHYSICS_MULTIPLAYER_SOLID; }
	void			SetMultiplayerBreakMode( mp_break_t mode ) {}
	mp_break_t		GetMultiplayerBreakMode( void ) const { return MULTIPLAYER_BREAK_DEFAULT; }

protected:
	float		m_angle;
	Materials	m_Material;
	EHANDLE m_hBreaker;			// The entity that broke us. Held as a data member because sometimes breaking is delayed.

private:

	Explosions	m_Explosion;
	QAngle		m_GibDir;
	string_t 	m_iszGibModel;
	string_t 	m_iszSpawnObject;
	int			m_ExplosionMagnitude;
	float		m_flPressureDelay;		// Delay before breaking when destoyed by pressure
	int			m_iMinHealthDmg;		// minimum damage attacker must have to cause damage
	bool		m_bTookPhysicsDamage;

	string_t	m_iszPropData;
	string_t	m_iszModelName;

protected:

	bool		UpdateHealth( int iNewHealth, CBaseEntity *pActivator );

	float		m_impactEnergyScale;

	COutputEvent m_OnBreak;
	COutputFloat m_OnHealthChanged;

	// Prop data storage
	float			m_flDmgModBullet;
	float			m_flDmgModClub;
	float			m_flDmgModExplosive;
	string_t		m_iszPhysicsDamageTableName;
	string_t		m_iszBreakableModel;
	int				m_iBreakableSkin;
	int				m_iBreakableCount;
	int				m_iMaxBreakableSize;
	string_t		m_iszBasePropData;	
	int				m_iInteractions;
	PerformanceMode_t m_PerformanceMode;

	float			m_explodeRadius;

public:
	// IPlayerPickupVPhysics
	virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
	virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason );
	virtual	CBasePlayer *HasPhysicsAttacker( float dt );
private:
	CHandle<CBasePlayer>	m_hPhysicsAttacker;
	float					m_flLastPhysicsInfluenceTime;
};

func_break.cpp

BEGIN_DATADESC( CBreakable )

	DEFINE_FIELD( m_Material, FIELD_INTEGER ),
	DEFINE_KEYFIELD( m_Explosion, FIELD_INTEGER, "explosion" ),
	DEFINE_KEYFIELD( m_GibDir, FIELD_VECTOR, "gibdir" ),
	DEFINE_FIELD( m_hBreaker, FIELD_EHANDLE ),

	// Don't need to save/restore these because we precache after restore
	//DEFINE_FIELD( m_idShard, FIELD_INTEGER ),
	DEFINE_FIELD( m_angle, FIELD_FLOAT ),
	DEFINE_FIELD( m_iszGibModel, FIELD_STRING ),
	DEFINE_FIELD( m_iszSpawnObject, FIELD_STRING ),
	DEFINE_KEYFIELD( m_ExplosionMagnitude, FIELD_INTEGER, "explodemagnitude" ),
	DEFINE_KEYFIELD( m_flPressureDelay, FIELD_FLOAT, "PressureDelay" ),
	DEFINE_KEYFIELD( m_iMinHealthDmg, FIELD_INTEGER, "minhealthdmg" ),
	DEFINE_FIELD( m_bTookPhysicsDamage, FIELD_BOOLEAN ),
	DEFINE_FIELD( m_iszPropData, FIELD_STRING ),
	DEFINE_INPUT( m_impactEnergyScale, FIELD_FLOAT, "physdamagescale" ),
	DEFINE_KEYFIELD( m_PerformanceMode, FIELD_INTEGER, "PerformanceMode" ),

	DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ),
	DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHealth", InputSetHealth ),
	DEFINE_INPUTFUNC( FIELD_INTEGER, "AddHealth", InputAddHealth ),
	DEFINE_INPUTFUNC( FIELD_INTEGER, "RemoveHealth", InputRemoveHealth ),
	DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMass", InputSetMass ),

	// Function Pointers
	DEFINE_ENTITYFUNC( BreakTouch ),
	DEFINE_THINKFUNC( Die ),

	// Outputs
	DEFINE_OUTPUT(m_OnBreak, "OnBreak"),
	DEFINE_OUTPUT(m_OnHealthChanged, "OnHealthChanged"),

	DEFINE_FIELD( m_flDmgModBullet, FIELD_FLOAT ),
	DEFINE_FIELD( m_flDmgModClub, FIELD_FLOAT ),
	DEFINE_FIELD( m_flDmgModExplosive, FIELD_FLOAT ),
	DEFINE_FIELD( m_iszPhysicsDamageTableName, FIELD_STRING ),
	DEFINE_FIELD( m_iszBreakableModel, FIELD_STRING ),
	DEFINE_FIELD( m_iBreakableSkin, FIELD_INTEGER ),
	DEFINE_FIELD( m_iBreakableCount, FIELD_INTEGER ),
	DEFINE_FIELD( m_iMaxBreakableSize, FIELD_INTEGER ),
	DEFINE_FIELD( m_iszBasePropData, FIELD_STRING ),
	DEFINE_FIELD( m_iInteractions, FIELD_INTEGER ),
	DEFINE_FIELD( m_explodeRadius, FIELD_FLOAT ),
	DEFINE_FIELD( m_iszModelName, FIELD_STRING ),
	
	// Physics Influence
	DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ),
	DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ),

END_DATADESC()


See Also