void CPlantedC4::C4Think() { if (!IsInWorld()) { UTIL_Remove( this ); return; } //Bomb is dead, don't think anymore if( !m_bBombTicking ) { SetThink( NULL ); return; } SetNextThink( gpGlobals->curtime + 0.12 ); #ifndef CLIENT_DLL // let the bots hear the bomb beeping // BOTPORT: Emit beep events at same time as client effects IGameEvent * event = gameeventmanager->CreateEvent( "bomb_beep" ); if( event ) { event->SetInt( "entindex", entindex() ); gameeventmanager->FireEvent( event ); } #endif // IF the timer has expired ! blow this bomb up! if (m_flC4Blow <= gpGlobals->curtime) { // give the defuser credit for defusing the bomb CBasePlayer *pBombOwner = dynamic_cast< CBasePlayer* >( GetOwnerEntity() ); if ( pBombOwner ) { pBombOwner->IncrementFragCount( 3 ); } CSGameRules()->m_bBombDropped = false; trace_t tr; Vector vecSpot = GetAbsOrigin(); vecSpot[2] += 8; UTIL_TraceLine( vecSpot, vecSpot + Vector ( 0, 0, -40 ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); Explode( &tr, DMG_BLAST ); CSGameRules()->m_bBombPlanted = false; IGameEvent * event = gameeventmanager->CreateEvent( "bomb_exploded" ); if( event ) { event->SetInt( "userid", pBombOwner?pBombOwner->GetUserID():-1 ); event->SetInt( "site", m_iBombSiteIndex ); event->SetInt( "priority", 9 ); gameeventmanager->FireEvent( event ); } } //if the defusing process has started if ((m_bStartDefuse == true) && (m_pBombDefuser != NULL)) { //if the defusing process has not ended yet if ( m_flDefuseCountDown > gpGlobals->curtime) { int iOnGround = FBitSet( m_pBombDefuser->GetFlags(), FL_ONGROUND ); //if the bomb defuser has stopped defusing the bomb if( m_flNextDefuse < gpGlobals->curtime || !iOnGround ) { if ( !iOnGround && m_pBombDefuser->IsAlive() ) ClientPrint( m_pBombDefuser, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground"); // release the player from being frozen m_pBombDefuser->ResetMaxSpeed(); m_pBombDefuser->m_bIsDefusing = false; #ifndef CLIENT_DLL // tell the bots someone has aborted defusing IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortdefuse" ); if( event ) { event->SetInt("userid", m_pBombDefuser->GetUserID() ); event->SetInt( "priority", 6 ); gameeventmanager->FireEvent( event ); } #endif //cancel the progress bar m_pBombDefuser->SetProgressBarTime( 0 ); m_pBombDefuser = NULL; m_bStartDefuse = false; m_flDefuseCountDown = 0; m_flDefuseLength = 0; //force it to show completely defused } return; } //if the defuse process has ended, kill the c4 else if ( !m_pBombDefuser->IsDead() ) { IGameEvent * event = gameeventmanager->CreateEvent( "bomb_defused" ); if( event ) { event->SetInt("userid", m_pBombDefuser->GetUserID() ); event->SetInt("site", m_iBombSiteIndex ); event->SetInt( "priority", 9 ); gameeventmanager->FireEvent( event ); } Vector soundPosition = m_pBombDefuser->GetAbsOrigin() + Vector( 0, 0, 5 ); CPASAttenuationFilter filter( soundPosition ); EmitSound( filter, entindex(), "c4.disarmfinish" ); // The bomb has just been disarmed.. Check to see if the round should end now m_bBombTicking = false; // release the player from being frozen m_pBombDefuser->ResetMaxSpeed(); m_pBombDefuser->m_bIsDefusing = false; CSGameRules()->m_bBombDefused = true; CSGameRules()->CheckWinConditions(); // give the defuser credit for defusing the bomb m_pBombDefuser->IncrementFragCount( 3 ); CSGameRules()->m_bBombDropped = false; CSGameRules()->m_bBombPlanted = false; // Clear their progress bar. m_pBombDefuser->SetProgressBarTime( 0 ); m_pBombDefuser = NULL; m_bStartDefuse = false; m_flDefuseLength = 10; return; } #ifndef CLIENT_DLL // tell the bots someone has aborted defusing IGameEvent * event = gameeventmanager->CreateEvent( "bomb_abortdefuse" ); if( event ) { event->SetInt("userid", m_pBombDefuser->GetUserID() ); event->SetInt( "priority", 6 ); gameeventmanager->FireEvent( event ); } #endif //if it gets here then the previouse defuser has taken off or been killed // release the player from being frozen m_pBombDefuser->ResetMaxSpeed(); m_pBombDefuser->m_bIsDefusing = false; m_bStartDefuse = false; m_pBombDefuser = NULL; } }
void CFuncRotating :: Spawn( ) { m_iState = STATE_OFF; m_fCurSpeed = 0; //LRC // set final pitch. Must not be PITCH_NORM, since we // plan on pitch shifting later. m_pitch = PITCH_NORM - 1; // maintain compatibility with previous maps if (m_flVolume == 0.0) m_flVolume = 1.0; // if the designer didn't set a sound attenuation, default to one. m_flAttenuation = ATTN_NORM; if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_SMALLRADIUS) ) { m_flAttenuation = ATTN_IDLE; } else if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_MEDIUMRADIUS) ) { m_flAttenuation = ATTN_STATIC; } else if ( FBitSet ( pev->spawnflags, SF_BRUSH_ROTATE_LARGERADIUS) ) { m_flAttenuation = ATTN_NORM; } // prevent divide by zero if level designer forgets friction! if ( m_flFanFriction <= 0 ) //LRC - ensure it's not negative { m_flFanFriction = 1; } if (pev->movedir == g_vecZero) { if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_Z_AXIS) ) pev->movedir = Vector(0,0,1); else if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_X_AXIS) ) pev->movedir = Vector(1,0,0); else pev->movedir = Vector(0,1,0); // y-axis } // check for reverse rotation if ( FBitSet(pev->spawnflags, SF_BRUSH_ROTATE_BACKWARDS) ) pev->movedir = pev->movedir * -1; // some rotating objects like fake volumetric lights will not be solid. if ( FBitSet(pev->spawnflags, SF_ROTATING_NOT_SOLID) ) { pev->solid = SOLID_NOT; pev->skin = CONTENTS_EMPTY; pev->movetype = MOVETYPE_PUSH; } else { pev->solid = SOLID_BSP; pev->movetype = MOVETYPE_PUSH; } UTIL_SetOrigin(this, pev->origin); SET_MODEL( ENT(pev), STRING(pev->model) ); SetUse(&CFuncRotating :: RotatingUse ); // did level designer forget to assign speed? if (pev->speed <= 0) pev->speed = 0; // Removed this per level designers request. -- JAY // if (pev->dmg == 0) // pev->dmg = 2; // instant-use brush? //LRC - start immediately if unnamed, too. if ( FBitSet( pev->spawnflags, SF_BRUSH_ROTATE_INSTANT) || FStringNull(pev->targetname) ) { SetThink(&CFuncRotating :: WaitForStart ); SetNextThink( 1.5 ); // leave a magic delay for client to start up } // can this brush inflict pain? if ( FBitSet (pev->spawnflags, SF_BRUSH_HURT) ) { SetTouch(&CFuncRotating :: HurtTouch ); } Precache( ); }
void CMP5N::MP5NFire( float flSpread, float flCycleTime, BOOL bUseSemi ) { m_iShotsFired++; m_fDelayFire = TRUE; m_flAccuracy = ( m_iShotsFired * m_iShotsFired ) / MP5N_ACCURACY_DIVISOR + MP5N_ACCURACY_OFFSET; if( m_flAccuracy > MP5N_MAX_INACCURACY ) { m_flAccuracy = MP5N_MAX_INACCURACY; } if( m_iClip <= 0 ) { if ( m_fFireOnEmpty ) { PlayEmptySound(); m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.2; } /*! @todo Implements me : if( TheBots ) TheBots->OnEvent( EVENT_WEAPON_FIRED_ON_EMPTY, m_pPlayer->pev, NULL ); */ return; } m_iClip--; m_pPlayer->pev->effects |= EF_MUZZLEFLASH; m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; m_pPlayer->m_iWeaponFlash = DIM_GUN_FLASH; UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); Vector vecDir = m_pPlayer->FireBullets3( m_pPlayer->GetGunPosition(), gpGlobals->v_forward, flSpread, 8192.0, MP5N_PENETRATION, BULLET_PLAYER_9MM, MP5N_DAMAGE, MP5N_RANGE_MODIFIER, m_pPlayer->pev, FALSE, m_pPlayer->random_seed ); PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usMP5N, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, m_pPlayer->pev->punchangle.x * 100, m_pPlayer->pev->punchangle.y * 100, 0, 0 ); m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + flCycleTime; if( !m_iClip && m_pPlayer->m_rgAmmo[ m_iPrimaryAmmoType ] <= 0 ) { m_pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); } m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + MP5N_IDLE_TIME; if( m_pPlayer->pev->velocity.Length2D() > 0 ) { KickBack( 0.9, 0.475, 0.35, 0.0425, 5, 3, 6 ); } else if( !FBitSet( m_pPlayer->pev->flags, FL_ONGROUND ) ) { KickBack( 0.5, 0.275, 0.2, 0.03, 3, 2, 10 ); } else if( FBitSet( m_pPlayer->pev->flags, FL_DUCKING ) ) { KickBack( 0.225, 0.15, 0.1, 0.015, 2, 1, 10 ); } else { KickBack( 0.25, 0.175, 0.125, 0.02, 2.25, 1.25, 10 ); } }
void Touch( CBaseEntity *pOther ) { switch( pOther->pev->movetype ) { case MOVETYPE_NONE: case MOVETYPE_PUSH: case MOVETYPE_NOCLIP: case MOVETYPE_FOLLOW: return; } if( pev->button ) { if( m_flWait >= gpGlobals->time ) return; if( !pOther->IsPlayer() || pOther->pev->movetype != MOVETYPE_WALK ) return; float time, dist, f; Vector origin, velocity; origin = (pev->absmin + pev->absmax) * 0.5f; CBaseEntity *pTarg = CBaseEntity::Instance( pev->owner ); // assume pev->owner is valid time = sqrt (( pTarg->pev->origin.z - origin.z ) / (0.5f * CVAR_GET_FLOAT( "sv_gravity" ))); if( !time ) { UTIL_Remove( this ); return; } velocity = pTarg->pev->origin - origin; velocity.z = 0.0f; dist = velocity.Length(); velocity = velocity.Normalize(); f = dist / time; velocity *= f; velocity.z = time * CVAR_GET_FLOAT( "sv_gravity" ); pOther->pev->flJumpPadTime = gpGlobals->time; pOther->pev->basevelocity = velocity; pOther->pev->velocity = g_vecZero; pOther->pev->flags &= ~FL_BASEVELOCITY; EMIT_SOUND( ENT( pev ), CHAN_VOICE, "world/jumppad.wav", VOL_NORM, ATTN_IDLE ); m_flWait = gpGlobals->time + ( 2.0f * gpGlobals->frametime ); if( FBitSet( pev->spawnflags, SF_PUSH_ONCE )) UTIL_Remove( this ); } else if( pOther->pev->solid != SOLID_NOT && pOther->pev->solid != SOLID_BSP ) { // instant trigger, just transfer velocity and remove if( FBitSet( pev->spawnflags, SF_PUSH_ONCE )) { pOther->pev->velocity = pOther->pev->velocity + (pev->speed * pev->movedir); if( pOther->pev->velocity.z > 0 ) pOther->pev->flags &= ~FL_ONGROUND; UTIL_Remove( this ); } else { Vector vecPush = (pev->speed * pev->movedir); if ( pOther->pev->flags & FL_BASEVELOCITY ) vecPush = vecPush + pOther->pev->basevelocity; pOther->pev->basevelocity = vecPush; pOther->pev->flags |= FL_BASEVELOCITY; pOther->pev->flJumpPadTime = gpGlobals->time; } } }
void CPushable :: Move( CBaseEntity *pOther, int push ) { entvars_t* pevToucher = pOther->pev; int playerTouch = 0; // Is entity standing on this pushable ? if ( FBitSet(pevToucher->flags,FL_ONGROUND) && pevToucher->groundentity && VARS(pevToucher->groundentity) == pev ) { // Only push if floating if ( pev->waterlevel > 0 ) pev->velocity.z += pevToucher->velocity.z * 0.1; return; } if ( pOther->IsPlayer() ) { if ( push && !(pevToucher->button & (IN_FORWARD|IN_USE)) ) // Don't push unless the player is pushing forward and NOT use (pull) return; playerTouch = 1; } float factor; if ( playerTouch ) { if ( !(pevToucher->flags & FL_ONGROUND) ) // Don't push away from jumping/falling players unless in water { if ( pev->waterlevel < 1 ) return; else factor = 0.1; } else factor = 1; } else factor = 0.25; pev->velocity.x += pevToucher->velocity.x * factor; pev->velocity.y += pevToucher->velocity.y * factor; float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); if ( push && (length > MaxSpeed()) ) { pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); } if ( playerTouch ) { pevToucher->velocity.x = pev->velocity.x; pevToucher->velocity.y = pev->velocity.y; if ( (gpGlobals->time - m_soundTime) > 0.7 ) { m_soundTime = gpGlobals->time; if ( length > 0 && FBitSet(pev->flags,FL_ONGROUND) ) { m_lastSound = RANDOM_LONG(0,2); EMIT_SOUND(ENT(pev), CHAN_WEAPON, m_soundNames[m_lastSound], 0.5, ATTN_NORM); // SetThink( StopSound ); // pev->nextthink = pev->ltime + 0.1; } else STOP_SOUND( ENT(pev), CHAN_WEAPON, m_soundNames[m_lastSound] ); } } }
void CPushable :: Move( CBaseEntity *pOther, int push ) { entvars_t* pevToucher = pOther->pev; int playerTouch = 0; // Is entity standing on this pushable ? if ( FBitSet(pevToucher->flags,FL_ONGROUND) && pevToucher->groundentity && VARS(pevToucher->groundentity) == pev ) { // Only push if floating if ( pev->waterlevel > 0 && pev->watertype > CONTENT_FLYFIELD) pev->velocity.z += pevToucher->velocity.z * 0.1; return; } if ( pOther->IsPlayer() ) { if ( push && !(pevToucher->button & (IN_FORWARD|IN_USE)) ) // Don't push unless the player is pushing forward and NOT use (pull) return; playerTouch = 1; } float factor; if ( playerTouch ) { if ( !(pevToucher->flags & FL_ONGROUND) ) // Don't push away from jumping/falling players unless in water { if ( pev->waterlevel < 1 || pev->watertype <= CONTENT_FLYFIELD) return; else factor = 0.1; } else factor = 1; } else factor = 0.25; if (!push) factor = factor*0.5; Vector oldVelocity = pev->velocity; //LRC 1.8 pev->velocity.x += pevToucher->velocity.x * factor; pev->velocity.y += pevToucher->velocity.y * factor; float length = sqrt( pev->velocity.x * pev->velocity.x + pev->velocity.y * pev->velocity.y ); if ( push && (length > MaxSpeed()) ) { pev->velocity.x = (pev->velocity.x * MaxSpeed() / length ); pev->velocity.y = (pev->velocity.y * MaxSpeed() / length ); } if ( playerTouch ) { //LRC 1.8 if ( pev->spawnflags & SF_PUSH_NOSUPERPUSH ) { // don't accelerate the pushable to be faster than the person pushing it float playerSpeed = pevToucher->velocity.Length2D(); Vector playerPushDir = pevToucher->velocity/playerSpeed; playerPushDir.z = 0; float newdot = DotProduct( playerPushDir, pev->velocity ); // how fast we're going with respect to the playerPushDir float olddot = DotProduct( playerPushDir, oldVelocity ); // how fast we used to be going if ( /*olddot <= playerSpeed+0.1f &&*/ newdot > playerSpeed ) { // if it wasn't going too fast before, and now it is, adjust to the pusher's actual velocity pev->velocity.x -= playerPushDir.x * newdot; pev->velocity.y -= playerPushDir.y * newdot; pev->velocity.x += pevToucher->velocity.x; pev->velocity.y += pevToucher->velocity.y; } } pevToucher->velocity.x = pev->velocity.x; pevToucher->velocity.y = pev->velocity.y; if ( (gpGlobals->time - m_soundTime) > 0.7 ) { m_soundTime = gpGlobals->time; if ( length > 0 && FBitSet(pev->flags,FL_ONGROUND) ) { m_lastSound = RANDOM_LONG(0,2); EMIT_SOUND(ENT(pev), CHAN_WEAPON, m_soundNames[m_lastSound], 0.5, ATTN_NORM); // SetThink( StopSound ); // SetNextThink( 0.1 ); } else STOP_SOUND( ENT(pev), CHAN_WEAPON, m_soundNames[m_lastSound] ); } } }
void CBaseDoor::Blocked(CBaseEntity *pOther) { edict_t * pentTarget = NULL; CBaseDoor *pDoor = NULL; // Hurt the blocker a little. if(pev->dmg) pOther->TakeDamage(pev, pev, pev->dmg, DMG_CRUSH); // if a door has a negative wait, it would never come back if blocked, // so let it just squash the object to death real fast if(m_flWait >= 0) { if(m_toggle_state == TS_GOING_DOWN) { DoorGoUp(); } else { DoorGoDown(); } } // Block all door pieces with the same targetname here. if(!FStringNull(pev->targetname)) { for(;;) { pentTarget = FIND_ENTITY_BY_TARGETNAME(pentTarget, STRING(pev->targetname)); if(VARS(pentTarget) != pev) { if(FNullEnt(pentTarget)) break; if(FClassnameIs(pentTarget, "func_door") || FClassnameIs(pentTarget, "func_door_rotating")) { pDoor = GetClassPtr((CBaseDoor *)VARS(pentTarget)); if(pDoor->m_flWait >= 0) { if(pDoor->pev->velocity == pev->velocity && pDoor->pev->avelocity == pev->velocity) { // this is the most hacked, evil, bastardized thing I've ever seen. kjb if(FClassnameIs(pentTarget, "func_door")) { // set origin to realign normal doors pDoor->pev->origin = pev->origin; pDoor->pev->velocity = g_vecZero; // stop! } else { // set angles to realign rotating doors pDoor->pev->angles = pev->angles; pDoor->pev->avelocity = g_vecZero; } } if(!FBitSet(pev->spawnflags, SF_DOOR_SILENT)) STOP_SOUND(ENT(pev), CHAN_STATIC, (char *)STRING(pev->noiseMoving)); if(pDoor->m_toggle_state == TS_GOING_DOWN) pDoor->DoorGoUp(); else pDoor->DoorGoDown(); } } } } } }
void CBaseButton::Precache( void ) { char *pszSound; if ( FBitSet ( pev->spawnflags, SF_BUTTON_SPARK_IF_OFF ) )// this button should spark in OFF state { PRECACHE_SOUND ("buttons/spark1.wav"); PRECACHE_SOUND ("buttons/spark2.wav"); PRECACHE_SOUND ("buttons/spark3.wav"); PRECACHE_SOUND ("buttons/spark4.wav"); PRECACHE_SOUND ("buttons/spark5.wav"); PRECACHE_SOUND ("buttons/spark6.wav"); } // get door button sounds, for doors which require buttons to open if (m_bLockedSound) { pszSound = ButtonSound( (int)m_bLockedSound ); PRECACHE_SOUND(pszSound); m_ls.sLockedSound = ALLOC_STRING(pszSound); } if (m_bUnlockedSound) { pszSound = ButtonSound( (int)m_bUnlockedSound ); PRECACHE_SOUND(pszSound); m_ls.sUnlockedSound = ALLOC_STRING(pszSound); } // get sentence group names, for doors which are directly 'touched' to open switch (m_bLockedSentence) { case 1: m_ls.sLockedSentence = MAKE_STRING("NA"); break; // access denied case 2: m_ls.sLockedSentence = MAKE_STRING("ND"); break; // security lockout case 3: m_ls.sLockedSentence = MAKE_STRING("NF"); break; // blast door case 4: m_ls.sLockedSentence = MAKE_STRING("NFIRE"); break; // fire door case 5: m_ls.sLockedSentence = MAKE_STRING("NCHEM"); break; // chemical door case 6: m_ls.sLockedSentence = MAKE_STRING("NRAD"); break; // radiation door case 7: m_ls.sLockedSentence = MAKE_STRING("NCON"); break; // gen containment case 8: m_ls.sLockedSentence = MAKE_STRING("NH"); break; // maintenance door case 9: m_ls.sLockedSentence = MAKE_STRING("NG"); break; // broken door default: m_ls.sLockedSentence = 0; break; } switch (m_bUnlockedSentence) { case 1: m_ls.sUnlockedSentence = MAKE_STRING("EA"); break; // access granted case 2: m_ls.sUnlockedSentence = MAKE_STRING("ED"); break; // security door case 3: m_ls.sUnlockedSentence = MAKE_STRING("EF"); break; // blast door case 4: m_ls.sUnlockedSentence = MAKE_STRING("EFIRE"); break; // fire door case 5: m_ls.sUnlockedSentence = MAKE_STRING("ECHEM"); break; // chemical door case 6: m_ls.sUnlockedSentence = MAKE_STRING("ERAD"); break; // radiation door case 7: m_ls.sUnlockedSentence = MAKE_STRING("ECON"); break; // gen containment case 8: m_ls.sUnlockedSentence = MAKE_STRING("EH"); break; // maintenance door default: m_ls.sUnlockedSentence = 0; break; } }
void CBaseButton::Spawn( ) { char *pszSound; //---------------------------------------------------- //determine sounds for buttons //a sound of 0 should not make a sound //---------------------------------------------------- pszSound = ButtonSound( m_sounds ); PRECACHE_SOUND(pszSound); pev->noise = ALLOC_STRING(pszSound); Precache(); if ( FBitSet ( pev->spawnflags, SF_BUTTON_SPARK_IF_OFF ) )// this button should spark in OFF state { SetThink ( &CBaseButton::ButtonSpark ); pev->nextthink = gpGlobals->time + 0.5;// no hurry, make sure everything else spawns } SetMovedir(pev); pev->movetype = MOVETYPE_PUSH; pev->solid = SOLID_BSP; SET_MODEL(ENT(pev), STRING(pev->model)); if (pev->speed == 0) pev->speed = 40; if (pev->health > 0) { pev->takedamage = DAMAGE_YES; } if (m_flWait == 0) m_flWait = 1; if (m_flLip == 0) m_flLip = 4; m_toggle_state = TS_AT_BOTTOM; m_vecPosition1 = pev->origin; // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big m_vecPosition2 = m_vecPosition1 + (pev->movedir * (fabs( pev->movedir.x * (pev->size.x-2) ) + fabs( pev->movedir.y * (pev->size.y-2) ) + fabs( pev->movedir.z * (pev->size.z-2) ) - m_flLip)); // Is this a non-moving button? if ( ((m_vecPosition2 - m_vecPosition1).Length() < 1) || (pev->spawnflags & SF_BUTTON_DONTMOVE) ) m_vecPosition2 = m_vecPosition1; m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE); m_fRotating = FALSE; // if the button is flagged for USE button activation only, take away it's touch function and add a use function if ( FBitSet ( pev->spawnflags, SF_BUTTON_TOUCH_ONLY ) ) // touchable button { SetTouch( &CBaseButton::ButtonTouch ); } else { SetTouch ( NULL ); SetUse ( &CBaseButton::ButtonUse ); } }
// // ambient_generic - general-purpose user-defined static sound // void CAmbientGeneric :: Spawn( void ) { /* -1 : "Default" 0 : "Everywhere" 200 : "Small Radius" 125 : "Medium Radius" 80 : "Large Radius" */ if ( FBitSet ( pev->spawnflags, AMBIENT_SOUND_EVERYWHERE) ) { m_flAttenuation = ATTN_NONE; } else if ( FBitSet ( pev->spawnflags, AMBIENT_SOUND_SMALLRADIUS) ) { m_flAttenuation = ATTN_IDLE; } else if ( FBitSet ( pev->spawnflags, AMBIENT_SOUND_MEDIUMRADIUS) ) { m_flAttenuation = ATTN_STATIC; } else if ( FBitSet ( pev->spawnflags, AMBIENT_SOUND_LARGERADIUS) ) { m_flAttenuation = ATTN_NORM; } else {// if the designer didn't set a sound attenuation, default to one. m_flAttenuation = ATTN_STATIC; } char* szSoundFile = (char*) STRING(pev->message); if ( FStringNull( pev->message ) || strlen( szSoundFile ) < 1 ) { ALERT( at_error, "EMPTY AMBIENT AT: %f, %f, %f\n", pev->origin.x, pev->origin.y, pev->origin.z ); pev->nextthink = gpGlobals->time + 0.1; SetThink( &CBaseEntity::SUB_Remove ); return; } pev->solid = SOLID_NOT; pev->movetype = MOVETYPE_NONE; // Set up think function for dynamic modification // of ambient sound's pitch or volume. Don't // start thinking yet. SetThink( &CAmbientGeneric::RampThink ); pev->nextthink = 0; // allow on/off switching via 'use' function. SetUse ( &CAmbientGeneric::ToggleUse ); m_fActive = FALSE; if ( FBitSet ( pev->spawnflags, AMBIENT_SOUND_NOT_LOOPING ) ) m_fLooping = FALSE; else m_fLooping = TRUE; Precache( ); }
//========================================================= // Look - Base class monster function to find enemies or // food by sight. iDistance is distance ( in units ) that the // monster can see. // // Sets the sight bits of the m_afConditions mask to indicate // which types of entities were sighted. // Function also sets the Looker's m_pLink // to the head of a link list that contains all visible ents. // (linked via each ent's m_pLink field) // //========================================================= void CBaseMonster :: Look ( int iDistance ) { int iSighted = 0; // DON'T let visibility information from last frame sit around! ClearConditions(bits_COND_SEE_HATE | bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_SEE_NEMESIS | bits_COND_SEE_CLIENT); m_pLink = NULL; CBaseEntity *pSightEnt = NULL;// the current visible entity that we're dealing with CBaseEntity *pList[100]; Vector delta = Vector( iDistance, iDistance, iDistance ); // Find only monsters/clients in box, NOT limited to PVS int count = UTIL_EntitiesInBox( pList, 100, pev->origin - delta, pev->origin + delta, FL_CLIENT|FL_MONSTER ); for ( int i = 0; i < count; i++ ) { pSightEnt = pList[i]; if ( pSightEnt != this && pSightEnt->pev->health > 0 ) { // the looker will want to consider this entity // don't check anything else about an entity that can't be seen, or an entity that you don't care about. if ( IRelationship( pSightEnt ) != R_NO && FInViewCone( pSightEnt ) && !FBitSet( pSightEnt->pev->flags, FL_NOTARGET ) && FVisible( pSightEnt ) ) { if ( pSightEnt->IsPlayer() ) { // if we see a client, remember that (mostly for scripted AI) iSighted |= bits_COND_SEE_CLIENT; } pSightEnt->m_pLink = m_pLink; m_pLink = pSightEnt; if ( pSightEnt == m_hEnemy ) { // we know this ent is visible, so if it also happens to be our enemy, store that now. iSighted |= bits_COND_SEE_ENEMY; } // don't add the Enemy's relationship to the conditions. We only want to worry about conditions when // we see monsters other than the Enemy. switch ( IRelationship ( pSightEnt ) ) { case R_NM: iSighted |= bits_COND_SEE_NEMESIS; break; case R_HT: iSighted |= bits_COND_SEE_HATE; break; case R_DL: iSighted |= bits_COND_SEE_DISLIKE; break; case R_FR: iSighted |= bits_COND_SEE_FEAR; break; case R_AL: break; default: ALERT ( at_aiconsole, "%s can't assess %s\n", STRING(pev->classname), STRING(pSightEnt->pev->classname ) ); break; } } } } SetConditions( iSighted ); }
//------------------------------------------------------------------------------ // Purpose: //------------------------------------------------------------------------------ void CAmbientGeneric::Activate( void ) { BaseClass::Activate(); // Initialize sound source. If no source was given, or source can't be found // then this is the source if (m_hSoundSource == NULL) { if (m_sSourceEntName != NULL_STRING) { m_hSoundSource = gEntList.FindEntityByName( NULL, m_sSourceEntName ); if ( m_hSoundSource != NULL ) { m_nSoundSourceEntIndex = m_hSoundSource->entindex(); } } if (m_hSoundSource == NULL) { m_hSoundSource = this; m_nSoundSourceEntIndex = entindex(); } else { if ( !FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE ) ) { AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); } } } #ifdef PORTAL // This is the only way we can silence the radio sound from the first room without touching them map -- jdw if ( PortalGameRules() && PortalGameRules()->ShouldRemoveRadio() ) { if ( V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_00" ) == 0 || V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_11" ) == 0 || V_strcmp( STRING( gpGlobals->mapname ), "testchmb_a_14" ) == 0 ) { if ( V_strcmp( STRING( GetEntityName() ), "radio_sound" ) == 0 ) { UTIL_Remove( this ); return; } } } #endif // PORTAL // If active start the sound if ( m_fActive ) { int flags = SND_SPAWNING; // If we are loading a saved game, we can't write into the init/signon buffer here, so just issue // as a regular sound message... if ( gpGlobals->eLoadType == MapLoad_Transition || gpGlobals->eLoadType == MapLoad_LoadGame || g_pGameRules->InRoundRestart() ) { flags = SND_NOFLAGS; } // Tracker 76119: 8/12/07 ywb: // Make sure pitch and volume are set up to the correct value (especially after restoring a .sav file) flags |= ( SND_CHANGE_PITCH | SND_CHANGE_VOL ); // Don't bother sending over to client if volume is zero, though if ( m_dpv.vol > 0 ) { SendSound( (SoundFlags_t)flags ); } SetNextThink( gpGlobals->curtime + 0.1f ); } }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CBullsquid :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case BSQUID_AE_SPIT: { Vector vecSpitOffset; Vector vecSpitDir; UTIL_MakeVectors ( pev->angles ); // !!!HACKHACK - the spot at which the spit originates (in front of the mouth) was measured in 3ds and hardcoded here. // we should be able to read the position of bones at runtime for this info. vecSpitOffset = ( gpGlobals->v_right * 8 + gpGlobals->v_forward * 37 + gpGlobals->v_up * 23 ); vecSpitOffset = ( pev->origin + vecSpitOffset ); vecSpitDir = ( ( m_hEnemy->pev->origin + m_hEnemy->pev->view_ofs ) - vecSpitOffset ).Normalize(); vecSpitDir.x += RANDOM_FLOAT( -0.05, 0.05 ); vecSpitDir.y += RANDOM_FLOAT( -0.05, 0.05 ); vecSpitDir.z += RANDOM_FLOAT( -0.05, 0 ); // do stuff for this event. AttackSound(); // spew the spittle temporary ents. MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpitOffset ); WRITE_BYTE( TE_SPRITE_SPRAY ); WRITE_COORD( vecSpitOffset.x); // pos WRITE_COORD( vecSpitOffset.y); WRITE_COORD( vecSpitOffset.z); WRITE_COORD( vecSpitDir.x); // dir WRITE_COORD( vecSpitDir.y); WRITE_COORD( vecSpitDir.z); WRITE_SHORT( iSquidSpitSprite ); // model WRITE_BYTE ( 15 ); // count WRITE_BYTE ( 210 ); // speed WRITE_BYTE ( 25 ); // noise ( client will divide by 100 ) MESSAGE_END(); CSquidSpit::Shoot( pev, vecSpitOffset, vecSpitDir * 900 ); } break; case BSQUID_AE_BITE: { // SOUND HERE! CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.bullsquidDmgBite, DMG_SLASH ); if ( pHurt ) { //pHurt->pev->punchangle.z = -15; //pHurt->pev->punchangle.x = -45; pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_forward * 100; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 100; } } break; case BSQUID_AE_TAILWHIP: { CBaseEntity *pHurt = CheckTraceHullAttack( 70, gSkillData.bullsquidDmgWhip, DMG_CLUB | DMG_ALWAYSGIB ); if ( pHurt ) { pHurt->pev->punchangle.z = -20; pHurt->pev->punchangle.x = 20; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 200; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_up * 100; } } break; case BSQUID_AE_BLINK: { // close eye. pev->skin = 1; } break; case BSQUID_AE_HOP: { float flGravity = g_psv_gravity->value; // throw the squid up into the air on this frame. if ( FBitSet ( pev->flags, FL_ONGROUND ) ) { pev->flags -= FL_ONGROUND; } // jump into air for 0.8 (24/30) seconds // pev->velocity.z += (0.875 * flGravity) * 0.5; pev->velocity.z += (0.625 * flGravity) * 0.5; } break; case BSQUID_AE_THROW: { int iPitch; // squid throws its prey IF the prey is a client. float theDamage = 0; CBaseEntity *pHurt = CheckTraceHullAttack( 70, theDamage, 0 ); if ( pHurt ) { // croonchy bite sound iPitch = RANDOM_FLOAT( 90, 110 ); switch ( RANDOM_LONG( 0, 1 ) ) { case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite2.wav", 1, ATTN_NORM, 0, iPitch ); break; case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite3.wav", 1, ATTN_NORM, 0, iPitch ); break; } //pHurt->pev->punchangle.x = RANDOM_LONG(0,34) - 5; //pHurt->pev->punchangle.z = RANDOM_LONG(0,49) - 25; //pHurt->pev->punchangle.y = RANDOM_LONG(0,89) - 45; // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. UTIL_ScreenShake( pHurt->pev->origin, 25.0, 1.5, 0.7, 2 ); if ( pHurt->IsPlayer() ) { UTIL_MakeVectors( pev->angles ); pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 300 + gpGlobals->v_up * 300; } } } break; default: CBaseMonster::HandleAnimEvent( pEvent ); } }
//========================================================= // CheckRangeAttack2 - this checks the Grunt's grenade // attack. //========================================================= BOOL CFriend :: CheckRangeAttack2 ( float flDot, float flDist ) { // if the grunt isn't moving, it's ok to check. if ( m_flGroundSpeed != 0 ) { m_fThrowGrenade = FALSE; return m_fThrowGrenade; } // assume things haven't changed too much since last time if (gpGlobals->time < m_flNextGrenadeCheck ) { return m_fThrowGrenade; } if ( !FBitSet ( m_hEnemy->pev->flags, FL_ONGROUND ) && m_hEnemy->pev->waterlevel == 0 && m_vecEnemyLKP.z > pev->absmax.z ) { //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to // be grenaded. // don't throw grenades at anything that isn't on the ground! m_fThrowGrenade = FALSE; return m_fThrowGrenade; } Vector vecTarget; // find feet if (RANDOM_LONG(0,1)) { // magically know where they are vecTarget = Vector( m_hEnemy->pev->origin.x, m_hEnemy->pev->origin.y, m_hEnemy->pev->absmin.z ); } else { // toss it to where you last saw them vecTarget = m_vecEnemyLKP; } // vecTarget = m_vecEnemyLKP + (m_hEnemy->BodyTarget( pev->origin ) - m_hEnemy->pev->origin); // estimate position // vecTarget = vecTarget + m_hEnemy->pev->velocity * 2; if ( ( vecTarget - pev->origin ).Length2D() <= 256 ) { // crap, I don't want to blow myself up m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. m_fThrowGrenade = FALSE; return m_fThrowGrenade; } Vector vecToss = VecCheckToss( pev, GetGunPosition(), vecTarget, 0.5 ); if ( vecToss != g_vecZero ) { m_vecTossVelocity = vecToss; // throw a hand grenade m_fThrowGrenade = TRUE; // don't check again for a while. m_flNextGrenadeCheck = gpGlobals->time; // 1/3 second. } else { // don't throw m_fThrowGrenade = FALSE; // don't check again for a while. m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. } return m_fThrowGrenade; }