void CPendulum :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if( IsLockedByMaster( pActivator ) || m_distance == 0 ) return; if( pev->speed ) { // pendulum is moving, stop it and auto-return if necessary if( FBitSet( pev->spawnflags, SF_PENDULUM_AUTO_RETURN )) { float delta = CBaseToggle::AxisDelta( pev->spawnflags, GetLocalAngles(), m_start ); SetLocalAvelocity( m_maxSpeed * pev->movedir ); SetNextThink( delta / m_maxSpeed ); SetThink( Stop ); } else { pev->speed = 0; // dead stop SetThink( NULL ); SetLocalAvelocity( g_vecZero ); m_iState = STATE_OFF; } } else { SetNextThink( 0.1f ); // start the pendulum moving SetThink( Swing ); m_time = gpGlobals->time; // save time to calculate dt m_dampSpeed = m_maxSpeed; } }
void CMomentaryRotButton :: ReturnMoveDone( void ) { float value = GetPos( GetLocalAngles() ); SetUse( &CMomentaryRotButton::ButtonUse ); if( value <= 0 ) { // Got back to the start, stop spinning. SetLocalAvelocity( g_vecZero ); SetLocalAngles( m_start ); m_iState = STATE_OFF; UpdateTarget( 0 ); SetMoveDoneTime( -1 ); SetMoveDone( NULL ); SetNextThink( -1 ); SetThink( NULL ); } else { m_iState = STATE_TURN_OFF; SetLocalAvelocity( -m_returnSpeed * pev->movedir ); SetMoveDoneTime( 0.1f ); SetThink( &CMomentaryRotButton::UpdateThink ); SetNextThink( 0.01f ); } }
void CMomentaryRotButton :: UpdateSelf( float value, bool bPlaySound ) { // set our move clock to 0.1 seconds in the future so we stop spinning unless we are // used again before then. SetMoveDoneTime( 0.1 ); if( m_direction > 0 && value >= 1.0 ) { // if we hit the end, zero our avelocity and snap to the end angles. SetLocalAvelocity( g_vecZero ); SetLocalAngles( m_end ); m_iState = STATE_ON; return; } else if( m_direction < 0 && value <= 0 ) { // if we returned to the start, zero our avelocity and snap to the start angles. SetLocalAvelocity( g_vecZero ); SetLocalAngles( m_start ); m_iState = STATE_OFF; return; } // i'm "in use" player turn me :-) m_iState = STATE_IN_USE; if( bPlaySound ) PlaySound(); SetLocalAvelocity(( m_direction * pev->speed ) * pev->movedir ); SetMoveDone( &CMomentaryRotButton::UseMoveDone ); }
void CMomentaryRotButton :: SetPosition( float value ) { pev->ideal_yaw = bound( 0.0f, value, 1 ); float flCurPos = GetPos( GetLocalAngles( )); if( flCurPos < pev->ideal_yaw ) { // moving forward (from start to end). SetLocalAvelocity( pev->speed * pev->movedir ); m_direction = 1; } else if( flCurPos > pev->ideal_yaw ) { // moving backward (from end to start). SetLocalAvelocity( -pev->speed * pev->movedir ); m_direction = -1; } else { // we're there already; nothing to do. SetLocalAvelocity( g_vecZero ); return; } // g-cont. to avoid moving by user in back direction if( FBitSet( pev->spawnflags, SF_MOMENTARY_ROT_BUTTON_AUTO_RETURN ) && m_returnSpeed > 0 ) m_lastUsed = 1; // play sound on set new pos PlaySound(); SetMoveDone( &CMomentaryRotButton::SetPositionMoveDone ); SetThink( &CMomentaryRotButton::UpdateThink ); SetNextThink( 0 ); // Think again in 0.1 seconds or the time that it will take us to reach our movement goal, // whichever is the shorter interval. This prevents us from overshooting and stuttering when we // are told to change position in very small increments. Vector vecNewAngles = m_start + pev->movedir * ( pev->ideal_yaw * m_flMoveDistance ); float flAngleDelta = fabs( AxisDelta( pev->spawnflags, vecNewAngles, GetLocalAngles( ))); float dt = flAngleDelta / pev->speed; if( dt < gpGlobals->frametime ) { dt = gpGlobals->frametime; float speed = flAngleDelta / gpGlobals->frametime; SetLocalAvelocity( speed * pev->movedir * m_direction ); } dt = bound( gpGlobals->frametime, dt, gpGlobals->frametime * 6 ); SetMoveDoneTime( dt ); }
void CMomentaryRotButton :: UseMoveDone( void ) { SetLocalAvelocity( g_vecZero ); // make sure our targets stop where we stopped. float flPos = GetPos( GetLocalAngles( )); UpdateTarget( flPos ); m_lastUsed = 0; if( FBitSet( pev->spawnflags, SF_MOMENTARY_ROT_BUTTON_AUTO_RETURN ) && m_returnSpeed > 0 ) { SetMoveDone( &CMomentaryRotButton::ReturnMoveDone ); m_direction = -1; if( flPos >= 1.0f ) { // disable use until button is waiting SetUse( NULL ); // delay before autoreturn. SetMoveDoneTime( m_flDelay + 0.1f ); } else SetMoveDoneTime( 0.1f ); } else { SetThink( NULL ); SetMoveDone( NULL ); } }
void CPendulum :: Swing( void ) { float delta, dt; delta = CBaseToggle::AxisDelta( pev->spawnflags, GetLocalAngles(), m_center ); dt = gpGlobals->time - m_time; // how much time has passed? m_time = gpGlobals->time; // remember the last time called // integrate velocity if( delta > 0 && m_accel > 0 ) pev->speed -= m_accel * dt; else pev->speed += m_accel * dt; pev->speed = bound( -m_maxSpeed, pev->speed, m_maxSpeed ); m_iState = STATE_ON; // scale the destdelta vector by the time spent traveling to get velocity SetLocalAvelocity( pev->speed * pev->movedir ); // call this again SetNextThink( 0.1f ); SetMoveDoneTime( 0.1f ); if( m_damp ) { m_dampSpeed -= m_damp * m_dampSpeed * dt; if( m_dampSpeed < 30.0 ) { SetLocalAngles( m_center ); pev->speed = 0; SetThink( NULL ); SetLocalAvelocity( g_vecZero ); m_iState = STATE_OFF; } else if( pev->speed > m_dampSpeed ) { pev->speed = m_dampSpeed; } else if( pev->speed < -m_dampSpeed ) { pev->speed = -m_dampSpeed; } } }
void CPendulum :: Stop( void ) { SetLocalAngles( m_start ); pev->speed = 0; // dead stop SetThink( NULL ); SetLocalAvelocity( g_vecZero ); m_iState = STATE_OFF; }
//========================================================= // Rotating Use - when a rotating brush is triggered //========================================================= void CFuncRotating :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if( IsLockedByMaster( pActivator )) return; m_bStopAtStartPos = false; if( useType == USE_SET ) { if( value != 0 ) { // never toggle direction from momentary entities if( pCaller && !FClassnameIs( pCaller, "momentary_rot_button" ) && !FClassnameIs( pCaller, "momentary_rot_door" )) pev->impulse = (value < 0) ? true : false; value = fabs( value ); SetTargetSpeed( bound( 0, value, 1 ) * m_flMaxSpeed ); } else { SetTargetSpeed( 0 ); } return; } // a liitle easter egg if( useType == USE_RESET ) { if( value == 0.0f ) { if( m_iState == STATE_OFF ) pev->impulse = !pev->impulse; return; } if( m_iState == STATE_OFF ) { // apply angular impulse (XashXT feature) SetLocalAvelocity( pev->movedir * (bound( -1, value, 1 ) * m_flMaxSpeed )); SetMoveDone( RotateFriction ); pev->friction = 1.0f; RotateFriction(); } return; } if( pev->speed != 0 ) SetTargetSpeed( 0 ); else SetTargetSpeed( m_flMaxSpeed ); }
void COsprey :: Killed( entvars_t *pevAttacker, int iGib ) { pev->movetype = MOVETYPE_TOSS; pev->gravity = 0.3; SetAbsVelocity( m_velocity ); SetLocalAvelocity( Vector( RANDOM_FLOAT( -20, 20 ), 0, RANDOM_FLOAT( -50, 50 ) )); STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor4.wav" ); UTIL_SetSize( pev, Vector( -32, -32, -64), Vector( 32, 32, 0) ); SetThink( DyingThink ); SetTouch( CrashTouch ); SetNextThink( 0.1 ); pev->health = 0; pev->takedamage = DAMAGE_NO; m_startTime = gpGlobals->time + 4.0; }
//========================================================= //========================================================= void CFlockingFlyer :: BoidAdvanceFrame ( ) { float flapspeed = (pev->speed - pev->armorvalue) / AFLOCK_ACCELERATE; pev->armorvalue = pev->armorvalue * .8 + pev->speed * .2; if (flapspeed < 0) flapspeed = -flapspeed; if (flapspeed < 0.25) flapspeed = 0.25; if (flapspeed > 1.9) flapspeed = 1.9; pev->framerate = flapspeed; Vector avelocity = GetLocalAvelocity(); // lean avelocity.x = - (GetAbsAngles().x + flapspeed * 5); // bank avelocity.z = - (GetAbsAngles().z + avelocity.y); SetLocalAvelocity( avelocity ); StudioFrameAdvance( 0.1 ); }
void CMomentaryRotButton :: SetPositionMoveDone( void ) { float flCurPos = GetPos( GetLocalAngles( )); if((( flCurPos >= pev->ideal_yaw ) && ( m_direction == 1 )) || (( flCurPos <= pev->ideal_yaw ) && ( m_direction == -1 ))) { // g-cont. we need auto return after direct set position? if( FBitSet( pev->spawnflags, SF_MOMENTARY_ROT_BUTTON_AUTO_RETURN ) && m_returnSpeed > 0 ) { SetMoveDone( &CMomentaryRotButton::ReturnMoveDone ); m_direction = -1; if( flCurPos >= 1.0f ) { // disable use until button is waiting SetUse( NULL ); // delay before autoreturn. SetMoveDoneTime( m_flDelay + 0.1f ); } else SetMoveDoneTime( 0.1f ); } else { m_iState = STATE_OFF; // we reached or surpassed our movement goal. SetLocalAvelocity( g_vecZero ); // BUGBUG: Won't this get the player stuck? SetLocalAngles( m_start + pev->movedir * ( pev->ideal_yaw * m_flMoveDistance )); SetNextThink( -1 ); SetMoveDoneTime( -1 ); UpdateTarget( pev->ideal_yaw ); } m_lastUsed = 0; return; } // set right state if( flCurPos >= pev->ideal_yaw ) m_iState = STATE_TURN_OFF; if( flCurPos <= pev->ideal_yaw ) m_iState = STATE_TURN_ON; Vector vecNewAngles = m_start + pev->movedir * ( pev->ideal_yaw * m_flMoveDistance ); float flAngleDelta = fabs( AxisDelta( pev->spawnflags, vecNewAngles, GetLocalAngles( ))); float dt = flAngleDelta / pev->speed; if( dt < gpGlobals->frametime ) { dt = gpGlobals->frametime; float speed = flAngleDelta / gpGlobals->frametime; SetLocalAvelocity( speed * pev->movedir * m_direction ); } dt = bound( gpGlobals->frametime, dt, gpGlobals->frametime * 6 ); SetMoveDoneTime( dt ); }
void COsprey :: DyingThink( void ) { StudioFrameAdvance( ); SetNextThink( 0.1 ); Vector angVel = GetLocalAvelocity(); angVel *= 1.02; SetLocalAvelocity( angVel ); // still falling? if (m_startTime > gpGlobals->time ) { UTIL_MakeAimVectors( GetAbsAngles() ); ShowDamage( ); Vector vecSpot = GetAbsOrigin() + GetAbsVelocity() * 0.2; Vector vecVel = GetAbsVelocity(); // random explosions MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now WRITE_COORD( vecSpot.x + RANDOM_FLOAT( -150, 150 )); WRITE_COORD( vecSpot.y + RANDOM_FLOAT( -150, 150 )); WRITE_COORD( vecSpot.z + RANDOM_FLOAT( -150, -50 )); WRITE_SHORT( g_sModelIndexFireball ); WRITE_BYTE( RANDOM_LONG(0,29) + 30 ); // scale * 10 WRITE_BYTE( 12 ); // framerate WRITE_BYTE( TE_EXPLFLAG_NONE ); MESSAGE_END(); // lots of smoke MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_SMOKE ); WRITE_COORD( vecSpot.x + RANDOM_FLOAT( -150, 150 )); WRITE_COORD( vecSpot.y + RANDOM_FLOAT( -150, 150 )); WRITE_COORD( vecSpot.z + RANDOM_FLOAT( -150, -50 )); WRITE_SHORT( g_sModelIndexSmoke ); WRITE_BYTE( 100 ); // scale * 10 WRITE_BYTE( 10 ); // framerate MESSAGE_END(); vecSpot = GetAbsOrigin() + (pev->mins + pev->maxs) * 0.5; MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_BREAKMODEL); // position WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z ); // size WRITE_COORD( 800 ); WRITE_COORD( 800 ); WRITE_COORD( 132 ); // velocity WRITE_COORD( vecVel.x ); WRITE_COORD( vecVel.y ); WRITE_COORD( vecVel.z ); // randomization WRITE_BYTE( 50 ); // Model WRITE_SHORT( m_iTailGibs ); //model id# // # of shards WRITE_BYTE( 8 ); // let client decide // duration WRITE_BYTE( 200 );// 10.0 seconds // flags WRITE_BYTE( BREAK_METAL ); MESSAGE_END(); // don't stop it we touch a entity pev->flags &= ~FL_ONGROUND; pev->nextthink = gpGlobals->time + 0.2; return; } else { Vector vecSpot = GetAbsOrigin() + (pev->mins + pev->maxs) * 0.5; /* MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_EXPLOSION); // This just makes a dynamic light now WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z + 512 ); WRITE_SHORT( m_iExplode ); WRITE_BYTE( 250 ); // scale * 10 WRITE_BYTE( 10 ); // framerate MESSAGE_END(); */ // gibs MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_SPRITE ); WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z + 512 ); WRITE_SHORT( m_iExplode ); WRITE_BYTE( 250 ); // scale * 10 WRITE_BYTE( 255 ); // brightness MESSAGE_END(); /* MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY ); WRITE_BYTE( TE_SMOKE ); WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z + 300 ); WRITE_SHORT( g_sModelIndexSmoke ); WRITE_BYTE( 250 ); // scale * 10 WRITE_BYTE( 6 ); // framerate MESSAGE_END(); */ Vector vecOrigin = GetAbsOrigin(); // blast circle MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecOrigin ); WRITE_BYTE( TE_BEAMCYLINDER ); WRITE_COORD( vecOrigin.x); WRITE_COORD( vecOrigin.y); WRITE_COORD( vecOrigin.z); WRITE_COORD( vecOrigin.x); WRITE_COORD( vecOrigin.y); WRITE_COORD( vecOrigin.z + 2000 ); // reach damage radius over .2 seconds WRITE_SHORT( m_iSpriteTexture ); WRITE_BYTE( 0 ); // startframe WRITE_BYTE( 0 ); // framerate WRITE_BYTE( 4 ); // life WRITE_BYTE( 32 ); // width WRITE_BYTE( 0 ); // noise WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 192 ); // r, g, b WRITE_BYTE( 128 ); // brightness WRITE_BYTE( 0 ); // speed MESSAGE_END(); EMIT_SOUND(ENT(pev), CHAN_STATIC, "weapons/mortarhit.wav", 1.0, 0.3); RadiusDamage( vecOrigin, pev, pev, 300, CLASS_NONE, DMG_BLAST ); // gibs vecSpot = vecOrigin + (pev->mins + pev->maxs) * 0.5; MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecSpot ); WRITE_BYTE( TE_BREAKMODEL); // position WRITE_COORD( vecSpot.x ); WRITE_COORD( vecSpot.y ); WRITE_COORD( vecSpot.z + 64); // size WRITE_COORD( 800 ); WRITE_COORD( 800 ); WRITE_COORD( 128 ); // velocity WRITE_COORD( m_velocity.x ); WRITE_COORD( m_velocity.y ); WRITE_COORD( fabs( m_velocity.z ) * 0.25 ); // randomization WRITE_BYTE( 40 ); // Model WRITE_SHORT( m_iBodyGibs ); //model id# // # of shards WRITE_BYTE( 128 ); // duration WRITE_BYTE( 200 );// 10.0 seconds // flags WRITE_BYTE( BREAK_METAL ); MESSAGE_END(); UTIL_Remove( this ); } }
//========================================================= // Leader boids use this think every tenth //========================================================= void CFlockingFlyer :: FlockLeaderThink( void ) { TraceResult tr; Vector vecDist;// used for general measurements Vector vecDir;// used for general measurements int cProcessed = 0;// keep track of how many other boids we've processed float flLeftSide; float flRightSide; pev->nextthink = gpGlobals->time + 0.1; UTIL_MakeVectors ( GetAbsAngles() ); // is the way ahead clear? if ( !FPathBlocked () ) { // if the boid is turning, stop the trend. if ( m_fTurning ) { m_fTurning = FALSE; Vector avelocity = GetLocalAvelocity(); avelocity.y = 0; SetLocalAvelocity( avelocity ); } m_fPathBlocked = FALSE; if (pev->speed <= AFLOCK_FLY_SPEED ) pev->speed+= 5; SetAbsVelocity( gpGlobals->v_forward * pev->speed ); BoidAdvanceFrame( ); return; } // IF we get this far in the function, the leader's path is blocked! m_fPathBlocked = TRUE; if ( !m_fTurning)// something in the way and boid is not already turning to avoid { // measure clearance on left and right to pick the best dir to turn UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - GetAbsOrigin()); flRightSide = vecDist.Length(); UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr); vecDist = (tr.vecEndPos - GetAbsOrigin()); flLeftSide = vecDist.Length(); // turn right if more clearance on right side if ( flRightSide > flLeftSide ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = -AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); m_fTurning = TRUE; } // default to left turn :) else if ( flLeftSide > flRightSide ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); m_fTurning = TRUE; } else { // equidistant. Pick randomly between left and right. m_fTurning = TRUE; if ( RANDOM_LONG( 0, 1 ) == 0 ) { Vector avelocity = GetLocalAvelocity(); avelocity.y = AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); } else { Vector avelocity = GetLocalAvelocity(); avelocity.y = -AFLOCK_TURN_RATE; SetLocalAvelocity( avelocity ); } } } SpreadFlock( ); SetAbsVelocity( gpGlobals->v_forward * pev->speed ); // check and make sure we aren't about to plow into the ground, don't let it happen UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() - gpGlobals->v_up * 16, ignore_monsters, ENT(pev), &tr); if (tr.flFraction != 1.0 && GetAbsVelocity().z < 0 ) { Vector velocity = GetAbsVelocity(); velocity.z = 0; SetAbsVelocity( velocity ); } // maybe it did, though. if ( FBitSet (pev->flags, FL_ONGROUND) ) { UTIL_SetOrigin (this, GetAbsOrigin() + Vector ( 0 , 0 , 1 ) ); Vector velocity = GetAbsVelocity(); velocity.z = 0; SetAbsVelocity( velocity ); } if ( m_flFlockNextSoundTime < gpGlobals->time ) { MakeSound(); m_flFlockNextSoundTime = gpGlobals->time + RANDOM_FLOAT( 1, 3 ); } BoidAdvanceFrame( ); return; }
void CFuncRotating :: UpdateSpeed( float flNewSpeed ) { float flOldSpeed = pev->speed; pev->speed = bound( -m_flMaxSpeed, flNewSpeed, m_flMaxSpeed ); if( m_bStopAtStartPos ) { int checkAxis = 2; // see if we got close to the starting orientation if( pev->movedir[0] != 0 ) { checkAxis = 0; } else if( pev->movedir[1] != 0 ) { checkAxis = 1; } float angDelta = anglemod( GetLocalAngles()[checkAxis] - m_angStart[checkAxis] ); if( angDelta > 180.0f ) angDelta -= 360.0f; if( flNewSpeed < 100 ) { if( flNewSpeed <= 25 && fabs( angDelta ) < 1.0f ) { m_flTargetSpeed = 0; m_bStopAtStartPos = false; pev->speed = 0.0f; SetLocalAngles( m_angStart ); } else if( fabs( angDelta ) > 90.0f ) { // keep rotating at same speed for now pev->speed = flOldSpeed; } else { float minSpeed = fabs( angDelta ); if( minSpeed < 20 ) minSpeed = 20; pev->speed = flOldSpeed > 0.0f ? minSpeed : -minSpeed; } } } SetLocalAvelocity( pev->movedir * pev->speed ); if(( flOldSpeed == 0 ) && ( pev->speed != 0 )) { // starting to move - emit the sound. EMIT_SOUND_DYN( edict(), CHAN_STATIC, STRING( pev->noise3 ), 0.01f, m_flAttenuation, 0, FANPITCHMIN ); RampPitchVol(); } else if(( flOldSpeed != 0 ) && ( pev->speed == 0 )) { // stopping - stop the sound. STOP_SOUND( edict(), CHAN_STATIC, STRING( pev->noise3 )); SetMoveDoneTime( -1 ); m_iState = STATE_OFF; } else { // changing speed - adjust the pitch and volume. RampPitchVol(); } }