// free for all game mode

if (!$gameModeAdded["FreeForAll"])
{
$gameModeAdded["FreeForAll"] = true;
$gameModeName[$nGameMode] = "FreeForAll";
$gameModePrintName[$nGameMode] = "Free For All";
$gameModePrintInServerList[$nGameMode] = true;
$nGameMode ++;
}

////////////////////////////////////////////////////////////////////////////////
// initialisation stuff

// called when the server loads the map
function FreeForAll::ServerStarted(%this)
{
   if ($debugMissionLoad)
      echo("GMServerStarted FreeForAll");

   $GMMissionArea = MissionArea;


   // artefact stuff

   $artefact = createWarpArtefact(getRandomArtefactSpawnPoint());
   $artefact.setScopeAlways();
   setArtefactOccasionalMove($artefact);


   $gameModePrintText = "Playing Free For All.  Every Omphr for himself, kill or be killed.";

   setTimedRoundsOn($Pref::Server::ffaDefaultRoundTime, "None 2 5 10 20 30");

   $weaponLimit = 6;
   
   setWeaponsListOn($Pref::Server::ffaDefaultWeaponList, $Pref::Server::ffaWeaponLists);
}


///////////////////////////////////////////////////////////////////////////////
// player/client management stuff

// new client entering the game
function FreeForAll::ClientEnterGame(%this, %client)
{
   %client.currentKillRun = 0;
   %client.maxKillRun = 0;


   if ($debugMissionLoad)
      echo("GMClientEnterGame FreeForAll");
}

// client fully loaded
function FreeForAll::ClientFullyLoaded(%this, %client)
{
   if ($debugMissionLoad)
      echo("GMClientFullyLoaded FreeForAll");

}

// returns true if this client is allowed to join the match
function FreeForAll::CanJoinMatch(%this, %client)
{
   return (!%client.inFight && $nPlayers < $nSlots);
}

// called on a player joining the match.  Newclient indicates whether the client has been in the match before
function FreeForAll::JoinMatch(%this, %client, %character, %newClient, %team)
{
   if (%client.player.isABot)
   {
      %client.player.setAiState("ChaseFacingOff");
   }

   %pos = getWords($artefact.getTransform(), 0, 2);

   %pos = VectorAdd(%pos, (getRandom() * 2 - 1) * 1000 SPC (getRandom() * 2 - 1) * 1000 SPC 0);

   %pos = setWord(%pos, 2, getTerrainOrWaterHeight(getWords(%pos, 0, 1)) + 10);
   
   //error("-------------------------");
   //error("SPAWNING AT: " @ %pos @ " --- " @ getWords(%pos, 0, 1) @ " --- " @ getTerrainOrWaterHeight(getWords(%pos, 0, 1)));
   
   %client.player.setTransform(%pos @ " 1 0 0 0");

   for (%i = 2; %i <= %client.maxKillRun; %i ++)
      giveKillRunWeaponTo(%client.player, %i);
}



// the reason you only get new weapons when you respawn is that it would make it too easy to get a long kill run if you
// got the new weapons "on demand"


$killRunWeaponClass[2] = "longWeapon";
$killRunWeaponClass[3] = "axe";
$killRunWeaponClass[4] = "dagger";
$killRunWeaponClass[5] = "bigSword";
$killRunWeaponClass[6] = "spear";

function giveKillRunWeaponTo(%player, %level)
{
   if (!%player.client.isDemoUser && $killRunWeaponClass[%level] !$= "")
   {
      %list = $weaponClassList[$killRunWeaponClass[%level]];
      //error("gkwt: " @ %list);

      %weapon = getRandomWeaponFromList(%list);
      //error("khtg: " @ %weapon SPC %weapon.index);

      error("giving weapon" SPC %weapon);
      giveWeaponTo(%player, %weapon.index);
   }
}

function getRandomWeaponFromList(%list)
{
   return getWord(%list, getRandom(0, getWordCount(%list) - 1));
}

// called on a client dropping for any reason
function FreeForAll::ClientDropped(%this, %client, %reason)
{

}


// called on a client leaving the match
function FreeForAll::ClientLeavingMatch(%this, %client)
{
   commandToClient(%client, 'SetBottomPrintText', "Left click to continue.", -1);
}


// called on player death or client leaving the match
function FreeForAll::RemovePlayer(%this, %player)
{

}

// call the client and tell him what colours we want the IFFs to be
function FreeForAll::SendClientIFFInfo(%this, %client)
{
   commandToClient(%client, 'setIFFColours', "0 1 0", "1 0 0", "0 0 1", "0 1 1", false);
}

function FreeForAll::playerHasNewTarget(%this, %player, %target)
{
   //error(%player SPC "has new target" SPC %target);
}


//////////////////////////////////////////////////////////////////
// action stuff

