class stub_Nade extends Nade;


function PostNetBeginPlay()
{
  SetTimer(ExplodeTimer, false);
}


simulated function PostNetReceive()
{
  if (bHidden && !bDisintegrated)
  {
    Disintegrate(Location, vect(0,0,1));
  }
}


function Timer()
{
  if (!bHidden)
  {
    Explode(Location, vect(0,0,1));
  }
  else
  {
    Destroy();
  }
}


// Shoot nades in mid-air
// Alex
function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
{
  if (Monster(instigatedBy) != none || instigatedBy == Instigator)
  {
    if (damageType == class'SirenScreamDamage')
    {
      Disintegrate(HitLocation, vect(0,0,1));
    }
    else
    {
      Explode(HitLocation, vect(0,0,1));
    }
  }
}


// cut-n-paste to remove grenade smoke trail
simulated function PostBeginPlay()
{
  if (Role == ROLE_Authority)
  {
    Velocity = Speed * Vector(Rotation);
    RandSpin(25000);
    bCanHitOwner = false;
    if (Instigator.HeadVolume.bWaterVolume)
    {
      bHitWater = true;
      Velocity = 0.6*Velocity;
    }
  }
}


simulated function Explode(vector HitLocation, vector HitNormal)
{
  local PlayerController  LocalPlayer;
  local Projectile P;
  local byte i;

  bHasExploded = True;
  BlowUp(HitLocation);
  PlaySound(ExplodeSounds[rand(ExplodeSounds.length)],,2.0);

  // Shrapnel
  for (i=Rand(6); i<10; i++)
  {
    P = Spawn(ShrapnelClass,,,,RotRand(True));
    if (P != none)
      P.RemoteRole = ROLE_None;
  }
  if (EffectIsRelevant(Location,false))
  {
    Spawn(Class'KFmod.KFNadeExplosion',,, HitLocation, rotator(vect(0,0,1)));
    Spawn(ExplosionDecal,self,,HitLocation, rotator(-HitNormal));
  }

  // Shake nearby players screens
  LocalPlayer = Level.GetLocalPlayerController();
  if ( (LocalPlayer != None) && (VSize(Location - LocalPlayer.ViewTarget.Location) < (DamageRadius * 1.5)) )
    LocalPlayer.ShakeView(RotMag, RotRate, RotTime, OffsetMag, OffsetRate, OffsetTime);

  Destroy();
}


// Make the projectile distintegrate, instead of explode
simulated function Disintegrate(vector HitLocation, vector HitNormal)
{
  bDisintegrated = true;
    bHidden = true;

    if( Role == ROLE_Authority )
    {
       SetTimer(0.1, false);
       NetUpdateTime = Level.TimeSeconds - 1;
    }

    PlaySound(DisintegrateSound,,2.0);

    if ( EffectIsRelevant(Location,false) )
    {
        Spawn(Class'KFMod.SirenNadeDeflect',,, HitLocation, rotator(vect(0,0,1)));
    }
}

simulated function Destroyed()
{
    if ( Trail != None )
        Trail.mRegen = false; // stop the emitter from regenerating
    if( !bHasExploded && !bHidden )
        Explode(Location,vect(0,0,1));
    if( bHidden && !bDisintegrated )
        Disintegrate(Location,vect(0,0,1));
    if ( Fear != None )
        Fear.Destroy();
    Super.Destroyed();
}

simulated function ProcessTouch( actor Other, vector HitLocation )
{
//    local vector Other2dLocation, TwoDLocation;
//    local float DistToOtherCenter;
//    local bool bHitIsCloseToCenter;

    if( KFBulletWhipAttachment(Other) != none )
    {
        return;
    }

    // Don't allow hits on poeple on the same team
    if( KFHumanPawn(Other) != none && Instigator != none
        && KFHumanPawn(Other).PlayerReplicationInfo.Team.TeamIndex == Instigator.PlayerReplicationInfo.Team.TeamIndex )
    {
        return;
    }

    // more realistic interactions with karma objects.
    if (Other.IsA('NetKActor'))
        KAddImpulse(Velocity,HitLocation,);

     // Failed attempt at making nades only stop if they are close to the center of the
     // collision. When I have more time, try and do a closest point along the ray test - Ramm
//    if ( !Other.bWorldGeometry && Other != Instigator )
//    {
//        Other2dLocation = Other.Location;
//        Other2dLocation.Z = 0;
//        TwoDLocation = Location;
//        TwoDLocation.Z = 0;
//        DistToOtherCenter = VSize(Other2dLocation - TwoDLocation);
//        bHitIsCloseToCenter = DistToOtherCenter < Other.CollisionRadius/2.0;
//        log("DistToOtherCenter = "$DistToOtherCenter$" Other.CollisionRadius/2.0 "$Other.CollisionRadius/2.0 );
//    }

    // Stop the grenade in its tracks if it hits an enemy.
    if ( !Other.bWorldGeometry && ((Other != Instigator && Other.Base != Instigator /*&& bHitIsCloseToCenter*/ )|| bCanHitOwner) )
        Velocity = Vect(0,0,0);
}

