init(delay)
{
  self endon("killed_player");
  self endon("disconnect");

  if(self.wwx_artillery_strike) return;

  self notify("end_artillery");
  wait(0.1);
  self endon("end_artillery");

  self.wwx_artillery_strike = true;

  // wait the first
  if(!isDefined(delay)) delay = level.wwx_rank_artillery_first;
  wait(delay);

  while(self.wwx_artillery_strike)
  {
    // let them know the artillery strike is available
    self iprintlnbold(&"ARTILLERY_READY");

    self teamsound("arty_ready", 1);

    //set up the on screen icon
    self hudNotify();
    self.calling = false;

    //monitor for binocular fire
    self thread waitForUse();

    // wait until they use artillery
    self waittill("artillery_over");

    if(level.wwx_rank_wmdtype >= 1) break;
    self iprintlnbold(&"ARTILLERY_RELOAD");
    self teamsound("arty_reload", 3);
    // now wait for one interval
    wait(level.wwx_rank_artillery_int + randomint(10));
  }

  // stop artillery
  self.wwx_artillery_strike = false;
  self notify("artillery_over");
  self notify("end_artillery");
}

friendlyInStrikeZone(targetPos)
{
  // return if friendly fire check has been disabled
  if(level.wwx_frndly == 0) return false;
  
  // dont need to check friendly if gametype is not teamplay
  if(level.wwx_currentgt == "dm" || level.wwx_currentgt == "lms" || level.wwx_currentgt == "ihtf") return false;

  if(!isDefined(targetPos)) return (undefined);

  if(distance(targetPos, self.origin) <= 1000) return (undefined);

  // check if players in the same team are in targetzone
  players = getentarray("player", "classname");
  for(i = 0; i < players.size; i++)
  {
    if(isPlayer(self) && isPlayer(players[i]))
    {
      if(players[i].sessionstate == "playing" && players[i].pers["team"] == self.pers["team"])
      {
        if(distance(targetpos, players[i].origin) <= 1000)
          return true;
      }
    }
  }
  return false;
}

hudNotify()
{
  self endon("killed_player");

  self hudNotifyRemove();

  self.artillery_available_icon = newClientHudElem(self);
  self.artillery_available_icon.alignX = "center";
  self.artillery_available_icon.alignY = "middle";
  self.artillery_available_icon.x = 172;
  self.artillery_available_icon.y = 455;
  self.artillery_available_icon.alpha = 1;
  self.artillery_available_icon setShader(game["artillery"], 32, 32);

  if(!isDefined(self.wwx_binocular_hint))
  {
    self.wwx_binocular_hint = newClientHudElem( self );
    self.wwx_binocular_hint.alignX = "center";
    self.wwx_binocular_hint.alignY = "top";
    self.wwx_binocular_hint.fontScale = 1;
    self.wwx_binocular_hint.x = 320;
    self.wwx_binocular_hint.y = 464;

    self.wwx_binocular_hint.sort = 5;
    self.wwx_binocular_hint setText(&"WMD_ACTIVATE_HINT");

    // do not show hint if planting a tripwire
    if(level.wwx_tweapon)
    {
      if( !self.wwx_plantwire && !self.wwx_defusewire && !isDefined(self.wwx_actimer) ||
        self [[level.wwx_getstance]](false) != 2 && !isDefined(self.wwx_actimer)) self.wwx_binocular_hint.alpha = 1;
      else self.wwx_binocular_hint.alpha = 0;
    }
    else self.wwx_binocular_hint.alpha = 1;
  }
}

hudNotifyRemove()
{
  if(isDefined(self.artillery_available_icon)) self.artillery_available_icon destroy();
}

binocHintHud()
{
  self endon("binocular_exit");

  if(!isdefined(self.wwx_binocular_hint))
  {
    self.wwx_binocular_hint = newClientHudElem( self );
    self.wwx_binocular_hint.alignX = "center";
    self.wwx_binocular_hint.alignY = "top";
    self.wwx_binocular_hint.fontScale = 1;
    self.wwx_binocular_hint.x = 320;
    self.wwx_binocular_hint.y = 464;
    self.wwx_binocular_hint.alpha = 1;
    self.wwx_binocular_hint.sort = 5;
  }

  self.wwx_binocular_hint setText(&"WMD_ARTILLERY_HINT");
  self thread artillery_binocularhint_hud_destroy2();
}

