class stub_Z_Boss extends ZombieBoss;


//=============================================================================
//                              ammo class == none fix
//=============================================================================

state FireMissile
{
  function AnimEnd( int Channel )
  {
    local vector Start;
    local Rotator R;

    Start = GetBoneCoords('tip').Origin;

    // at least shoot at someone, not walls
    if (Controller.Target == none)
      Controller.Target = Controller.Enemy;

    // fix MyAmmo none logs
    if (!SavedFireProperties.bInitialized)
    {
      SavedFireProperties.AmmoClass = class'SkaarjAmmo';
      SavedFireProperties.ProjectileClass = class'BossLAWProj';
      SavedFireProperties.WarnTargetPct = 0.15;
      SavedFireProperties.MaxRange = 10000;
      SavedFireProperties.bTossed = false;
      SavedFireProperties.bTrySplash = false;
      SavedFireProperties.bLeadTarget = true;
      SavedFireProperties.bInstantHit = true;
      SavedFireProperties.bInitialized = true;
    }

    R = AdjustAim(SavedFireProperties,Start,100);
    PlaySound(RocketFireSound,SLOT_Interact,2.0,,TransientSoundRadius,,false);
    // added projectile owner
    spawn(class'BossLAWProj',self,,Start,R);

    bShotAnim = true;
    Acceleration = vect(0,0,0);
    SetAnimAction('FireEndMissile');
    HandleWaitForAnim('FireEndMissile');

    // Randomly send out a message about Patriarch shooting a rocket(5% chance)
    if ( FRand() < 0.05 && Controller.Enemy != none && PlayerController(Controller.Enemy.Controller) != none )
    {
      PlayerController(Controller.Enemy.Controller).Speech('AUTO', 10, "");
    }

    GoToState('');
  }
}


//=============================================================================
//                              ctrl == none fixes
//=============================================================================

function bool MeleeDamageTarget(int hitdamage, vector pushdir)
{
  // added 'Controller != none' check
  if (Controller != none && Controller.Target != none && Controller.Target.IsA('NetKActor'))
    pushdir = Normal(Controller.Target.Location-Location)*100000;

  return super(KFMonster).MeleeDamageTarget(hitdamage, pushdir);
}


// non-state one
function ClawDamageTarget()
{
  local vector PushDir;
  local name Anim;
  local float frame,rate;
  local float UsedMeleeDamage;
  local bool bDamagedSomeone;
  local KFHumanPawn P;
  local Actor OldTarget;

  // check this from the very start to prevent any log spam
  if (Controller == none || IsInState('ZombieDying'))
    return;

  if (MeleeDamage > 1)
    UsedMeleeDamage = (MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1));
  else
    UsedMeleeDamage = MeleeDamage;

  GetAnimParams(1, Anim,frame,rate);

  if (Controller != none && Controller.Target != none)
    PushDir = (damageForce * Normal(Controller.Target.Location - Location));
  else
    PushDir = damageForce * vector(Rotation);

  // merging 2 similar checks
  // dick animation
  if (Anim == 'MeleeImpale')
  {
    MeleeRange = ImpaleMeleeDamageRange;
    bDamagedSomeone = MeleeDamageTarget(UsedMeleeDamage, PushDir);
  }
  // the hand animation
  else
  {
    MeleeRange = ClawMeleeDamageRange;
    OldTarget = Controller.Target;

    foreach DynamicActors(class'KFHumanPawn', P)
    {
      if ( (P.Location - Location) dot PushDir > 0.0 ) // Added dot Product check in Balance Round 3
      {
        Controller.Target = P;
        bDamagedSomeone = bDamagedSomeone || MeleeDamageTarget(UsedMeleeDamage, damageForce * Normal(P.Location - Location)); // Always pushing players away added in Balance Round 3
      }
    }

    Controller.Target = OldTarget;
  }

  MeleeRange = default.MeleeRange;

  if (bDamagedSomeone)
  {
    if (Anim == 'MeleeImpale')
      PlaySound(MeleeImpaleHitSound, SLOT_Interact, 2.0);
    else
      PlaySound(MeleeAttackHitSound, SLOT_Interact, 2.0);
  }
}


//=============================================================================
//                   headshot fix while he is machinegunning
//=============================================================================

state FireChaingun
{
  function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
  {
    local float EnemyDistSq, DamagerDistSq;

    // changed vect(0,0,0) with Momentum
    global.TakeDamage(Damage,instigatedBy,hitlocation,Momentum,damageType);

    // if someone close up is shooting us, just charge them
    if (InstigatedBy != none)
    {
      DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location);

      if ( (ChargeDamage > 200 && DamagerDistSq < (500 * 500)) || DamagerDistSq < (100 * 100) )
      {
        SetAnimAction('transition');
        GoToState('Charging');
        return;
      }
    }

    if (Controller.Enemy != none && InstigatedBy != none && InstigatedBy != Controller.Enemy)
    {
      EnemyDistSq = VSizeSquared(Location - Controller.Enemy.Location);
      DamagerDistSq = VSizeSquared(Location - InstigatedBy.Location);
    }

    if (InstigatedBy != none && (DamagerDistSq < EnemyDistSq || Controller.Enemy == none) )
    {
      MonsterController(Controller).ChangeEnemy(InstigatedBy,Controller.CanSee(InstigatedBy));
      Controller.Target = InstigatedBy;
      Controller.Focus = InstigatedBy;

      if( DamagerDistSq < (500 * 500) )
      {
        SetAnimAction('transition');
        GoToState('Charging');
      }
    }
  }
}


defaultproperties{}