//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) { m_hPhysicsAttacker = pPhysGunUser; m_flLastPhysicsInfluenceTime = gpGlobals->curtime; m_flTimeGrabbed = FLT_MAX; m_bHeldByPhysgun = false; if( m_iMineState == MINE_STATE_ARMED ) { // Put the mine back to searching. Wake( false ); return; } if( Reason == DROPPED_BY_CANNON ) { // Set to lock down to ground again. m_bPlacedByPlayer = true; OpenHooks( true ); SetMineState( MINE_STATE_DEPLOY ); } else if ( Reason == LAUNCHED_BY_CANNON ) { SetMineState( MINE_STATE_LAUNCHED ); } }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::Spawn() { Precache(); Wake( false ); SetModel("models/props_combine/combine_mine01.mdl"); SetSolid( SOLID_VPHYSICS ); m_hSprite.Set( NULL ); m_takedamage = DAMAGE_EVENTS_ONLY; // Find my feet! m_iHookN = LookupPoseParameter( "blendnorth" ); m_iHookE = LookupPoseParameter( "blendeast" ); m_iHookS = LookupPoseParameter( "blendsouth" ); m_iAllHooks = LookupPoseParameter( "blendstates" ); m_flHookPositions = 0; SetHealth( 100 ); m_bBounce = true; SetSequence( SelectWeightedSequence( ACT_IDLE ) ); OpenHooks( true ); m_bHeldByPhysgun = false; m_iFlipAttempts = 0; if( !GetParent() ) { // Create vphysics now if I'm not being carried. CreateVPhysics(); } m_flTimeGrabbed = FLT_MAX; if( m_bDisarmed ) { SetMineState( MINE_STATE_DORMANT ); } else { SetMineState( MINE_STATE_DEPLOY ); } }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::InputDisarm( inputdata_t &inputdata ) { // Only affect a mine that's armed and not placed by player. if( !m_bPlacedByPlayer && m_iMineState == MINE_STATE_ARMED ) { if( m_pConstraint ) { physenv->DestroyConstraint( m_pConstraint ); m_pConstraint = NULL; } m_bDisarmed = true; OpenHooks(false); SetMineState(MINE_STATE_DORMANT); } }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::SetMineState( int iState ) { m_iMineState = iState; switch( iState ) { case MINE_STATE_DORMANT: { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.1 ); UpdateLight( false, 0, 0, 0, 0 ); SetThink( NULL ); } break; case MINE_STATE_CAPTIVE: { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.2 ); // Unhook unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); OpenHooks(); physenv->DestroyConstraint( m_pConstraint ); m_pConstraint = NULL; UpdateLight( true, 0, 0, 255, 190 ); SetThink( &CBounceBomb::CaptiveThink ); SetNextThink( gpGlobals->curtime + 0.1f ); SetTouch( NULL ); } break; case MINE_STATE_DEPLOY: OpenHooks( true ); UpdateLight( true, 0, 0, 255, 190 ); SetThink( &CBounceBomb::SettleThink ); SetTouch( NULL ); SetNextThink( gpGlobals->curtime + 0.1f ); break; case MINE_STATE_ARMED: UpdateLight( false, 0, 0, 0, 0 ); SetThink( &CBounceBomb::SearchThink ); SetNextThink( gpGlobals->curtime + 0.1f ); break; case MINE_STATE_TRIGGERED: { OpenHooks(); if( m_pConstraint ) { physenv->DestroyConstraint( m_pConstraint ); m_pConstraint = NULL; } // Scare NPC's CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 300, 1.0f, this ); CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.2 ); SetTouch( &CBounceBomb::ExplodeTouch ); unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); Vector vecNudge; vecNudge.x = random->RandomFloat( -1, 1 ); vecNudge.y = random->RandomFloat( -1, 1 ); vecNudge.z = 1.5; vecNudge *= 350; VPhysicsGetObject()->Wake(); VPhysicsGetObject()->ApplyForceCenter( vecNudge ); float x, y; x = 10 + random->RandomFloat( 0, 20 ); y = 10 + random->RandomFloat( 0, 20 ); VPhysicsGetObject()->ApplyTorqueCenter( AngularImpulse( x, y, 0 ) ); // Since we just nudged the mine, ignore collisions with the world until // the mine is in the air. We only want to explode if the player tries to // run over the mine before it jumps up. m_flIgnoreWorldTime = gpGlobals->curtime + 1.0; UpdateLight( true, 255, 0, 0, 190 ); // use the correct bounce behavior if (m_iModification == MINE_MODIFICATION_CAVERN) { SetThink ( &CBounceBomb::CavernBounceThink ); SetNextThink( gpGlobals->curtime + 0.15 ); } else { SetThink( &CBounceBomb::BounceThink ); SetNextThink( gpGlobals->curtime + 0.5 ); } } break; case MINE_STATE_LAUNCHED: { UpdateLight( true, 255, 0, 0, 190 ); SetThink( NULL ); SetNextThink( gpGlobals->curtime + 0.5 ); SetTouch( &CBounceBomb::ExplodeTouch ); unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); } break; default: DevMsg("**Unknown Mine State: %d\n", iState ); break; } }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::Spawn() { Precache(); Wake( false ); SetModel("models/props_combine/combine_mine01.mdl"); SetSolid( SOLID_VPHYSICS ); m_hSprite.Set( NULL ); m_takedamage = DAMAGE_EVENTS_ONLY; // Find my feet! m_iHookN = LookupPoseParameter( "blendnorth" ); m_iHookE = LookupPoseParameter( "blendeast" ); m_iHookS = LookupPoseParameter( "blendsouth" ); m_iAllHooks = LookupPoseParameter( "blendstates" ); m_flHookPositions = 0; SetHealth( 100 ); m_bBounce = true; SetSequence( SelectWeightedSequence( ACT_IDLE ) ); OpenHooks( true ); m_bHeldByPhysgun = false; m_iFlipAttempts = 0; if( !GetParent() ) { // Create vphysics now if I'm not being carried. CreateVPhysics(); } m_flTimeGrabbed = FLT_MAX; if( m_bDisarmed ) { SetMineState( MINE_STATE_DORMANT ); } else { SetMineState( MINE_STATE_DEPLOY ); } // default to a different skin for cavern turrets (unless explicitly overridden) if ( m_iModification == MINE_MODIFICATION_CAVERN ) { // look for this value in the first datamap // loop through the data description list, restoring each data desc block datamap_t *dmap = GetDataDescMap(); bool bFoundSkin = false; // search through all the readable fields in the data description, looking for a match for ( int i = 0; i < dmap->dataNumFields; ++i ) { if ( dmap->dataDesc[i].flags & (FTYPEDESC_OUTPUT | FTYPEDESC_KEY) ) { if ( !Q_stricmp(dmap->dataDesc[i].externalName, "Skin") ) { bFoundSkin = true; break; } } } if (!bFoundSkin) { // select a random skin for the mine. Actually, we'll cycle through the available skins // using a static variable to provide better distribution. The static isn't saved but // really it's only cosmetic. static unsigned int nextSkin = MINE_CITIZEN_SKIN_MIN; m_nSkin = nextSkin; // increment the skin for next time nextSkin = (nextSkin >= MINE_CITIZEN_SKIN_MAX) ? MINE_CITIZEN_SKIN_MIN : nextSkin + 1; } // pretend like the player set me down. m_bPlacedByPlayer = true; } }