//------------------------------------------------------------------------------ // Purpose : Drop a window pane entity // Input : // Output : //------------------------------------------------------------------------------ void CBreakableSurface::DropPane(int nWidth, int nHeight) { // Check parameter range if (nWidth < 0 || nWidth >= m_nNumWide) return; if (nHeight < 0 || nHeight >= m_nNumHigh) return; if (!IsBroken(nWidth,nHeight)) { BreakPane(nWidth,nHeight); QAngle vAngles; VectorAngles(-1*m_vNormal,vAngles); Vector vWidthDir,vHeightDir; AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); Vector vBreakPos = m_vCorner + (nWidth*vWidthDir*m_flPanelWidth) + (nHeight*vHeightDir*m_flPanelHeight); CreateShards(vBreakPos, vAngles, vec3_origin, vec3_origin, WINDOW_PANEL_SIZE, WINDOW_PANEL_SIZE, WINDOW_SMALL_SHARD_SIZE); DamageSound(); CWindowPane *pPane = CWindowPane::CreateWindowPane(vBreakPos, vAngles); if (pPane) { pPane->SetLocalAngularVelocity( RandomAngle(-120,120) ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CAntlionGrub::CreateNugget( void ) { CGrubNugget *pNugget = (CGrubNugget *) CreateEntityByName( "item_grubnugget" ); if ( pNugget == NULL ) return; Vector vecOrigin; Vector vecForward; GetAttachment( LookupAttachment( "glow" ), vecOrigin, &vecForward ); // Find out what size to make this nugget! int nDenomination = GetNuggetDenomination(); pNugget->SetDenomination( nDenomination ); pNugget->SetAbsOrigin( vecOrigin ); pNugget->SetAbsAngles( RandomAngle( 0, 360 ) ); DispatchSpawn( pNugget ); IPhysicsObject *pPhys = pNugget->VPhysicsGetObject(); if ( pPhys ) { Vector vecForward; GetVectors( &vecForward, NULL, NULL ); Vector vecVelocity = RandomVector( -35.0f, 35.0f ) + ( vecForward * -RandomFloat( 50.0f, 75.0f ) ); AngularImpulse vecAngImpulse = RandomAngularImpulse( -100.0f, 100.0f ); pPhys->AddVelocity( &vecVelocity, &vecAngImpulse ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::SecondaryAttack( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; //Must have ammo if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } if( m_bInReload ) m_bInReload = false; // MUST call sound before removing a round from the clip of a CMachineGun BaseClass::WeaponSound( WPN_DOUBLE ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow; // Don't autoaim on grenade tosses AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); VectorScale( vecThrow, 1000.0f, vecThrow ); #ifndef CLIENT_DLL //Create the grenade CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); pGrenade->SetThrower( GetOwner() ); pGrenade->SetDamage( SMG1_GRENADE_DAMAGE ); pGrenade->SetDamageRadius( SMG1_GRENADE_RADIUS ); CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); // Register a muzzleflash for the AI. pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); #endif SendWeaponAnim( ACT_VM_SECONDARYATTACK ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // Decrease ammo pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); // Can shoot again immediately m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::SecondaryAttack( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; //Must have ammo if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } if( m_bInReload ) m_bInReload = false; // MUST call sound before removing a round from the clip of a CMachineGun BaseClass::WeaponSound( WPN_DOUBLE ); pPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAGS_NONE ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow; // Don't autoaim on grenade tosses AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); VectorScale( vecThrow, 1000.0f, vecThrow ); //Create the grenade QAngle angles; VectorAngles( vecThrow, angles ); CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, angles, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); pGrenade->SetThrower( GetOwner() ); pGrenade->SetDamage( sk_plr_dmg_smg1_grenade.GetFloat() ); SendWeaponAnim( ACT_VM_SECONDARYATTACK ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // Decrease ammo pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); // Can shoot again immediately m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; // Register a muzzleflash for the AI. pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &info - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void CNPC_CombineShot::Event_Killed(const CTakeDamageInfo &info) { // Don't bother if we've been told not to, or the player has a megaphyscannon if ( combine_shot_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) { BaseClass::Event_Killed( info ); return; } CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); if ( !pPlayer ) { CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ; if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() ) { pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() ); } } if ( pPlayer != NULL ) { CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules); // Attempt to drop health if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) { DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedHealth(); } if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false ) { // Attempt to drop a grenade if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) ) { DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedGrenade(); } } } BaseClass::Event_Killed( info ); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void HunterDamageCallback( const CEffectData &data ) { CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "HunterDamage" ); if ( pGlassEmitter == NULL ) return; pGlassEmitter->SetSortOrigin( data.m_vOrigin ); // Handle increased scale const float flMaxSpeed = 400.0f; const float flMinSpeed = 50.0f; float flAngularSpray = 1.0f; // Setup our collision information pGlassEmitter->m_ParticleCollision.Setup( data.m_vOrigin, &data.m_vNormal, flAngularSpray, flMinSpeed, flMaxSpeed, 600.0f, 0.2f ); Vector dir, end; int numFlecks = 32; Particle3D *pFleckParticle; Vector spawnOffset; //Dump out flecks for ( int i = 0; i < numFlecks; i++ ) { spawnOffset = data.m_vOrigin + RandomVector( -32.0f, 32.0f ); pFleckParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset ); if ( pFleckParticle == NULL ) break; pFleckParticle->m_flLifeRemaining = random->RandomFloat( 2.0f, 3.0f ); dir[0] = data.m_vNormal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[1] = data.m_vNormal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray ); dir[2] = data.m_vNormal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray ); pFleckParticle->m_uchSize = random->RandomInt( 3, 8 ); pFleckParticle->m_vecVelocity = dir * random->RandomFloat( flMinSpeed, flMaxSpeed); pFleckParticle->m_vAngles = RandomAngle( 0, 360 ); pFleckParticle->m_flAngSpeed = random->RandomFloat( -800, 800 ); unsigned char color = 255; pFleckParticle->m_uchFrontColor[0] = color; pFleckParticle->m_uchFrontColor[1] = color; pFleckParticle->m_uchFrontColor[2] = color; pFleckParticle->m_uchBackColor[0] = color * 0.25f; pFleckParticle->m_uchBackColor[1] = color * 0.25f; pFleckParticle->m_uchBackColor[2] = color * 0.25f; } }
bool CDirector_Manager::AddBoss(const Vector &vecPosition) { // No se ha podido acceder al Director. if ( !Director() ) return false; // No es posible crear un jefe aquí. if ( !CanMake(vecPosition) ) return false; // Creamos un jefe de la lista. const char *pBossName = GetBossClass(); CAI_BaseNPC *pBoss = (CAI_BaseNPC *)CreateEntityByName(pBossName); QAngle angles = RandomAngle(0, 360); angles.x = 0.0; angles.z = 0.0; pBoss->SetAbsAngles(angles); // Establecemos la ubicación de creación. pBoss->SetAbsOrigin(vecPosition); // Debe caer al suelo y desaparecer. pBoss->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); UTIL_DropToFloor(pBoss, MASK_SOLID); ConVarRef director_debug("director_debug"); // Marcamos al nodo afortunado. if ( director_debug.GetBool() ) NDebugOverlay::Box(vecPosition, -Vector(15, 15, 15), Vector(15, 15, 15), 223, 1, 1, 10, 3.0f); DispatchSpawn(pBoss); pBoss->SetOwnerEntity(Director()); DispatchActivate(pBoss); // ¡¡NO CAMBIAR!! pBoss->SetName(MAKE_STRING(BOSS_NAME)); // Al parecer se atoro en una pared. if ( !PostSpawn(pBoss) ) return false; DevMsg("[MANAGER] Se ha creado un JEFE. \r\n"); ++Director()->BossSpawned; Director()->BossPendient = false; Director()->ChildsKilled = 0; return true; }
//----------------------------------------------------------------------------- // Purpose: Create a resource chunk //----------------------------------------------------------------------------- CResourceChunk *CResourceChunk::Create( bool bProcessed, const Vector &vecOrigin, const Vector &vecVelocity ) { CResourceChunk *pChunk = (CResourceChunk*)CreateEntityByName("resource_chunk"); UTIL_SetOrigin( pChunk, vecOrigin ); pChunk->m_bIsProcessed = bProcessed; pChunk->m_bBeingCollected = false; pChunk->Spawn(); pChunk->SetAbsVelocity( vecVelocity ); pChunk->SetLocalAngularVelocity( RandomAngle( -100, 100 ) ); pChunk->SetLocalAngles( vec3_angle ); return pChunk; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::SecondaryAttack( void ) { // Only the player fires this way so we can cast CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); if ( pPlayer == NULL ) return; //Must have ammo if ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) { SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; return; } // MUST call sound before removing a round from the clip of a CMachineGun BaseClass::WeaponSound( DOUBLE ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); Vector vecThrow = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ) * 1000.0f; //Create the grenade CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer ); pGrenade->SetAbsVelocity( vecThrow ); pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY ); pGrenade->SetOwner( GetOwner() ); pGrenade->SetDamage( sk_plr_dmg_ar2_grenade.GetFloat() ); SendWeaponAnim( ACT_VM_SECONDARYATTACK ); // player "shoot" animation pPlayer->SetAnimation( PLAYER_ATTACK1 ); // Decrease ammo pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); // Can shoot again immediately m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; // Can blow up after a short delay (so have time to release mouse button) m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; // Register a muzzleflash for the AI. pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); }
// Атака зажигательными гранатами. Отключена. Для включения см. комментарий в ф-ции Spawn() // See the function and the and of npc_cremator.h void CNPC_Cremator::ThrowIncendiaryGrenade( void ) { Vector vecStart; GetAttachment( "anim_attachment_LH", vecStart ); Vector forward, up, right, vecThrow; GetVectors( &forward, &right, &up ); vecThrow = forward * 450 + up * 175 + right * random->RandomFloat(-15, 5); CGrenadeIncendiary *pIncendiary = (CGrenadeIncendiary*)Create( "grenade_incendiary", vecStart, vec3_angle, this ); pIncendiary->SetAbsVelocity( vecThrow ); pIncendiary->SetGravity( 1.5f ); pIncendiary->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); pIncendiary->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); }
///------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ CWindowPane* CWindowPane::CreateWindowPane( const Vector &vecOrigin, const QAngle &vecAngles ) { CWindowPane *pGlass = (CWindowPane*)CreateEntityByName( "window_pane" ); if ( !pGlass ) { Msg( "NULL Ent in CreateWindowPane!\n" ); return NULL; } if ( pGlass->edict() ) { pGlass->SetLocalOrigin( vecOrigin ); pGlass->SetLocalAngles( vecAngles ); pGlass->Spawn(); pGlass->SetTouch(&CWindowPane::PaneTouch); pGlass->SetLocalAngularVelocity( RandomAngle(-50,50) ); pGlass->m_nBody = random->RandomInt(0,2); } return pGlass; }
void Bot_FlipOut( CPluginBot *pBot, CBotCmd &cmd ) { if ( bot_flipout.GetInt() > 0 && !pBot->m_PlayerInfo->IsDead() ) { if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) { cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; } if ( bot_flipout.GetInt() >= 2 ) { QAngle angOffset = RandomAngle( -1, 1 ); pBot->m_LastAngles += angOffset; for ( int i = 0 ; i < 2; i++ ) { if ( fabs( pBot->m_LastAngles[ i ] - pBot->m_ForwardAngle[ i ] ) > 15.0f ) { if ( pBot->m_LastAngles[ i ] > pBot->m_ForwardAngle[ i ] ) { pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] + 15; } else { pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] - 15; } } } pBot->m_LastAngles[ 2 ] = 0; pBot->m_BotInterface->SetLocalAngles( pBot->m_LastAngles ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_GlassImpact( const Vector &pos, const Vector &normal ) { VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" ); pGlassEmitter->SetSortOrigin( pos ); Vector vecColor; engine->ComputeLighting( pos, NULL, true, vecColor ); // HACK: Blend a little toward white to match the materials... VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor ); float flShardSize = random->RandomFloat( 2.0f, 6.0f ); unsigned char color[3] = { 200, 200, 210 }; // --------------------- // Create glass shards // ---------------------- int numShards = random->RandomInt( 2, 4 ); for ( int i = 0; i < numShards; i++ ) { Particle3D *pParticle; pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos ); if ( pParticle ) { pParticle->m_flLifeRemaining = random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE); pParticle->m_vecVelocity[0] = ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_vecVelocity[1] = ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_vecVelocity[2] = ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED ); pParticle->m_uchSize = flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize); pParticle->m_vAngles = RandomAngle( 0, 360 ); pParticle->m_flAngSpeed = random->RandomFloat(-800,800); pParticle->m_uchFrontColor[0] = (byte)(color[0] * vecColor.x); pParticle->m_uchFrontColor[1] = (byte)(color[1] * vecColor.y); pParticle->m_uchFrontColor[2] = (byte)(color[2] * vecColor.z); pParticle->m_uchBackColor[0] = (byte)(color[0] * vecColor.x); pParticle->m_uchBackColor[1] = (byte)(color[1] * vecColor.y); pParticle->m_uchBackColor[2] = (byte)(color[2] * vecColor.z); } } pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING ); color[0] = 64; color[1] = 64; color[2] = 92; // --------------------------- // Dust // --------------------------- Vector dir; Vector offset = pos + ( normal * 2.0f ); float colorRamp; SimpleParticle newParticle; for ( int i = 0; i < 4; i++ ) { newParticle.m_Pos = offset; newParticle.m_flLifetime= 0.0f; newParticle.m_flDieTime = random->RandomFloat( 0.1f, 0.25f ); dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 1, 4 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 8; newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 16.0f )*(i+1); newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1); newParticle.m_uchStartAlpha = random->RandomInt( 128, 255 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -1, 1 ); colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] ); } // // Bullet hole capper // newParticle.m_Pos = offset; newParticle.m_flLifetime = 0.0f; newParticle.m_flDieTime = random->RandomFloat( 1.0f, 1.5f ); dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f ); dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f ); dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f ); newParticle.m_uchStartSize = random->RandomInt( 4, 8 ); newParticle.m_uchEndSize = newParticle.m_uchStartSize * 4.0f; newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f ); newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f ); newParticle.m_uchStartAlpha = random->RandomInt( 32, 64 ); newParticle.m_uchEndAlpha = 0; newParticle.m_flRoll = random->RandomFloat( 0, 360 ); newParticle.m_flRollDelta = random->RandomFloat( -2, 2 ); colorRamp = random->RandomFloat( 0.5f, 1.25f ); newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f; newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f; newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f; AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &info - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void CTDP_NPC_CombineS::Event_Killed( const CTakeDamageInfo &info ) { // Don't bother if we've been told not to, or the player has a megaphyscannon /* if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) { BaseClass::Event_Killed( info ); return; }*/ CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); if ( pPlayer != NULL ) { // Elites drop alt-fire ammo, so long as they weren't killed by dissolving. if( IsElite() ) { CBaseEntity *pItem = DropItem( "item_ammo_ar2_altfire", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); if ( pItem ) { IPhysicsObject *pObj = pItem->VPhysicsGetObject(); if ( pObj ) { Vector vel = RandomVector( -64.0f, 64.0f ); AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f ); vel[2] = 0.0f; pObj->AddVelocity( &vel, &angImp ); } if( info.GetDamageType() & DMG_DISSOLVE ) { CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem); if( pAnimating ) { pAnimating->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); } } } } //CTDPGameRules *pTDPGameRules = static_cast<CTDPGameRules *>(g_pGameRules); // Attempt to drop health /*if ( pTDPGameRules->NPC_ShouldDropHealth( pPlayer ) ) { DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pTDPGameRules->NPC_DroppedHealth(); }*/ // Attempt to drop a grenade /*if ( pTDPGameRules->NPC_ShouldDropGrenade( pPlayer ) ) { DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pTDPGameRules->NPC_DroppedGrenade(); }*/ } BaseClass::Event_Killed( info ); }
//----------------------------------------------------------------------------- // Purpose: Run this Bot's AI for one frame. //----------------------------------------------------------------------------- void Bot_Think( CBaseTFPlayer *pBot ) { // Hack to make Bots use Menus if ( pBot->m_pCurrentMenu == gMenus[MENU_CLASS] ) { int iClass = g_iNextBotClass; if ( iClass == -1 ) iClass = random->RandomInt( 1, TFCLASS_CLASS_COUNT ); pBot->m_pCurrentMenu->Input( pBot, iClass ); } else if ( bot_changeclass.GetInt() && bot_changeclass.GetInt() != pBot->PlayerClass() ) { pBot->m_pCurrentMenu = gMenus[MENU_CLASS]; pBot->m_pCurrentMenu->Input( pBot, bot_changeclass.GetInt() ); } // Make sure we stay being a bot pBot->AddFlag( FL_FAKECLIENT ); botdata_t *botdata = &g_BotData[ ENTINDEX( pBot->pev ) - 1 ]; QAngle vecViewAngles; float forwardmove = 0.0; float sidemove = botdata->sidemove; float upmove = 0.0; unsigned short buttons = 0; byte impulse = 0; float frametime = gpGlobals->frametime; vecViewAngles = pBot->GetLocalAngles(); // Create some random values if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) ) { trace_t trace; // Stop when shot if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) ) { if ( pBot->m_iHealth == 100 ) { forwardmove = 600 * ( botdata->backwards ? -1 : 1 ); if ( botdata->sidemove != 0.0f ) { forwardmove *= random->RandomFloat( 0.1, 1.0f ); } } else { forwardmove = 0; } } // Only turn if I haven't been hurt if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 ) { Vector vecEnd; Vector forward; QAngle angle; float angledelta = 15.0; int maxtries = (int)360.0/angledelta; if ( botdata->lastturntoright ) { angledelta = -angledelta; } angle = pBot->GetLocalAngles(); Vector vecSrc; while ( --maxtries >= 0 ) { AngleVectors( angle, &forward ); vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 ); vecEnd = vecSrc + forward * 10; UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, MASK_PLAYERSOLID, pBot, COLLISION_GROUP_NONE, &trace ); if ( trace.fraction == 1.0 ) { if ( gpGlobals->curtime < botdata->nextturntime ) { break; } } angle.y += angledelta; if ( angle.y > 180 ) angle.y -= 360; else if ( angle.y < -180 ) angle.y += 360; botdata->nextturntime = gpGlobals->curtime + 2.0; botdata->lastturntoright = random->RandomInt( 0, 1 ) == 0 ? true : false; botdata->forwardAngle = angle; botdata->lastAngles = angle; } if ( gpGlobals->curtime >= botdata->nextstrafetime ) { botdata->nextstrafetime = gpGlobals->curtime + 1.0f; if ( random->RandomInt( 0, 5 ) == 0 ) { botdata->sidemove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 ); } else { botdata->sidemove = 0; } sidemove = botdata->sidemove; if ( random->RandomInt( 0, 20 ) == 0 ) { botdata->backwards = true; } else { botdata->backwards = false; } } pBot->SetLocalAngles( angle ); vecViewAngles = angle; } // Is my team being forced to defend? if ( bot_defend.GetInt() == pBot->GetTeamNumber() ) { buttons |= IN_ATTACK2; } // If bots are being forced to fire a weapon, see if I have it else if ( bot_forcefireweapon.GetString() ) { CBaseCombatWeapon *pWeapon = pBot->Weapon_OwnsThisType( bot_forcefireweapon.GetString() ); if ( pWeapon ) { // Switch to it if we don't have it out CBaseCombatWeapon *pActiveWeapon = pBot->GetActiveWeapon(); // Is it a twohandedweapon? If so, get the left weapon CWeaponTwoHandedContainer *pContainer = dynamic_cast< CWeaponTwoHandedContainer * >( pActiveWeapon ); if ( pContainer ) { pActiveWeapon = pContainer->GetLeftWeapon(); } // Switch? if ( pActiveWeapon != pWeapon ) { pBot->Weapon_Switch( pWeapon ); } else { // Start firing // Some weapons require releases, so randomise firing if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) { buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; } } } } if ( bot_flipout.GetInt() ) { if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) { buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; } } } else { // Wait for Reinforcement wave if ( !pBot->IsAlive() ) { // Try hitting my buttons occasionally if ( random->RandomInt( 0, 100 ) > 80 ) { // Respawn the bot if ( random->RandomInt( 0, 1 ) == 0 ) { buttons |= IN_JUMP; } else { buttons = 0; } } } } if ( bot_flipout.GetInt() >= 2 ) { QAngle angOffset = RandomAngle( -1, 1 ); botdata->lastAngles += angOffset; for ( int i = 0 ; i < 2; i++ ) { if ( fabs( botdata->lastAngles[ i ] - botdata->forwardAngle[ i ] ) > 15.0f ) { if ( botdata->lastAngles[ i ] > botdata->forwardAngle[ i ] ) { botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] + 15; } else { botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] - 15; } } } botdata->lastAngles[ 2 ] = 0; pBot->SetLocalAngles( botdata->lastAngles ); } // Fix up the m_fEffects flags pBot->PostClientMessagesSent(); RunPlayerMove( pBot, pBot->GetLocalAngles(), forwardmove, sidemove, upmove, buttons, impulse, frametime ); }
bool CASW_Spawn_Manager::SpawnRandomShieldbug() { int iNumNodes = g_pBigAINet->NumNodes(); if ( iNumNodes < 6 ) return false; int nHull = HULL_WIDE_SHORT; CUtlVector<CASW_Open_Area*> aAreas; for ( int i = 0; i < 6; i++ ) { CAI_Node *pNode = NULL; int nTries = 0; while ( nTries < 5 && ( !pNode || pNode->GetType() != NODE_GROUND ) ) { pNode = g_pBigAINet->GetNode( RandomInt( 0, iNumNodes ) ); nTries++; } if ( pNode ) { CASW_Open_Area *pArea = FindNearbyOpenArea( pNode->GetOrigin(), HULL_MEDIUMBIG ); if ( pArea && pArea->m_nTotalLinks > 30 ) { // test if there's room to spawn a shieldbug at that spot if ( ValidSpawnPoint( pArea->m_pNode->GetPosition( nHull ), NAI_Hull::Mins( nHull ), NAI_Hull::Maxs( nHull ), true, false ) ) { aAreas.AddToTail( pArea ); } else { delete pArea; } } } // stop searching once we have 3 acceptable candidates if ( aAreas.Count() >= 3 ) break; } // find area with the highest connectivity CASW_Open_Area *pBestArea = NULL; for ( int i = 0; i < aAreas.Count(); i++ ) { CASW_Open_Area *pArea = aAreas[i]; if ( !pBestArea || pArea->m_nTotalLinks > pBestArea->m_nTotalLinks ) { pBestArea = pArea; } } if ( pBestArea ) { CBaseEntity *pAlien = SpawnAlienAt( "asw_shieldbug", pBestArea->m_pNode->GetPosition( nHull ), RandomAngle( 0, 360 ) ); IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>( pAlien ); if ( pSpawnable ) { pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL); } aAreas.PurgeAndDeleteElements(); return true; } aAreas.PurgeAndDeleteElements(); return false; }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CNPC_Bullsquid::HandleAnimEvent( animevent_t *pEvent ) { switch( pEvent->event ) { case BSQUID_AE_SPIT: { Vector vSpitPos; GetAttachment("mouth", vSpitPos); vSpitPos.z += 40.0f; Vector vTarget; // If our enemy is looking at us and far enough away, lead him if (HasCondition(COND_ENEMY_FACING_ME) && UTIL_DistApprox(GetAbsOrigin(), GetEnemy()->GetAbsOrigin()) > (40 * 12)) { UTIL_PredictedPosition(GetEnemy(), 0.5f, &vTarget); vTarget.z = GetEnemy()->GetAbsOrigin().z; } else { // Otherwise he can't see us and he won't be able to dodge vTarget = GetEnemy()->BodyTarget(vSpitPos, true); } vTarget[2] += random->RandomFloat(0.0f, 32.0f); // Try and spit at our target Vector vecToss; if (GetSpitVector(vSpitPos, vTarget, &vecToss) == false) { DevMsg("GetSpitVector( vSpitPos, vTarget, &vecToss ) == false\n"); // Now try where they were if (GetSpitVector(vSpitPos, m_vSavePosition, &vecToss) == false) { DevMsg("GetSpitVector( vSpitPos, m_vSavePosition, &vecToss ) == false\n"); // Failing that, just shoot with the old velocity we calculated initially! vecToss = m_vecSaveSpitVelocity; } } // Find what our vertical theta is to estimate the time we'll impact the ground Vector vecToTarget = (vTarget - vSpitPos); VectorNormalize(vecToTarget); float flVelocity = VectorNormalize(vecToss); float flCosTheta = DotProduct(vecToTarget, vecToss); float flTime = (vSpitPos - vTarget).Length2D() / (flVelocity * flCosTheta); // Emit a sound where this is going to hit so that targets get a chance to act correctly CSoundEnt::InsertSound(SOUND_DANGER, vTarget, (15 * 12), flTime, this); // Don't fire again until this volley would have hit the ground (with some lag behind it) SetNextAttack(gpGlobals->curtime + flTime + random->RandomFloat(0.5f, 2.0f)); for (int i = 0; i < 6; i++) { CGrenadeSpit *pGrenade = (CGrenadeSpit*)CreateEntityByName("grenade_spit"); pGrenade->SetAbsOrigin(vSpitPos); pGrenade->SetAbsAngles(vec3_angle); DispatchSpawn(pGrenade); pGrenade->SetThrower(this); pGrenade->SetOwnerEntity(this); if (i == 0) { pGrenade->SetSpitSize(SPIT_LARGE); pGrenade->SetAbsVelocity(vecToss * flVelocity); } else { pGrenade->SetAbsVelocity((vecToss + RandomVector(-0.035f, 0.035f)) * flVelocity); pGrenade->SetSpitSize(random->RandomInt(SPIT_SMALL, SPIT_MEDIUM)); } // Tumble through the air pGrenade->SetLocalAngularVelocity(QAngle(random->RandomFloat(-250, -500), random->RandomFloat(-250, -500), random->RandomFloat(-250, -500))); } for (int i = 0; i < 8; i++) { DispatchParticleEffect("blood_impact_yellow_01", vSpitPos + RandomVector(-12.0f, 12.0f), RandomAngle(0, 360)); } EmitSound("NPC_Antlion.PoisonShoot"); } break; case BSQUID_AE_BITE: { // SOUND HERE! CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_bite.GetFloat(), DMG_SLASH ); if ( pHurt ) { Vector forward, up; AngleVectors( GetAbsAngles(), &forward, NULL, &up ); pHurt->ApplyAbsVelocityImpulse( 100 * (up-forward) ); pHurt->SetGroundEntity( NULL ); } } break; case BSQUID_AE_WHIP_SND: { EmitSound( "NPC_Bullsquid.TailWhip" ); break; } /* case BSQUID_AE_TAILWHIP: { CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_whip.GetFloat(), DMG_SLASH | DMG_ALWAYSGIB ); if ( pHurt ) { Vector right, up; AngleVectors( GetAbsAngles(), NULL, &right, &up ); if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) pHurt->ViewPunch( QAngle( 20, 0, -20 ) ); pHurt->ApplyAbsVelocityImpulse( 100 * (up+2*right) ); } } break; */ case BSQUID_AE_BLINK: { // close eye. m_nSkin = 1; } break; case BSQUID_AE_HOP: { float flGravity = GetCurrentGravity(); // throw the squid up into the air on this frame. if ( GetFlags() & FL_ONGROUND ) { SetGroundEntity( NULL ); } // jump 40 inches into the air Vector vecVel = GetAbsVelocity(); vecVel.z += sqrt( flGravity * 2.0 * 40 ); SetAbsVelocity( vecVel ); } break; case BSQUID_AE_THROW: { // squid throws its prey IF the prey is a client. CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), 0, 0 ); if ( pHurt ) { pHurt->ViewPunch( QAngle(20,0,-20) ); // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. UTIL_ScreenShake( pHurt->GetAbsOrigin(), 25.0, 1.5, 0.7, 2, SHAKE_START ); // If the player, throw him around if ( pHurt->IsPlayer()) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pHurt->ApplyAbsVelocityImpulse( forward * 300 + up * 300 ); } // If not the player see if has bullsquid throw interatcion else { CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pHurt ); if (pVictim) { if ( pVictim->DispatchInteraction( g_interactionBullsquidThrow, NULL, this ) ) { Vector forward, up; AngleVectors( GetLocalAngles(), &forward, NULL, &up ); pVictim->ApplyAbsVelocityImpulse( forward * 300 + up * 250 ); } } } } } break; default: BaseClass::HandleAnimEvent( pEvent ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : &info - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void CNPC_CombineAce::Event_Killed( const CTakeDamageInfo &info ) { if (!(g_Language.GetInt() == LANGUAGE_GERMAN || UTIL_IsLowViolence()) && info.GetDamageType() & (DMG_BLAST | DMG_CRUSH) && !(info.GetDamageType() & (DMG_DISSOLVE)) && !PlayerHasMegaPhysCannon()) { Vector vecDamageDir = info.GetDamageForce(); SpawnBlood(GetAbsOrigin(), g_vecAttackDir, BloodColor(), info.GetDamage()); DispatchParticleEffect("headshotspray", GetAbsOrigin(), GetAbsAngles(), this); EmitSound("Gore.Headshot"); float flFadeTime = 25.0; CGib::SpawnSpecificGibs(this, 1, 750, 1500, "models/gibs/soldier_ace_head.mdl", flFadeTime); Vector vecRagForce; vecRagForce.x = random->RandomFloat(-400, 400); vecRagForce.y = random->RandomFloat(-400, 400); vecRagForce.z = random->RandomFloat(0, 250); Vector vecRagDmgForce = (vecRagForce + vecDamageDir); CBaseEntity *pLeftArmGib = CreateRagGib("models/gibs/soldier_ace_left_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pLeftArmGib) { color32 color = pLeftArmGib->GetRenderColor(); pLeftArmGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pRightArmGib = CreateRagGib("models/gibs/soldier_ace_right_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pRightArmGib) { color32 color = pRightArmGib->GetRenderColor(); pRightArmGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pTorsoGib = CreateRagGib("models/gibs/soldier_ace_torso.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pTorsoGib) { color32 color = pTorsoGib->GetRenderColor(); pTorsoGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pPelvisGib = CreateRagGib("models/gibs/soldier_ace_pelvis.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pPelvisGib) { color32 color = pPelvisGib->GetRenderColor(); pPelvisGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pLeftLegGib = CreateRagGib("models/gibs/soldier_ace_left_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pLeftLegGib) { color32 color = pLeftLegGib->GetRenderColor(); pLeftLegGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pRightLegGib = CreateRagGib("models/gibs/soldier_ace_right_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pRightLegGib) { color32 color = pRightLegGib->GetRenderColor(); pRightLegGib->SetRenderColor(color.r, color.g, color.b, color.a); } //now add smaller gibs. CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p3.mdl", flFadeTime); CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p4.mdl", flFadeTime); if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0) { pArmor->Remove(); DropItem("item_shield", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360)); } Vector forceVector = CalcDamageForceVector(info); // Drop any weapon that I own if (VPhysicsGetObject()) { Vector weaponForce = forceVector * VPhysicsGetObject()->GetInvMass(); Weapon_Drop(m_hActiveWeapon, NULL, &weaponForce); } else { Weapon_Drop(m_hActiveWeapon); } if (info.GetAttacker()->IsPlayer()) { ((CSingleplayRules*)GameRules())->NPCKilled(this, info); } UTIL_Remove(this); SetThink(NULL); return; } // Don't bother if we've been told not to, or the player has a megaphyscannon if ( combine_ace_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) { BaseClass::Event_Killed( info ); return; } SetEyeState(ACE_EYE_DEAD); if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0) { pArmor->Remove(); } CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); if ( !pPlayer ) { CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ; if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() ) { pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() ); } } if ( pPlayer != NULL ) { // Elites drop alt-fire ammo, so long as they weren't killed by dissolving. #ifdef HL2_EPISODIC if (HasSpawnFlags(SF_COMBINE_NO_AR2DROP) == false) #endif { if (FClassnameIs(GetActiveWeapon(), "weapon_ar2")) { CBaseEntity *pItem = DropItem("item_ammo_ar2_altfire", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360)); if (pItem) { IPhysicsObject *pObj = pItem->VPhysicsGetObject(); if (pObj) { Vector vel = RandomVector(-64.0f, 64.0f); AngularImpulse angImp = RandomAngularImpulse(-300.0f, 300.0f); vel[2] = 0.0f; pObj->AddVelocity(&vel, &angImp); } if (info.GetDamageType() & DMG_DISSOLVE) { CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem); if (pAnimating) { pAnimating->Dissolve(NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL); } } else { WeaponManager_AddManaged(pItem); } } } else if (FClassnameIs(GetActiveWeapon(), "weapon_smg1")) { CBaseEntity *pItem = DropItem("item_ammo_smg1_grenade", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360)); if (pItem) { IPhysicsObject *pObj = pItem->VPhysicsGetObject(); if (pObj) { Vector vel = RandomVector(-64.0f, 64.0f); AngularImpulse angImp = RandomAngularImpulse(-300.0f, 300.0f); vel[2] = 0.0f; pObj->AddVelocity(&vel, &angImp); } if (info.GetDamageType() & DMG_DISSOLVE) { CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem); if (pAnimating) { pAnimating->Dissolve(NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL); } } else { WeaponManager_AddManaged(pItem); } } } } CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules); // Attempt to drop health if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) { DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedHealth(); } if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0) { DropItem("item_shield", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360)); } } BaseClass::Event_Killed( info ); }
Vector3 RandomMover::VectorChange(void) { return AngleToVector(RandomAngle(), Random::Number(mMoveSpeed / 16, mMoveSpeed)); }
bool CASW_Spawn_Manager::SpawnRandomParasitePack( int nParasites ) { int iNumNodes = g_pBigAINet->NumNodes(); if ( iNumNodes < 6 ) return false; int nHull = HULL_TINY; CUtlVector<CASW_Open_Area*> aAreas; for ( int i = 0; i < 6; i++ ) { CAI_Node *pNode = NULL; int nTries = 0; while ( nTries < 5 && ( !pNode || pNode->GetType() != NODE_GROUND ) ) { pNode = g_pBigAINet->GetNode( RandomInt( 0, iNumNodes ) ); nTries++; } if ( pNode ) { CASW_Open_Area *pArea = FindNearbyOpenArea( pNode->GetOrigin(), HULL_MEDIUMBIG ); if ( pArea && pArea->m_nTotalLinks > 30 ) { // test if there's room to spawn a shieldbug at that spot if ( ValidSpawnPoint( pArea->m_pNode->GetPosition( nHull ), NAI_Hull::Mins( nHull ), NAI_Hull::Maxs( nHull ), true, false ) ) { aAreas.AddToTail( pArea ); } else { delete pArea; } } } // stop searching once we have 3 acceptable candidates if ( aAreas.Count() >= 3 ) break; } // find area with the highest connectivity CASW_Open_Area *pBestArea = NULL; for ( int i = 0; i < aAreas.Count(); i++ ) { CASW_Open_Area *pArea = aAreas[i]; if ( !pBestArea || pArea->m_nTotalLinks > pBestArea->m_nTotalLinks ) { pBestArea = pArea; } } if ( pBestArea ) { for ( int i = 0; i < nParasites; i++ ) { // raise the position by 12 units, a workaround for parasites // falling through displacements CBaseEntity *pAlien = SpawnAlienAt( "asw_parasite", pBestArea->m_pNode->GetPosition( nHull ) + Vector(0.f, 0.f, 12.f), RandomAngle( 0, 360 ) ); IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>( pAlien ); if ( pSpawnable ) { pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL); } if ( asw_director_debug.GetBool() && pAlien ) { Msg( "Spawned parasite at %f %f %f\n", pAlien->GetAbsOrigin() ); NDebugOverlay::Cross3D( pAlien->GetAbsOrigin(), 8.0f, 255, 0, 0, true, 20.0f ); } } aAreas.PurgeAndDeleteElements(); return true; } aAreas.PurgeAndDeleteElements(); return false; }
//========================================================= // Crea un hijo en la ubicación especificada. //========================================================= bool CDirector_Manager::AddChild(const Vector &vecPosition, int flag) { // No se ha podido acceder al Director. if ( !Director() ) return false; // No es posible crear un hijo aquí. if ( !CanMake(vecPosition) ) return false; // Creamos un hijo de la lista. const char *pChildName = GetChildClass(); CAI_BaseNPC *pChild = (CAI_BaseNPC *)CreateEntityByName(pChildName); QAngle angles = RandomAngle(0, 360); angles.x = 0.0; angles.z = 0.0; pChild->SetAbsAngles(angles); // Establecemos la ubicación de creación. pChild->SetAbsOrigin(vecPosition); // Debe caer al suelo y desaparecer. pChild->AddSpawnFlags(SF_NPC_FALL_TO_GROUND); pChild->AddSpawnFlags(SF_NPC_FADE_CORPSE); UTIL_DropToFloor(pChild, MASK_SOLID); ConVarRef director_debug("director_debug"); DispatchSpawn(pChild); pChild->SetOwnerEntity(Director()); DispatchActivate(pChild); // ¡¡NO CAMBIAR!! pChild->SetName(MAKE_STRING(CHILD_NAME)); // Sin colisiones. if ( flag == SPAWN_NO_COLLISION || flag == SPAWN_NO_COLLISION_AND_POWERFUL ) { pChild->SetCollisionGroup(COLLISION_GROUP_SPECIAL_NPC); Vector vecOriginRadius; if ( Director()->Status == PANIC && RandomInt(0, 4) == 2 ) pChild->SetCollisionGroup(COLLISION_GROUP_NPC); // Intentamos crearlo en un radio de 100 if ( CAI_BaseNPC::FindSpotForNPCInRadius(&vecOriginRadius, vecPosition, pChild, 150, false) ) { // Evitamos que se mueva por debajo del suelo. vecOriginRadius.z = vecPosition.z; // Movemos hacia esta ubicación. pChild->SetAbsOrigin(vecOriginRadius); // Marcamos al nodo afortunado. (Naranja) if ( director_debug.GetBool() ) NDebugOverlay::Box(vecOriginRadius, -Vector(10, 10, 10), Vector(10, 10, 10), 255, 128, 0, 10, 20.0f); } } // Poderoso. if ( flag == SPAWN_POWERFUL || flag == SPAWN_NO_COLLISION_AND_POWERFUL ) { int moreHealth = 3; // Normal: 5 más de salud. if ( InGameRules()->IsSkillLevel(SKILL_MEDIUM) ) moreHealth = 5; // Dificil: 8 más de salud. if ( InGameRules()->IsSkillLevel(SKILL_HARD) ) moreHealth = 8; // Más rápido. pChild->SetAddAccel(40); // Establecemos la nueva salud. pChild->SetMaxHealth(pChild->GetMaxHealth() + moreHealth); pChild->SetHealth(pChild->GetMaxHealth()); // Seleccionamos al jugador más cercano. float flDistance = 0.0f; CIN_Player *pPlayer = UTIL_GetNearestInPlayer(pChild->GetAbsOrigin(), flDistance); if ( pPlayer ) { // Le decimos que su nuevo enemigo es el jugador y le damos la ubicación de este. pChild->SetEnemy(pPlayer); pChild->UpdateEnemyMemory(pPlayer, pPlayer->GetAbsOrigin()); } } // Al parecer se atoro en una pared. if ( !PostSpawn(pChild) ) { // Marcamos al nodo desafortunado. (Negro) if ( director_debug.GetBool() ) NDebugOverlay::Box(vecPosition, -Vector(10, 10, 10), Vector(10, 10, 10), 0, 0, 0, 10, 3.0f); return false; } // Marcamos al nodo afortunado. (Rojo) if ( director_debug.GetBool() ) NDebugOverlay::Box(vecPosition, -Vector(10, 10, 10), Vector(10, 10, 10), 223, 1, 1, 10, 3.0f); DevMsg("[MANAGER] Se ha creado <%s> (faltan %i) \r\n", pChildName, Director()->SpawnQueue); ++Director()->ChildsSpawned; return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponSMG1::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) { switch( pEvent->event ) { case EVENT_WEAPON_SMG1: { Vector vecShootOrigin, vecShootDir; QAngle angDiscard; // Support old style attachment point firing if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard))) { vecShootOrigin = pOperator->Weapon_ShootPosition(); } CAI_BaseNPC *npc = pOperator->MyNPCPointer(); ASSERT( npc != NULL ); vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); } break; case EVENT_WEAPON_AR2_ALTFIRE: { CAI_BaseNPC *npc = pOperator->MyNPCPointer(); Vector vecShootOrigin, vecShootDir; vecShootOrigin = pOperator->Weapon_ShootPosition(); //vecShootDir = npc->GetShootEnemyDir( vecShootOrigin ); //Checks if it can fire the grenade WeaponRangeAttack2Condition(); Vector vecThrow = m_vecTossVelocity; //If on the rare case the vector is 0 0 0, cancel for avoid launching the grenade without speed //This should be on WeaponRangeAttack2Condition(), but for some unknown reason return CASE_NONE //doesn't stop the launch if (vecThrow == Vector(0, 0, 0)) { break; } CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create("grenade_ar2", vecShootOrigin, vec3_angle, npc); pGrenade->SetAbsVelocity(vecThrow); pGrenade->SetLocalAngularVelocity(RandomAngle(-400, 400)); //tumble in air pGrenade->SetMoveType(MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE); pGrenade->SetThrower(GetOwner()); pGrenade->SetGravity(0.5); // lower gravity since grenade is aerodynamic and engine doesn't know it. pGrenade->SetDamage(sk_plr_dmg_smg1_grenade.GetFloat()); if (g_pGameRules->IsSkillLevel(SKILL_HARD)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(2,3); } else if (g_pGameRules->IsSkillLevel(SKILL_VERYHARD)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(1.5,2); } else if (g_pGameRules->IsSkillLevel(SKILL_NIGHTMARE)) { m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(1,1.5); } else { m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown. } m_iClip2--; } break; default: BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); break; } }
//----------------------------------------------------------------------------- // Purpose: // Input : &info - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void CNPC_CombineS::Event_Killed( const CTakeDamageInfo &info ) { // Don't bother if we've been told not to, or the player has a megaphyscannon if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) { BaseClass::Event_Killed( info ); return; } CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); if ( !pPlayer ) { CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ; if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() ) { pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() ); } } if ( pPlayer != NULL ) { // Elites drop alt-fire ammo, so long as they weren't killed by dissolving. if( IsElite() ) { #ifdef HL2_EPISODIC if ( HasSpawnFlags( SF_COMBINE_NO_AR2DROP ) == false ) #endif { CBaseEntity *pItem = DropItem( "item_ammo_ar2_altfire", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); if ( pItem ) { IPhysicsObject *pObj = pItem->VPhysicsGetObject(); if ( pObj ) { Vector vel = RandomVector( -64.0f, 64.0f ); AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f ); vel[2] = 0.0f; pObj->AddVelocity( &vel, &angImp ); } if( info.GetDamageType() & DMG_DISSOLVE ) { CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem); if( pAnimating ) { pAnimating->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); } } else { WeaponManager_AddManaged( pItem ); } } } } CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules); // Attempt to drop health if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) { DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedHealth(); } if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false ) { // Attempt to drop a grenade if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) ) { DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedGrenade(); } } } BaseClass::Event_Killed( info ); }
void CASW_Spawn_Manager::PrespawnAlienAtRandomNode(const char *szAlienClass, const int iNumAliens, const int iHull, const Vector &playerStartPos, const int iNumNodes) { for (int i = 0; i < iNumAliens; ++i) { CAI_Node *pNode = NULL; for (int k = 0; k < 30; ++k) { int node_id = RandomInt(0, iNumNodes - 1); pNode = g_pBigAINet->GetNode(node_id); if (!pNode || pNode->GetType() != NODE_GROUND) continue; else if (pNode->GetOrigin().DistToSqr(playerStartPos) < 1000 * 1000) { continue; } if (ValidSpawnPoint(pNode->GetPosition(iHull), NAI_Hull::Mins(iHull), NAI_Hull::Maxs(iHull), true, false)) { // Raise the end position a little up off the floor, place the npc and drop him down CBaseEntity *pAlien = SpawnAlienAt(szAlienClass, pNode->GetPosition(iHull) + Vector(0.f, 0.f, 12.f), RandomAngle(0, 360)); IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pAlien); if (pSpawnable) { pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL); } if (asw_director_debug.GetBool() && pAlien) { Msg("Spawned alien at %f %f %f\n", pAlien->GetAbsOrigin()); NDebugOverlay::Cross3D(pAlien->GetAbsOrigin(), 8.0f, 255, 0, 0, true, 20.0f); } if (pAlien) break; } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : &info - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- void CNPC_CombineS::Event_Killed( const CTakeDamageInfo &info ) { if (!(g_Language.GetInt() == LANGUAGE_GERMAN || UTIL_IsLowViolence()) && info.GetDamageType() & (DMG_BLAST | DMG_CRUSH) && !(info.GetDamageType() & (DMG_DISSOLVE)) && !PlayerHasMegaPhysCannon()) { Vector vecDamageDir = info.GetDamageForce(); SpawnBlood(GetAbsOrigin(), g_vecAttackDir, BloodColor(), info.GetDamage()); DispatchParticleEffect("headshotspray", GetAbsOrigin(), GetAbsAngles(), this); EmitSound("Gore.Headshot"); float flFadeTime = 25.0; CGib::SpawnSpecificGibs(this, 1, 750, 1500, "models/gibs/soldier_head.mdl", flFadeTime); Vector vecRagForce; vecRagForce.x = random->RandomFloat(-400, 400); vecRagForce.y = random->RandomFloat(-400, 400); vecRagForce.z = random->RandomFloat(0, 250); Vector vecRagDmgForce = (vecRagForce + vecDamageDir); CBaseEntity *pLeftArmGib = CreateRagGib("models/gibs/soldier_left_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pLeftArmGib) { color32 color = pLeftArmGib->GetRenderColor(); pLeftArmGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pRightArmGib = CreateRagGib("models/gibs/soldier_right_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pRightArmGib) { color32 color = pRightArmGib->GetRenderColor(); pRightArmGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pTorsoGib = CreateRagGib("models/gibs/soldier_torso.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pTorsoGib) { color32 color = pTorsoGib->GetRenderColor(); pTorsoGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pPelvisGib = CreateRagGib("models/gibs/soldier_pelvis.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pPelvisGib) { color32 color = pPelvisGib->GetRenderColor(); pPelvisGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pLeftLegGib = CreateRagGib("models/gibs/soldier_left_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pLeftLegGib) { color32 color = pLeftLegGib->GetRenderColor(); pLeftLegGib->SetRenderColor(color.r, color.g, color.b, color.a); } CBaseEntity *pRightLegGib = CreateRagGib("models/gibs/soldier_right_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire()); if (pRightLegGib) { color32 color = pRightLegGib->GetRenderColor(); pRightLegGib->SetRenderColor(color.r, color.g, color.b, color.a); } //now add smaller gibs. CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p3.mdl", flFadeTime); CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p4.mdl", flFadeTime); Vector forceVector = CalcDamageForceVector(info); // Drop any weapon that I own if (VPhysicsGetObject()) { Vector weaponForce = forceVector * VPhysicsGetObject()->GetInvMass(); Weapon_Drop(m_hActiveWeapon, NULL, &weaponForce); } else { Weapon_Drop(m_hActiveWeapon); } if (info.GetAttacker()->IsPlayer()) { ((CSingleplayRules*)GameRules())->NPCKilled(this, info); } UTIL_Remove(this); SetThink(NULL); return; } // Don't bother if we've been told not to, or the player has a megaphyscannon if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) { BaseClass::Event_Killed( info ); return; } CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); if ( !pPlayer ) { CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ; if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() ) { pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() ); } } if ( pPlayer != NULL ) { CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules); // Attempt to drop health if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) { DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedHealth(); } if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false ) { // Attempt to drop a grenade if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) ) { DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); pHL2GameRules->NPC_DroppedGrenade(); } } } BaseClass::Event_Killed( info ); }