// called on a player-player collision
function FreeForAll::OnHit(%this, %hiter, %hitee, %myHitbox, %hisHitbox, %myForce, %hisForce, %myMult, %hisMult, %winner, %myV2, %hisV2)
{
   return standardHitDamage(%hiter, %hitee, %myHitbox, %hisHitbox, %myForce, %hisForce, %myMult, %hisMult, %winner, %myV2, %hisV2);
}





// called when a player is killed by an opponent
function FreeForAll::OnKilled(%this, %killee, %killer, %reason)
{
   echo("FreeForAll::OnKilled" SPC %killee SPC %killer SPC %reason);


   if (%reason $= "swordBlow")
   {
      if (!%killer.isABot)
         %killer.client.incScore(1);
      else
         incBotScore(%killer.client, 1);

      %killer.setDamageLevel(%killer.getDamageLevel() - 25);
      
      reportFFAResult(%killer.client, "kill", %killee.client);
   }
   else if (%reason $= "bleeding")
   {
      if (!%killer.isABot)
         %killer.client.incScore(1);
      else
         incBotScore(%killer.client, 1);

      %killer.setDamageLevel(%killer.getDamageLevel() - 25);
   }
   else if (%reason $= "warpArtefact")
   {
      if (%killer)
      {

         if (!%killer.isABot)
            %killer.client.incScore(1);
         else
            incBotScore(%killer.client, 1);

         %killer.setDamageLevel(%killer.getDamageLevel() - 25);
      }
      else
      {
         if (!%killee.isABot)
            %killee.client.incScore(-1);
         else
            incBotScore(%killee.client, -1);
      }
   }
   else if (%reason $= "warpStorm")
   {
      if (!%killee.isABot)
         %killee.client.incScore(-1);
      else
         incBotScore(%killee.client, -1);
   }
   else if (%reason $= "warpFire")
   {
      if (!%killer.isABot)
         %killer.client.incScore(1);
      else
         incBotScore(%killer.client, 1);

      %killer.setDamageLevel(%killer.getDamageLevel() - 25);
   }
   else if (%reason $= "curse")
   {
      if (!%killer.isABot)
         %killer.client.incScore(1);
      else
         incBotScore(%killer.client, 1);

      %killer.setDamageLevel(%killer.getDamageLevel() - 25);
   }
   else if (%reason $= "gridRupture")
   {
      if (!%killer.isABot)
         %killer.client.incScore(1);
      else
         incBotScore(%killer.client, 1);

      %killer.setDamageLevel(%killer.getDamageLevel() - 25);
   }
   else if (%reason $= "warpExplosion")
   {
      if (!%killee.isABot)
         %killee.client.incScore(-1);
      else
         incBotScore(%killee.client, -1);
   }


   %killer.client.currentKillRun ++;

   if (%killer.client.currentKillRun > %killer.client.maxKillRun)
   {
      //giveKillRunWeaponTo(%killer, %killer.client.currentKillRun); 
      %killer.client.maxKillRun = %killer.client.currentKillRun;
   }

   // we schedule it a bit later to ensure other messages have got there
   schedule(1000, 0, "standardKillMessage", %killee, %killer, %reason); 
   
   if (%killer.client.currentKillRun > 1)
      schedule(1300, 0, "messageAll", '', '%1 has a Kill Run of %2!', %killer.client.name, %killer.client.currentKillRun);
}




// called on a player's death
function FreeForAll::OnDeath(%this, %player)
{
   

   %player.client.currentKillRun = 0;
}


function FreeForAll::onSuicide(%this, %client)
{
   reportFFAResult(%client, "suicide", 0);
}



function FreeForAll::playerHitItem(%this, %player, %item)
{

}



function FreeForAll::Trigger(%this, %client, %trigger, %val)
{
   //error("client trigger: " @ %trigger SPC %val);
}



/////////////////////////////////////////////////////////////////////
// mission area stuff

// called when the player enters the MissionArea mission area struct
function FreeForAll::OnEnterMissionArea(%this, %player)
{
   
}

// called when the player leaves the MissionArea mission area struct
function FreeForAll::OnLeaveMissionArea(%this, %player)
{
  
}



//////////////////////////////////////////////////////////////////////

function FreeForAll::onTimedRoundEndRound(%this)
{
   for (%i = 0; %i < ClientGroup.getCount(); %i ++)
   {
      %c = ClientGroup.getObject(%i);

      %c.maxKillRun = 0;
   }
}




////////////////////////////////////////////////////////////////////
// mission end cleanup


function FreeForAll::OnMissionEnded(%this)
{
   disactiveWarpStorms();

   finishWarpArtefact($artefact);
}

////////////////////////////////////////////////////////////////////
// ball stuff

// player collides with the ball
function FreeForAll::PlayerHitBall(%this, %player, %hitboxID, %ball)
{

}


