class PipeBombPlaceable extends PipeBombProjectile placeable; var(PipeBombProjectile) int TeamIndex; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire var(PipeBombProjectile) int EnemyCountdown; // Countdown to explosion after enemy detected var(PipeBombProjectile) bool bTriggerOnEnemy; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire var(PipeBombProjectile) bool bImmuneToDamage; // team which "placed" pipebomb. Use to avoid unnecessary friendly fire var(PipeBombProjectile) float MyDamage; var(PipeBombProjectile) float MyDamageRadius; var(PipeBombProjectile) float MyMomentumTransfer; static function PreloadAssets() { } static function bool UnloadAssets() { return true; } simulated function PostBeginPlay() { if ( Level.NetMode != NM_DedicatedServer) { BombLight = Spawn(class'PipebombLight',self); BombLight.SetBase(self); } // removed initial velocity Countdown = EnemyCountdown; Damage = MyDamage; DamageRadius = MyDamageRadius; MomentumTransfer = MyMomentumTransfer; PlacedTeam = TeamIndex; SetTimer(1.0, True); // this projectile is supposed to be placed in a map, so arm it immediately } function Timer() { local Pawn CheckPawn; local float ThreatLevel; if( !bHidden && !bTriggered ) { if( ArmingCountDown >= 0 ) { ArmingCountDown -= 0.1; if( ArmingCountDown <= 0 ) { SetTimer(1.0,True); } } else { // Check for enemies if( !bEnemyDetected ) { bAlwaysRelevant=false; PlaySound(BeepSound,,0.5,,50.0); if ( bTriggerOnEnemy ) { foreach VisibleCollidingActors( class 'Pawn', CheckPawn, DetectionRadius, Location ) { if( CheckPawn == Instigator || KFGameType(Level.Game).FriendlyFireScale > 0 && CheckPawn.PlayerReplicationInfo != none && CheckPawn.PlayerReplicationInfo.Team.TeamIndex == PlacedTeam ) { // Make the thing beep if someone on our team is within the detection radius // This gives them a chance to get out of the way ThreatLevel += 0.001; } else { if( (CheckPawn != Instigator) && (CheckPawn.Role == ROLE_Authority) && ((CheckPawn.PlayerReplicationInfo != none && CheckPawn.PlayerReplicationInfo.Team.TeamIndex != PlacedTeam) || CheckPawn.GetTeamNum() != PlacedTeam)) { if( KFMonster(CheckPawn) != none ) { ThreatLevel += KFMonster(CheckPawn).MotionDetectorThreat; if( ThreatLevel >= ThreatThreshhold ) { bEnemyDetected=true; SetTimer(0.15,True); } } else { bEnemyDetected=true; SetTimer(0.15,True); } } } } if( ThreatLevel >= ThreatThreshhold ) { bEnemyDetected=true; SetTimer(0.15,True); } else if( ThreatLevel > 0 ) { SetTimer(0.5,True); } else { SetTimer(1.0,True); } } else { SetTimer(1.0,True); } } // Play some fast beeps and blow up else { bAlwaysRelevant=true; Countdown--; if( CountDown > 0 ) { PlaySound(BeepSound,SLOT_Misc,2.0,,150.0); } else { Explode(Location, vector(Rotation)); } } } } else { Destroy(); } } simulated function Explode(vector HitLocation, vector HitNormal) { super.Explode(HitLocation, HitNormal); TriggerEvent(Event, self, Instigator); } function Trigger( actor Other, pawn EventInstigator ) { if ( !bHidden && !bTriggered ) { Instigator = EventInstigator; Explode(Location, vector(Rotation)); } } function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HitIndex) { if ( bImmuneToDamage ) return; Instigator = InstigatedBy; super.TakeDamage(Damage, InstigatedBy, Hitlocation, Momentum, damageType, HitIndex); } simulated function HurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) { local actor Victims; local float damageScale, dist; local vector dir; local int NumKilled; local KFMonster KFMonsterVictim; local Pawn P; local KFPawn KFP; local array CheckedPawns; local int i; local bool bAlreadyChecked; if ( bHurtEntry ) return; bHurtEntry = true; foreach CollidingActors (class 'Actor', Victims, DamageRadius, HitLocation) { // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag if( (Victims != self) && (Hurtwall != Victims) && (Victims.Role == ROLE_Authority) && !Victims.IsA('FluidSurfaceInfo') && ExtendedZCollision(Victims)==None ) { if( (Instigator==None || Instigator.Health<=0) && KFPawn(Victims)!=None ) Continue; dir = Victims.Location - HitLocation; dist = FMax(1,VSize(dir)); dir = dir/dist; damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); if ( Instigator == None || Instigator.Controller == None ) { Victims.SetDelayedDamageInstigatorController( InstigatorController ); } P = Pawn(Victims); if( P != none ) { for (i = 0; i < CheckedPawns.Length; i++) { if (CheckedPawns[i] == P) { bAlreadyChecked = true; break; } } if( bAlreadyChecked ) { bAlreadyChecked = false; P = none; continue; } KFMonsterVictim = KFMonster(Victims); if( KFMonsterVictim != none && KFMonsterVictim.Health <= 0 ) { KFMonsterVictim = none; } KFP = KFPawn(Victims); if( KFMonsterVictim != none ) { damageScale *= KFMonsterVictim.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity)); } else if( KFP != none ) { // don't hurt the same team if ( KFP.PlayerReplicationInfo != none && KFP.PlayerReplicationInfo.Team != none && KFP.PlayerReplicationInfo.Team.TeamIndex == PlacedTeam ) damageScale = 0; else { damageScale *= KFP.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity)); // Reduce damage to poeple so I can make the damage radius a bit bigger for killing zeds damageScale *= 0.5; } } CheckedPawns[CheckedPawns.Length] = P; if ( damageScale <= 0) { P = none; continue; } else { //Victims = P; P = none; } } Victims.TakeDamage(damageScale * DamageAmount,Instigator,Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,(damageScale * Momentum * dir),DamageType); if( Role == ROLE_Authority && KFMonsterVictim != none && KFMonsterVictim.Health <= 0 ) { NumKilled++; } if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0) { Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, InstigatorController, DamageType, Momentum, HitLocation); } } } bHurtEntry = false; } defaultproperties { TeamIndex=255 EnemyCountdown=5 bTriggerOnEnemy=True MyDamage=1500.000000 ArmingCountDown=0.000000 ExplodeSounds(0)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode01' ExplodeSounds(1)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode02' ExplodeSounds(2)=SoundGroup'Inf_Weapons.antitankmine.antitankmine_explode03' StaticMesh=StaticMesh'KF_pickups2_Trip.Supers.Pipebomb_Pickup' }