예제 #1
0
//-----------------------------------------------------------------------------
// Purpose: Object has been blown up. Tunnels are never fully destroyed, so they stay on the minimap.
//-----------------------------------------------------------------------------
void CObjectTunnel::Killed( void )
{
	m_bDying = true;

	RemoveAllSappers( this );

	// Do an explosion.
	CPASFilter filter( GetAbsOrigin() );
	te->Explosion( 
		filter, 
		0.0,				
		&GetAbsOrigin(),
		g_sModelIndexFireball,
		5.4,		// radius
		15,
		TE_EXPLFLAG_NODLIGHTS,
		256,
		200);

	// Become non-solid and invisible
	VPhysicsDestroyObject();
	AddSolidFlags( FSOLID_NOT_SOLID );
	m_takedamage = DAMAGE_NO;
	AddEffects( EF_NODRAW );
}
bool CHL2MP_Player::StartObserverMode(int mode)
{
	//we only want to go into observer mode if the player asked to, not on a death timeout
	if ( m_bEnterObserver == true )
	{
		VPhysicsDestroyObject();
		return BaseClass::StartObserverMode( mode );
	}
	return false;
}
예제 #3
0
void CFuncBulletShield::Spawn( void )
{
	BaseClass::Spawn();

	AddSolidFlags( FSOLID_CUSTOMRAYTEST );
	AddSolidFlags( FSOLID_CUSTOMBOXTEST );
	// SetSolid(SOLID_CUSTOM);

	VPhysicsDestroyObject();
}
C_PhysPropClientside::~C_PhysPropClientside()
{
	if ( m_pRespawnZone )
	{
		m_pRespawnZone->PropDestroyed( this );
	}

	PhysCleanupFrictionSounds( this );
	VPhysicsDestroyObject();
	s_PhysPropList.FindAndRemove( this );
}
예제 #5
0
//------------------------------------------------------------------------------
// Purpose : Brickbat grenade turns back into a brickbat weapon
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CGrenade_Brickbat::SpawnBrickbatWeapon( void )
{
	CWeaponBrickbat *pBrickbat = (CWeaponBrickbat*)CBaseEntity::CreateNoSpawn( 
		"weapon_brickbat", GetLocalOrigin(), GetLocalAngles(), NULL );
	// Spawn after we set the ammo type so the correct model is used
	if (pBrickbat)
	{
		pBrickbat->m_iCurrentAmmoType = m_nType;
		pBrickbat->Spawn();
		VPhysicsDestroyObject();
		SetThink(NULL);
		UTIL_Remove(this);
	}
}
예제 #6
0
void CGEPropDynamic::Materialize(void)
{
	//A more lightweight and optional func_rebreakable materalize function 
	CreateVPhysics();

	if (m_bRobustSpawn)
	{
		// iterate on all entities in the vicinity.
		CBaseEntity *pEntity;
		Vector max = CollisionProp()->OBBMaxs();
		for (CEntitySphereQuery sphere(GetAbsOrigin(), max.NormalizeInPlace()); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity())
		{
			if (pEntity == this || pEntity->GetSolid() == SOLID_NONE || pEntity->GetSolid() == SOLID_BSP || pEntity->GetSolidFlags() & FSOLID_NOT_SOLID || pEntity->GetMoveType() & MOVETYPE_NONE)
				continue;

			// Ignore props that can't move
			if (pEntity->VPhysicsGetObject() && !pEntity->VPhysicsGetObject()->IsMoveable())
				continue;

			// Prevent respawn if we are blocked by anything and try again in 1 second
			if (Intersects(pEntity))
			{
				SetSolid(SOLID_NONE);
				AddSolidFlags(FSOLID_NOT_SOLID);
				VPhysicsDestroyObject();
				SetNextThink(gpGlobals->curtime + 1.0f);
				return;
			}
		}
	}

	m_iHealth = m_iHealthOverride;

	if (m_iHealth > 0)
		m_takedamage = DAMAGE_YES;

	RemoveEffects(EF_NODRAW);
	RemoveSolidFlags(FSOLID_NOT_SOLID);

	m_bUsingBrokenSkin = false;

	if (m_bUseRandomSkins)
		PickNewSkin();
	else
		m_nSkin = m_iStartingSkin;

	SetRenderColor(m_col32basecolor.r, m_col32basecolor.g, m_col32basecolor.b);

	m_Respawn.FireOutput(this, this);
}
예제 #7
0
void C_ASW_Door::OnDataChanged( DataUpdateType_t type )
{
	BaseClass::OnDataChanged( type );

	if ( !IsAlive() && VPhysicsGetObject())
	{
		VPhysicsDestroyObject();
	}

	if ( m_flOldSealTime != m_flCurrentSealTime )
	{
		m_fLastWeldedTime = gpGlobals->curtime;
		m_bUnwelding = ( m_flOldSealTime > m_flCurrentSealTime );
		m_flOldSealTime = m_flCurrentSealTime;
	}
}
예제 #8
0
//=========================================================
// Spawn
//=========================================================
void CGenericNPC::Spawn()
{
	Precache();

	SetModel( STRING( GetModelName() ) );

/*
	if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) )
		UTIL_SetSize(this, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
	else
		UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX);
*/

	if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) || FStrEq( STRING( GetModelName() ), "models/holo.mdl" ) )
		UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX);
	else
		UTIL_SetSize(this, NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN));

	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_NOT_STANDABLE );
	SetMoveType( MOVETYPE_STEP );
	m_bloodColor		= BLOOD_COLOR_RED;
	m_iHealth			= 8;
	m_flFieldOfView		= 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result )
	m_NPCState			= NPC_STATE_NONE;
	
	CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS );

	NPCInit();
	if ( !HasSpawnFlags(SF_GENERICNPC_NOTSOLID) )
	{
		trace_t tr;
		UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_SOLID, &tr );
		if ( tr.startsolid )
		{
			Msg("Placed npc_generic in solid!!! (%s)\n", STRING(GetModelName()) );
			m_spawnflags |= SF_GENERICNPC_NOTSOLID;
		}
	}

	if ( HasSpawnFlags(SF_GENERICNPC_NOTSOLID) )
	{
		AddSolidFlags( FSOLID_NOT_SOLID );
		m_takedamage = DAMAGE_NO;
		VPhysicsDestroyObject();
	}
}
예제 #9
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponBugBait::FallInit( void )
{
	// Bugbait shouldn't be physics, because it musn't roll/move away from it's spawnpoint.
	// The game will break if the player can't pick it up, so it must stay still.
	SetModel( GetWorldModel() );

	VPhysicsDestroyObject();
	SetMoveType( MOVETYPE_FLYGRAVITY );
	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_TRIGGER );

	SetPickupTouch();
	
	SetThink( &CBaseCombatWeapon::FallThink );

	SetNextThink( gpGlobals->curtime + 0.1f );
}
예제 #10
0
//====================================================================================
// FALL TO GROUND
//====================================================================================
//-----------------------------------------------------------------------------
// Purpose: Setup for the fall
//-----------------------------------------------------------------------------
void CBaseCombatWeapon::FallInit( void )
{
	SetModel( GetWorldModel() );
	VPhysicsDestroyObject();

	if ( !VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ) )
	{
		SetMoveType( MOVETYPE_FLYGRAVITY );
		SetSolid( SOLID_BBOX );
		AddSolidFlags( FSOLID_TRIGGER );
	}
	else
	{
#if !defined( CLIENT_DLL )
		// Constrained start?
		if ( HasSpawnFlags( SF_WEAPON_START_CONSTRAINED ) )
		{
			//Constrain the weapon in place
			IPhysicsObject *pReferenceObject, *pAttachedObject;
			
			pReferenceObject = g_PhysWorldObject;
			pAttachedObject = VPhysicsGetObject();

			if ( pReferenceObject && pAttachedObject )
			{
				constraint_fixedparams_t fixed;
				fixed.Defaults();
				fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject );
				
				fixed.constraint.forceLimit	= lbs2kg( 10000 );
				fixed.constraint.torqueLimit = lbs2kg( 10000 );

				m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed );

				m_pConstraint->SetGameData( (void *) this );
			}
		}