artillery_binocularhint_hud_destroy()
{
  if(isDefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();
}

artillery_binocularhint_hud_destroy2()
{
  self endon("binocular_enter");
  self endon("killed_player");
  self waittill("binocular_exit");

  if(isDefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();
}

waitforuse()
{
  self endon("end_waitforuse");
  self endon("killed_player");

  for (;;)
  {
    self waittill("binocular_enter");
    self thread waitForBinocUse();
    self thread binocHintHud();
    wait .2;
  }
}

waitForBinocUse()
{
  // kill dupes
  self notify("binocular_exit");
  wait(0.1);
  self endon("binocular_exit");
  self endon("artillery_fired");
  self endon("killed_player");

  // wait for use button to be pressed
  for(;;)
  {
    if(isPlayer(self) && self useButtonPressed() && !self.calling)
      {
      self.calling = true;
      self thread callradio();
      self waittill ("radiodone");
      }
    wait .01;
  }
}

callradio()
{
  self endon("killed_player");

  // player has used weapon
  self.usedweapons = true;

  self iprintlnbold(&"ARTILLERY_RADIO_IN");

  targetPos = getTargetPosition();
  friendly = friendlyInstrikezone(targetPos);

  self teamSound("arty_firemission", 3.6);
  for(i = 1; i < 4; i++) self teamSound("arty_" + randomInt(8), 0.6);
  self teamSound("arty_pointfuse", 3);

  if(isDefined(targetPos) && isDefined(friendly) && friendly == false)
  {
    self iprintlnbold(&"ARTILLERY_FIRED");
    self teamsound("arty_shot", 3);

    artillery = spawn("script_origin", targetPos);
    artillery thread fireBarrage(self);

    //clear hud icon
    self hudNotifyRemove();

    //clear hint icon
    if(isdefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();

    //notify threads
    self notify("radiodone");
    self notify("end_waitforuse");
    self notify ("artillery_fired");
  }
  else if(!isDefined(targetpos) && !isDefined(friendly))
  {
    friendly = undefined;
    self iprintlnbold(&"ARTILLERY_NOT_VALID");
    self teamSound("arty_novalid", 3);
    self notify("radiodone");
  }
  else if(isDefined(friendly) && friendly == true)
  {
    friendly = undefined;
    self iprintlnbold(&"ARTILLERY_FRIENDLY_WARNING");
    self teamSound("arty_frndly", 3);
    self notify("radiodone");
  }
  else if(isDefined(targetpos) && !isDefined(friendly))
  {
    friendly = undefined;
    self iprintlnbold(&"ARTILLERY_TO_CLOSE_WARNING");
    self teamSound("arty_tooclose", 3);
    self notify("radiodone");
  }
  self.calling = false;
  self notify("radiodone");
}

fireBarrage(owner)
{
  //drop flare
  if(level.wwx_rank_wmd_flare) playfx(level.wwx_effect["flare_indicator"], self.origin);
  wait(1);

  // create artillery start position (surface level)
  artilleryStartPos = (level.wwx_playArea_Min[0], level.wwx_playArea_Min[1], 0);

  // Number of shells in barrage
  shellNumber = 12;

  // artillery firing sounds
  for(i = 0; i < shellNumber; i++ )
  {
    self thread firingSound();
    wait(.5);
  }

  // create shell target positions
  shellTargetPos = [];
  for(i = 0; i < shellNumber; i++ )
    shellTargetPos[i] = calcShellPos(self.origin);

  self.artilleryGlobalDelay = 0;

  // fire shells
  for (i = 0; i < shellNumber; i++ )
    self thread fireShell(owner, artilleryStartPos, shellTargetPos[i]);

  // wait for all shells to explode
  shellImpacts = 0;
  while ( shellImpacts < shellNumber )
  {
    self waittill ("artillery_shell_impact");
    shellImpacts++;
  }

  owner notify ("artillery_over");
  self delete();
}

fireShell(owner, shellStartPos, shellTargetPos)
{
  // calculate the height of the artillery spawn point to let shells come in at a certain angle
  //shellAngle = 60;
  //shellDist = distance(shellTargetPos, shellStartPos);
  //shellHeight = int(shellDist * tan(shellAngle));
  //shellStartPos = (shellStartPos[0], shellStartPos[1], shellHeight);
  shellStartPos = (shellTargetPos[0]-100, shellTargetPos[1]-100, level.wwx_mapArea_Max[2]);

  self.artilleryGlobalDelay += randomFloatRange( .5, 1.5 );
  wait(self.artilleryGlobalDelay);
  wait(randomFloatRange(1.5, 2.5));

  // show visible artillery shell
  shell = spawn("script_model", shellStartPos);
  shell setModel("xmodel/prop_stuka_bomb");
  shell.angles = vectorToAngles(vectorNormalize(shellTargetPos - shellStartPos));

  // Play incoming sound
  shell playSound("artillery_incoming");

  // calculate time in air (s) based on distance (m) and preferred shell speed (m/s)!
  shellDist = distance(shellTargetPos, shellStartPos);
  shellDist = int(shellDist * 0.0254); // Convert distance to metres
  shellSpeed = 50;
  shellInAir = calcTime(shellDist, shellSpeed);

  // move visible artillery shell (correct target to slam shells into the ground, and for more realistic FX)
  shell moveTo(shellTargetPos + (0,0,-100), shellInAir);

  // wait for shell to hit
  wait(shellInAir);

  shell shellImpact(owner);
  self notify("artillery_shell_impact");
}

shellImpact(owner)
{
  playfx(level.wwx_effect["artillery"], self.origin);
  self playSound("artillery_explosion");

  surfaceFx = calcImpactSurface(self.origin);
  if(isPlayer(owner))
    self thread ww2x\_wwx_utils::scriptedfxradiusdamage(owner, undefined, "MOD_EXPLOSIVE", "artillery_mp", level.wwx_artillery_radius, 500, 350, "generic", surfaceFx, true, true, true);

  self hide();
  wait(3);
  self delete();
}

calcTime(distvalue, speedvalue)
{
  distunit = 1;  // Metres
  speedunit = 1; // Metres per second
  timeinsec = (distvalue * distunit) / (speedvalue * speedunit);
  if(timeinsec < 0) timeinsec = 0.1;
  return timeinsec;
}

getTargetPosition()
{
  startOrigin = self getEye() + (0,0,20);
  forward = anglesToForward(self getplayerangles());
  forward = [[level.wwx_vectorscale]](forward, 100000);
  endOrigin = startOrigin + forward;

  trace = bulletTrace( startOrigin, endOrigin, false, self );
  if(trace["fraction"] == 1.0 || trace["surfacetype"] == "default") return (undefined);
    else return (trace["position"]);
}

calcShellPos(targetPos)
{
  shellPos = undefined;
  iterations = 0;

  while(!isDefined(shellPos) && iterations < 5)
  {
    shellPos = targetPos;
    angle = randomFloat(360);
    radius = randomFloat(level.wwx_rank_artillery_radius);
    randomOffset = (cos(angle) * radius, sin(angle) * radius, 0);
    shellPos += randomOffset;
    startOrigin = shellPos + (0, 0, 800);
    endOrigin = shellPos + (0, 0, -2048);

    trace = bulletTrace( startOrigin, endOrigin, true, undefined );
    if(trace["fraction"] < 1.0) shellPos = trace["position"];
      else shellPos = undefined;

    iterations++;
  }
  if(!isDefined(shellPos)) shellPos = targetPos;
  return shellPos;
}

calcImpactSurface(targetPos)
{
  startOrigin = targetPos + (0, 0, 800);
  endOrigin = targetPos + (0, 0, -2048);

  trace = bulletTrace(startOrigin, endOrigin, true, undefined);
  if(trace["fraction"] < 1.0) surface = trace["surfacetype"];
    else surface = "dirt";

  return surface;
}

firingSound()
{
  players = getentarray("player", "classname");
  for(i = 0; i < players.size; i++)
    players[i] playLocalSound("artillery_fire");
}

teamSound(nat,wt)
{
    if (self.pers["team"] == "allies")
		{
		switch(game["allies"])
			{
			case "american":self playLocalSound("us_"+nat);wait(wt);break;
							
			case "british":self playLocalSound("uk_"+nat);wait(wt);break;
					
			default:self playLocalSound("ru_"+nat);wait(wt);break;
			}
		}
	else if (self.pers["team"] == "axis")
		{
		switch(game["axis"])
			{
			case "german":self playLocalSound("ge_"+nat);wait(wt);break;
			}
		}
}