/* HurtRadius()
 Hurt locally authoritative actors within the radius.
*/
simulated function HurtRadius( float DamageAmount, float DamageRadius, class<DamageType> 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<Pawn> 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 )
                {
                    damageScale *= KFP.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity));
                }

                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);
            }
        }
    }

    if( Role == ROLE_Authority )
    {
        if ( NumKilled >= 8 && Instigator != none && Instigator.PlayerReplicationInfo != none &&
             KFSteamStatsAndAchievements(Instigator.PlayerReplicationInfo.SteamStatsAndAchievements) != none )
        {
            KFSteamStatsAndAchievements(Instigator.PlayerReplicationInfo.SteamStatsAndAchievements).Killed8ZedsWithGrenade();
        }

        if ( NumKilled >= 4 )
        {
            KFGameType(Level.Game).DramaticEvent(0.05);
        }
        else if ( NumKilled >= 2 )
        {
            KFGameType(Level.Game).DramaticEvent(0.03);
        }
    }

    bHurtEntry = false;
}

// Overridden to tweak the handling of the impact sound
simulated function HitWall( vector HitNormal, actor Wall )
{
    local Vector VNorm;
    local PlayerController PC;

    if ( (Pawn(Wall) != None) || (GameObjective(Wall) != None) )
    {
        Explode(Location, HitNormal);
        return;
    }

    if (!bTimerSet)
    {
        SetTimer(ExplodeTimer, false);
        bTimerSet = true;
    }

    // Reflect off Wall w/damping
    VNorm = (Velocity dot HitNormal) * HitNormal;
    Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel;

    RandSpin(100000);
    DesiredRotation.Roll = 0;
    RotationRate.Roll = 0;
    Speed = VSize(Velocity);

    if ( Speed < 20 )
    {
        bBounce = False;
        PrePivot.Z = -1.5;
            SetPhysics(PHYS_None);
        DesiredRotation = Rotation;
        DesiredRotation.Roll = 0;
        DesiredRotation.Pitch = 0;
        SetRotation(DesiredRotation);

        if( Fear == none )
        {
            Fear = Spawn(class'AvoidMarker');
            Fear.SetCollisionSize(DamageRadius,DamageRadius);
            Fear.StartleBots();
        }

        if ( Trail != None )
            Trail.mRegen = false; // stop the emitter from regenerating
    }
    else
    {
        if ( (Level.NetMode != NM_DedicatedServer) && (Speed > 50) )
            PlaySound(ImpactSound, SLOT_Misc );
        else
        {
            bFixedRotationDir = false;
            bRotateToDesired = true;
            DesiredRotation.Pitch = 0;
            RotationRate.Pitch = 50000;
        }
        if ( !Level.bDropDetail && (Level.DetailMode != DM_Low) && (Level.TimeSeconds - LastSparkTime > 0.5) && EffectIsRelevant(Location,false) )
        {
            PC = Level.GetLocalPlayerController();
            if ( (PC.ViewTarget != None) && VSize(PC.ViewTarget.Location - Location) < 6000 )
                Spawn(HitEffectClass,,, Location, Rotator(HitNormal));
            LastSparkTime = Level.TimeSeconds;
        }
    }
}

defaultproperties
{
    RotMag=(X=600.000000,Y=600.000000,Z=600.000000)
    RotRate=(X=12500.000000,Y=12500.000000,Z=12500.000000)
    RotTime=6.000000
    OffsetMag=(X=5.000000,Y=10.000000,Z=5.000000)
    OffsetRate=(X=300.000000,Y=300.000000,Z=300.000000)
    OffsetTime=3.500000

    ShrapnelClass=Class'KFShrapnel'
    DampenFactor=0.250000
    DampenFactorParallel=0.400000
    HitEffectClass=None
    Speed=160.000000
    MaxSpeed=850//350.000000
    Damage=300.000000 // Increased in Balance Round 2
    DamageRadius=420.000000 // Increased in Balance Round 2
    MomentumTransfer=100000.000000
    MyDamageType=Class'KFMod.DamTypeFrag'
    ExplosionDecal=Class'KFMod.KFScorchMark'
    StaticMesh=StaticMesh'KillingFloorStatics.FragProjectile'
    DrawScale=0.400000
    AmbientGlow=0
    bUnlit=False
    TransientSoundVolume=200.000000
    bNetTemporary=False
    bNetNotify=true

    ImpactSound=sound'KF_GrenadeSnd.Nade_HitSurf'
    ExplodeSounds(0)=sound'KF_GrenadeSnd.Nade_Explode_1'
    ExplodeSounds(1)=sound'KF_GrenadeSnd.Nade_Explode_2'
    ExplodeSounds(2)=sound'KF_GrenadeSnd.Nade_Explode_3'
    DisintegrateSound=Sound'Inf_Weapons.faust_explode_distant02'
    bBlockHitPointTraces=false
}