#endif //CLIENT_DLL
	}	

	SetPickupTouch();
	
	SetThink( &CBaseCombatWeapon::FallThink );

	SetNextThink( gpGlobals->curtime + 0.1f );
}
예제 #11
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CGrenadeHopwire::CombatThink( void )
{
	// Stop the grenade from moving
	AddEFlags( EF_NODRAW );
	AddFlag( FSOLID_NOT_SOLID );
	VPhysicsDestroyObject();
	SetAbsVelocity( vec3_origin );
	SetMoveType( MOVETYPE_NONE );

	// Do special behaviors if there are any striders in the area
	KillStriders();

	// FIXME: Replace
	//EmitSound("NPC_Strider.Shoot");
	//EmitSound("d3_citadel.weapon_zapper_beam_loop2");

	// Quick screen flash
	CBasePlayer *pPlayer = ToBasePlayer( GetThrower() );
	color32 white = { 255,255,255,255 };
	UTIL_ScreenFade( pPlayer, white, 0.2f, 0.0f, FFADE_IN );

	// Create the vortex controller to pull entities towards us
	if ( hopwire_vortex.GetBool() )
	{
		m_hVortexController = CGravityVortexController::Create( GetAbsOrigin(), 512, 150, 3.0f );

		// Start our client-side effect
		EntityMessageBegin( this, true );
			WRITE_BYTE( 0 );
		MessageEnd();
		
		// Begin to stop in two seconds
		SetThink( &CGrenadeHopwire::EndThink );
		SetNextThink( gpGlobals->curtime + 2.0f );
	}
	else
	{
		// Remove us immediately
		SetThink( &CBaseEntity::SUB_Remove );
		SetNextThink( gpGlobals->curtime + 0.1f );
	}
}
예제 #12
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFPowerup::Spawn( void )
{
	BaseClass::Precache();
	BaseClass::Spawn();

	BaseClass::SetOriginalSpawnOrigin( GetAbsOrigin() );
	BaseClass::SetOriginalSpawnAngles( GetAbsAngles() );

	VPhysicsDestroyObject();
	SetMoveType( MOVETYPE_NONE );
	SetSolidFlags( FSOLID_NOT_SOLID | FSOLID_TRIGGER );

	if ( m_bDisabled )
	{
		SetDisabled( true );
	}

	m_bRespawning = false;

	ResetSequence( LookupSequence("idle") );
}
예제 #13
0
CBaseEntity* CItem::Respawn( void )
{
	SetTouch( NULL );
	AddEffects( EF_NODRAW );

	VPhysicsDestroyObject();

	SetMoveType( MOVETYPE_NONE );
	SetSolid( SOLID_BBOX );
	AddSolidFlags( FSOLID_TRIGGER );

	UTIL_SetOrigin( this, g_pGameRules->VecItemRespawnSpot( this ) );// blip to whereever you should respawn.
	SetAbsAngles( g_pGameRules->VecItemRespawnAngles( this ) );// set the angles.


	UTIL_DropToFloor( this, MASK_SOLID );


	RemoveAllDecals(); //remove any decals

	SetThink ( &CItem::Materialize );
	SetNextThink( gpGlobals->curtime + g_pGameRules->FlItemRespawnTime( this ) );
	return this;
}
예제 #14
0
void CGEPropDynamic::Event_Killed(const CTakeDamageInfo &info)
{
	// More or less just the kill event copied straight from prop_physics_respawnable, though it does not teleport as it cannot move on its own.

	IPhysicsObject *pPhysics = VPhysicsGetObject();
	if (pPhysics && !pPhysics->IsMoveable())
	{
		pPhysics->EnableMotion(true);
		VPhysicsTakeDamage(info);
	}

	Break(info.GetInflictor(), info);

	PhysCleanupFrictionSounds(this);

	VPhysicsDestroyObject();

	CBaseEntity::PhysicsRemoveTouchedList(this);
	CBaseEntity::PhysicsRemoveGroundList(this);
	DestroyAllDataObjects();

	AddEffects(EF_NODRAW);

	if (IsOnFire() || IsDissolving())
	{
		UTIL_Remove(GetEffectEntity());
	}

	SetContextThink(NULL, 0, "PROP_CLEARFLAGS");

	if (m_flRespawnTime > 0)
	{
		SetThink(&CGEPropDynamic::Materialize);
		SetNextThink(gpGlobals->curtime + m_flRespawnTime);
	}
}
void CRotatingPickup::Spawn()
{
	// CItem is designed for Vphys objects, so we need to undo a couple of things its spawn() does
	Vector OriginalLocation = GetAbsOrigin();
		BaseClass::Spawn();
	VPhysicsDestroyObject();
	SetAbsOrigin(OriginalLocation);
 
	UseClientSideAnimation();
	SetModel(PICKUP_MODEL);
 
	SetMoveType(MOVETYPE_NONE);
 
	// Grab the highest point on the model before we change the bounding box
	MdlTop = GetAbsOrigin();
	MdlTop.z += GetModelPtr()->hull_max().z;
 
	SetSolid(SOLID_NONE);
	CollisionProp()->UseTriggerBounds(true,6); // Reign in the volume added to the trigger collision box
	Vector OBBSize = Vector(CollisionProp()->OBBSize().Length() / 2); // need to use length as the model will be rotated at 45 degrees on clients
	SetSize(-OBBSize,OBBSize); // Resize the bounding box
 
	AddEffects(EF_NOSHADOW);	
}
//------------------------------------------------------------------------------
// Purpose: Break into panels
// Input  : pBreaker - 
//			vDir - 
//-----------------------------------------------------------------------------
void CBreakableSurface::Die( CBaseEntity *pBreaker, const Vector &vAttackDir )
{
	if ( m_bIsBroken )
		return;

	// Play a break sound
	PhysBreakSound( this, VPhysicsGetObject(), GetAbsOrigin() );

	m_bIsBroken = true;
	m_iHealth = 0.0f;

	if (pBreaker)
	{
		m_OnBreak.FireOutput( pBreaker, this );
	}
	else
	{
		m_OnBreak.FireOutput( this, this );
	}

	float flDir = -1;

	if ( vAttackDir.LengthSqr() > 0.001 )
	{
		float flDot = DotProduct( m_vNormal, vAttackDir );
		if (flDot < 0)
		{
			m_vLLVertex += m_vNormal;
			m_vLRVertex += m_vNormal;
			m_vULVertex += m_vNormal;
			m_vURVertex += m_vNormal;
			m_vNormal	*= -1;
			flDir		=   1;
		}
	}

	// -------------------------------------------------------
	// The surface has two sides, when we are killed pick 
	// the side that the damage came from 
	// -------------------------------------------------------
	Vector vWidth		= m_vLLVertex - m_vLRVertex;
	Vector vHeight		= m_vLLVertex - m_vULVertex;
	CrossProduct( vWidth, vHeight, m_vNormal.GetForModify() );
	VectorNormalize(m_vNormal.GetForModify());

	// ---------------------------------------------------
	//  Make sure width and height are oriented correctly
	// ---------------------------------------------------
	QAngle vAngles;
	VectorAngles(-1*m_vNormal,vAngles);
	Vector vWidthDir,vHeightDir;
	AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir);

	float flWDist = DotProduct(vWidthDir,vWidth);
	if (fabs(flWDist)<0.5)
	{
		Vector vSaveHeight	= vHeight;
		vHeight				= vWidth * flDir;
		vWidth				= vSaveHeight * flDir;
	}

	// -------------------------------------------------
	// Find which corner to use
	// -------------------------------------------------
	bool bLeft  = (DotProduct(vWidthDir,vWidth)   < 0);
	bool bLower = (DotProduct(vHeightDir,vHeight) < 0);
	if (bLeft)
	{
		m_vCorner = bLower ? m_vLLVertex : m_vULVertex;
	}
	else 
	{
		m_vCorner = bLower ? m_vLRVertex : m_vURVertex;
	}

	// -------------------------------------------------
	//  Calculate the number of panels
	// -------------------------------------------------
	float flWidth		= vWidth.Length();
	float flHeight		= vHeight.Length();
	m_nNumWide			= flWidth  / WINDOW_PANEL_SIZE;
	m_nNumHigh			= flHeight / WINDOW_PANEL_SIZE;

	// If to many panels make panel size bigger
	if (m_nNumWide > MAX_NUM_PANELS) m_nNumWide = MAX_NUM_PANELS;
	if (m_nNumHigh > MAX_NUM_PANELS) m_nNumHigh = MAX_NUM_PANELS;

	m_flPanelWidth	= flWidth  / m_nNumWide;
	m_flPanelHeight	= flHeight / m_nNumHigh;
	
	// Initialize panels
	for (int w=0;w<MAX_NUM_PANELS;w++)
	{ 
		for (int h=0;h<MAX_NUM_PANELS;h++)
		{
			SetSupport( w, h, WINDOW_PANE_HEALTHY );
		}
	}

	// Reset onground flags for any entity that may 
	// have been standing on me
	ResetOnGroundFlags();

	VPhysicsDestroyObject();
	AddSolidFlags( FSOLID_TRIGGER );
	AddSolidFlags( FSOLID_NOT_SOLID );
	SetTouch(&CBreakableSurface::SurfaceTouch);
}
예제 #17
0
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOther -
//-----------------------------------------------------------------------------
void CGrappleHook::HookTouch(CBaseEntity *pOther)
{
	if (!pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS))
		return;
	if ((pOther != m_hOwner) && (pOther->m_takedamage != DAMAGE_NO))
	{
		m_hOwner->NotifyHookDied();
		SetTouch(NULL);
		SetThink(NULL);
		UTIL_Remove(this);
	}
	else
	{
		trace_t	tr;
		tr = BaseClass::GetTouchTrace();
		// See if we struck the world
		if (pOther->GetMoveType() == MOVETYPE_NONE && !(tr.surface.flags & SURF_SKY))
		{
			EmitSound("Weapon_AR2.Reload_Push");
			// if what we hit is static architecture, can stay around for a while.
			Vector vecDir = GetAbsVelocity();
			//FIXME: We actually want to stick (with hierarchy) to what we've hit
			SetMoveType(MOVETYPE_NONE);
			Vector vForward;
			AngleVectors(GetAbsAngles(), &vForward);
			VectorNormalize(vForward);
			CEffectData data;
			data.m_vOrigin = tr.endpos;
			data.m_vNormal = vForward;
			data.m_nEntIndex = 0;
			// DispatchEffect( "Impact", data );
			// AddEffects( EF_NODRAW );
			SetTouch(NULL);
			VPhysicsDestroyObject();
			VPhysicsInitNormal(SOLID_VPHYSICS, FSOLID_NOT_STANDABLE, false);
			AddSolidFlags(FSOLID_NOT_SOLID);
			// SetMoveType( MOVETYPE_NONE );
			if (!m_hPlayer)
			{
				Assert(0);
				return;
			}
			// Set Jay's gai flag
			m_hPlayer->SetPhysicsFlag(PFLAG_VPHYSICS_MOTIONCONTROLLER, true);
			//IPhysicsObject *pPhysObject = m_hPlayer->VPhysicsGetObject();
			IPhysicsObject *pRootPhysObject = VPhysicsGetObject();
			Assert(pRootPhysObject);
			//Assert(pPhysObject);
			pRootPhysObject->EnableMotion(false);
			// Root has huge mass, tip has little
			pRootPhysObject->SetMass(VPHYSICS_MAX_MASS);
			// pPhysObject->SetMass( 100 );
			// float damping = 3;
			// pPhysObject->SetDamping( &damping, &damping );
			Vector origin = m_hPlayer->GetAbsOrigin();
			Vector rootOrigin = GetAbsOrigin();
			m_fSpringLength = (origin - rootOrigin).Length();
			m_bPlayerWasStanding = ((m_hPlayer->GetFlags() & FL_DUCKING) == 0);
			SetThink(&CGrappleHook::HookedThink);
			SetNextThink(gpGlobals->curtime + 0.1f);
		}
		else
		{
			// Put a mark unless we've hit the sky
			if ((tr.surface.flags & SURF_SKY) == false)
			{
				UTIL_ImpactTrace(&tr, DMG_BULLET);
			}
			SetTouch(NULL);
			SetThink(NULL);
			m_hOwner->NotifyHookDied();
			UTIL_Remove(this);
		}
	}
}
C_RagdollShadow::~C_RagdollShadow( void )
{
	VPhysicsDestroyObject();

	delete m_pSpring;
}
예제 #19
0
//-----------------------------------------------------------------------------
// Purpose: Breaks the breakable. m_hBreaker is the entity that caused us to break.
//-----------------------------------------------------------------------------
void CBreakable::Die( void )
{
	Vector vecVelocity;// shard velocity
	char cFlag = 0;
	int pitch;
	float fvol;
	
	pitch = 95 + random->RandomInt(0,29);

	if (pitch > 97 && pitch < 103)
	{
		pitch = 100;
	}

	// The more negative m_iHealth, the louder
	// the sound should be.

	fvol = random->RandomFloat(0.85, 1.0) + (abs(m_iHealth) / 100.0);
	if (fvol > 1.0)
	{
		fvol = 1.0;
	}

	const char *soundname = NULL;

	switch (m_Material)
	{
	default:
		break;

	case matGlass:
		soundname = "Breakable.Glass";
		cFlag = BREAK_GLASS;
		break;

	case matWood:
		soundname = "Breakable.Crate";
		cFlag = BREAK_WOOD;
		break;

	case matComputer:
		soundname = "Breakable.Computer";
		cFlag = BREAK_METAL;
		break;

	case matMetal:
		soundname = "Breakable.Metal";
		cFlag = BREAK_METAL;
		break;

	case matFlesh:
	case matWeb:
		soundname = "Breakable.Flesh";
		cFlag = BREAK_FLESH;
		break;

	case matRocks:
	case matCinderBlock:
		soundname = "Breakable.Concrete";
		cFlag = BREAK_CONCRETE;
		break;

	case matCeilingTile:
		soundname = "Breakable.Ceiling";
		break;
	}

	if ( soundname )
	{
		if ( m_hBreaker && m_hBreaker->IsPlayer() )
		{
			IGameEvent * event = gameeventmanager->CreateEvent( "break_breakable" );
			if ( event )
			{
				event->SetInt( "userid", ToBasePlayer( m_hBreaker )->GetUserID() );
				event->SetInt( "entindex", entindex() );
				event->SetInt( "material", cFlag );
				gameeventmanager->FireEvent( event );
			}
		}

		CSoundParameters params;
		if ( GetParametersForSound( soundname, params, NULL ) )
		{
			CPASAttenuationFilter filter( this );

			EmitSound_t ep;
			ep.m_nChannel = params.channel;
			ep.m_pSoundName = params.soundname;
			ep.m_flVolume = fvol;
			ep.m_SoundLevel = params.soundlevel;
			ep.m_nPitch = pitch;

			EmitSound( filter, entindex(), ep );	
		}
	}
		
	switch( m_Explosion )
	{
	case expDirected:
		vecVelocity = g_vecAttackDir * -200;
		break;

	case expUsePrecise:
		{
			AngleVectors( m_GibDir, &vecVelocity, NULL, NULL );
			vecVelocity *= 200;
		}
		break;

	case expRandom:
		vecVelocity.x = 0;
		vecVelocity.y = 0;
		vecVelocity.z = 0;
		break;

	default:
		DevMsg("**ERROR - Unspecified gib dir method in func_breakable!\n");
		break;
	}

	Vector vecSpot = WorldSpaceCenter();
	CPVSFilter filter2( vecSpot );

	int iModelIndex = 0;
	CCollisionProperty *pCollisionProp = CollisionProp();

	Vector vSize = pCollisionProp->OBBSize();
	int iCount = ( vSize[0] * vSize[1] + vSize[1] * vSize[2] + vSize[2] * vSize[0] ) / ( 3 * 12 * 12 );

	if ( iCount > func_break_max_pieces.GetInt() )
	{
		iCount = func_break_max_pieces.GetInt();
	}

	ConVarRef breakable_disable_gib_limit( "breakable_disable_gib_limit" );
	if ( !breakable_disable_gib_limit.GetBool() && iCount )
	{
		if ( m_PerformanceMode == PM_NO_GIBS )
		{
			iCount = 0;
		}
		else if ( m_PerformanceMode == PM_REDUCED_GIBS )
		{
			int iNewCount = iCount * func_break_reduction_factor.GetFloat();
			iCount = MAX( iNewCount, 1 );
		}
	}

	if ( m_iszModelName != NULL_STRING )
	{
		for ( int i = 0; i < iCount; i++ )
		{

	#ifdef HL1_DLL
			// Use the passed model instead of the propdata type
			const char *modelName = STRING( m_iszModelName );
			
			// if the map specifies a model by name
			if( strstr( modelName, ".mdl" ) != NULL )
			{
				iModelIndex = modelinfo->GetModelIndex( modelName );
			}
			else	// do the hl2 / normal way
	#endif

			iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel(  STRING( m_iszModelName ) ) );

			// All objects except the first one in this run are marked as slaves...
			int slaveFlag = 0;
			if ( i != 0 )
			{
				slaveFlag = BREAK_SLAVE;
			}

			te->BreakModel( filter2, 0.0, 
				vecSpot, pCollisionProp->GetCollisionAngles(), vSize, 
				vecVelocity, iModelIndex, 100, 1, 2.5, cFlag | slaveFlag );
		}
	}

	ResetOnGroundFlags();

	// Don't fire something that could fire myself
	SetName( NULL_STRING );

	AddSolidFlags( FSOLID_NOT_SOLID );
	
	// Fire targets on break
	m_OnBreak.FireOutput( m_hBreaker, this );

	VPhysicsDestroyObject();
	SetThink( &CBreakable::SUB_Remove );
	SetNextThink( gpGlobals->curtime + 0.1f );
	if ( m_iszSpawnObject != NULL_STRING )
	{
		CBaseEntity::Create( STRING(m_iszSpawnObject), vecSpot, pCollisionProp->GetCollisionAngles(), this );
	}

	if ( Explodable() )
	{
		ExplosionCreate( vecSpot, pCollisionProp->GetCollisionAngles(), this, GetExplosiveDamage(), GetExplosiveRadius(), true );
	}
}
예제 #20
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_Gib::~C_Gib( void )
{
	VPhysicsDestroyObject();
}