// koth.cpp : Defines the entry point for the DLL application.

#include "bzfsAPI.h"
#include <map>
#include <cmath>

class KOTHMapHandler : public bz_CustomMapObjectHandler
{
public:
  virtual bool MapObject ( bz_ApiString object, bz_CustomMapObjectInfo *data );
};

KOTHMapHandler	kothmaphandler;

class KOTHCommands : public bz_CustomSlashCommandHandler
{
public:
  virtual ~KOTHCommands() {};
  virtual bool SlashCommand ( int playerID, bz_ApiString command, bz_ApiString message, bz_APIStringList *param );
};

KOTHCommands kothcommands;

class KOTHHandler : public bz_Plugin
{
public:
  virtual const char* Name () {return "King Of The Hill";}
  virtual void Init ( const char* config );
  virtual void Cleanup ();

  virtual void Event ( bz_EventData *eventData );

};

BZ_PLUGIN(KOTHHandler)

void KOTHHandler::Init(const char* /*commandLine*/) {
  MaxWaitTime = 0.5f;

  bz_registerCustomMapObject("KOTH",&kothmaphandler);
  Register(bz_ePlayerUpdateEvent);
  Register(bz_ePlayerPausedEvent);
  Register(bz_ePlayerPartEvent);
  Register(bz_ePlayerJoinEvent);
  Register(bz_ePlayerDieEvent);
  bz_registerCustomSlashCommand("kothstatus",&kothcommands);
  bz_registerCustomSlashCommand("kothon",&kothcommands);
  bz_registerCustomSlashCommand("kothoff",&kothcommands);
  bz_registerCustomSlashCommand("kothsoundon",&kothcommands);
  bz_registerCustomSlashCommand("kothsoundoff",&kothcommands);
  bz_registerCustomSlashCommand("kothtimemult",&kothcommands);
  bz_registerCustomSlashCommand("kothtimemultmin",&kothcommands);
  bz_registerCustomSlashCommand("kothtime",&kothcommands);
  bz_registerCustomSlashCommand("kothautotimeon",&kothcommands);
  bz_registerCustomSlashCommand("kothautotimeoff",&kothcommands);
  bz_registerCustomSlashCommand("kingsay",&kothcommands);
}

void KOTHHandler::Cleanup(void) {

  Flush();
  bz_removeCustomMapObject("KOTH");
  bz_removeCustomSlashCommand("kothstatus");
  bz_removeCustomSlashCommand("kothon");
  bz_removeCustomSlashCommand("kothoff");
  bz_removeCustomSlashCommand("kothsoundon");
  bz_removeCustomSlashCommand("kothsoundoff");
  bz_removeCustomSlashCommand("kothtimemult");
  bz_removeCustomSlashCommand("kothtimemultmin");
  bz_removeCustomSlashCommand("kothtime");
  bz_removeCustomSlashCommand("kothautotimeon");
  bz_removeCustomSlashCommand("kothautotimeoff");
  bz_removeCustomSlashCommand("kingsay");
}

class KOTH
{
public:
  KOTH()
  {
    id = -1;
    startTime = 0;
    team = eNoTeam;
    callsign = "";
    teamPlay = false;
    TTH = 60;
    adjustedTime = 60;
    timeMult = 0.03;
    timeMultMin = 0.50;
    enabled = true;
    toldHillOpen = false;
    onePlayerWarn = false;
    autoTimeOn = false;
    TTHminutes = 0;
    TTHseconds = 30;
    playerJustWon = -1;
    soundEnabled = true;
  }
  bz_eTeamType team;
  std::string callsign;
  double TTH;
  double adjustedTime;
  double timeMult;
  double timeMultMin;
  double startTime;
  bool teamPlay;
  bool enabled;
  bool toldHillOpen;
  bool onePlayerWarn;
  bool autoTimeOn;
  bool soundEnabled;
  int TTHminutes;
  int TTHseconds;
  int playerJustWon;
  int id;
};

KOTH koth;

class KOTHZone : public bz_CustomZoneObject {
public:
  KOTHZone() : bz_CustomZoneObject() {}
};

KOTHZone kothzone;

bool KOTHMapHandler::MapObject ( bz_ApiString object, bz_CustomMapObjectInfo *data )
{
  if (object != "KOTH" || !data)
    return false;

  kothzone.handleDefaultOptions(data);

  // parse all the chunks
  for ( unsigned int i = 0; i < data->data.size(); i++ )
  {
    std::string line = data->data.get(i).c_str();

    bz_APIStringList *nubs = bz_newStringList();
    nubs->tokenize(line.c_str()," ",0,true);

    if ( nubs->size() > 0)
    {
      std::string key = bz_toupper(nubs->get(0).c_str());

      if ( key == "TEAMPLAY")
      {
	koth.teamPlay = true;
      }
      else if ( key == "NOSOUND")
      {
	koth.soundEnabled = false;
      }
      else if ( key == "AUTOTIME" && nubs->size() == 1 )
      {
	koth.autoTimeOn = true;
      }
      else if ( key == "AUTOTIME" && nubs->size() > 2 )
      {
	double temp1 = (double)atof(nubs->get(1).c_str());
	double temp2 = (double)atof(nubs->get(2).c_str());
	if (temp1 >= 1 && temp1 <= 99)
	  koth.timeMult = temp1 / 100;
	if (temp2 >= 1 && temp2 <= 99)
	  koth.timeMultMin = temp2 / 100;
	koth.autoTimeOn = true;
      }
      else if ( key == "HOLDTIME" && nubs->size() > 1 )
      {
	double temp = (double)atof(nubs->get(1).c_str());
	if (temp >= 1 && temp <= 7200)
	  koth.TTH = temp;
      }
    }

    bz_deleteStringList(nubs);
  }
  return true;
}

std::string truncate(std::string cllsn)
{
  std::string fixed = "";

  for (int i = 0; i < 16; i++)
  {
    fixed.push_back(cllsn[i]);
  }

  fixed.append("~");

  return fixed;
}

const char* getTeamColor(bz_eTeamType testteam)
{
  if (testteam == eRedTeam)
    return "RED";
  if (testteam == eGreenTeam)
    return "GREEN";
  if (testteam == eBlueTeam)
    return "BLUE";
  if (testteam == ePurpleTeam)
    return "PURPLE";
  if (testteam == eRogueTeam)
    return "ROGUE";

  return " ";
}

bool onePlayer()
{
  int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) + bz_getTeamCount(eRogueTeam);

  if (numPlayers <= 1)
  {
    if (!koth.onePlayerWarn)
      bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "King of the Hill disabled: less than 2 players.");

    koth.onePlayerWarn = true;
    return true;
  }
  else
  {
    if (koth.onePlayerWarn)
      bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "King of the Hill enabled: more than 1 player.");

    koth.onePlayerWarn = false;
    return false;
  }
}

void autoTime()
{
  int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) + bz_getTeamCount(eRogueTeam);

  if (!koth.autoTimeOn || numPlayers < 3)
  {
    koth.adjustedTime = koth.TTH;
    return;
  }

  double timeDown = ( 1 - ((double)numPlayers - 2) * koth.timeMult);

  if (timeDown < koth.timeMultMin)
    timeDown = koth.timeMultMin;

  koth.adjustedTime = (int)(koth.TTH * timeDown);

  return;
}

double ConvertToNum(std::string inmessage, double minNum, double maxNum) {

  int messagelength = (int)inmessage.length();

  if (messagelength > 0 && messagelength < 5)
  {
    double messagevalue = 0;
    double tens = 1;

    for ( int i = (messagelength - 1); i >= 0; i-- ) {

      if (inmessage[i] < '0' || inmessage[i] > '9')  // got something other than a number
	return 0;

      tens *= 10;
      messagevalue +=  (((double)inmessage[i] - '0') / 10) * tens;
    }

    if (messagevalue >= minNum && messagevalue <= maxNum)
      return messagevalue;
  }

  return 0;
}

void killTeams(bz_eTeamType safeteam, std::string kothcallsign)
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_getPlayerIndexList ( playerList );

  for ( unsigned int i = 0; i < playerList->size(); i++ ) {

    bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));

    if (player) {

      if (player->team != safeteam)
      {
	bz_killPlayer(player->playerID, true, BZ_SERVER);
	if (koth.soundEnabled)
	  bz_sendPlayCustomLocalSound(player->playerID,"flag_lost");
      }
      else if (koth.soundEnabled)
	bz_sendPlayCustomLocalSound(player->playerID,"flag_won");
    }

    bz_freePlayerRecord(player);
  }
  bz_deleteIntList(playerList);

  bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) IS KING OF THE HILL!", getTeamColor(safeteam), kothcallsign.c_str());

  return;
}

void killPlayers(int safeid, std::string kothcallsign)
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_getPlayerIndexList ( playerList );

  for ( unsigned int i = 0; i < playerList->size(); i++ ) {

    bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));

    if (player) {

      if (player->playerID != safeid)
      {
	bz_killPlayer(player->playerID, true, koth.id);
	if (koth.soundEnabled)
	  bz_sendPlayCustomLocalSound(player->playerID,"flag_lost");
      }
      else if (koth.soundEnabled)
	bz_sendPlayCustomLocalSound(player->playerID,"flag_won");
    }

    bz_freePlayerRecord(player);
  }

  bz_deleteIntList(playerList);

  bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s IS KING OF THE HILL!", kothcallsign.c_str());

  return;
}

void sendWarnings(const char* teamcolor, std::string playercallsign, double kothstartedtime)
{
  double TimeElapsed = bz_getCurrentTime() - kothstartedtime;
  double TimeRemaining = koth.adjustedTime - TimeElapsed;
  int toTens = int((TimeRemaining + 5) / 10) * 10;

  if ((TimeRemaining/60) < koth.TTHminutes && koth.adjustedTime > 59)
  {
    if (!koth.teamPlay || koth.team == eRogueTeam)
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s will be King in %i secs!", playercallsign.c_str(), toTens);
    else
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) will be King in %i secs!", teamcolor, playercallsign.c_str(), toTens);

    koth.TTHminutes--;
  }

  if (koth.adjustedTime < koth.TTHseconds)
  {
    koth.TTHseconds = koth.TTHseconds - 10;
    return;
  }

  if (TimeRemaining < koth.TTHseconds)
  {
    if (!koth.teamPlay || koth.team == eRogueTeam)
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s will be King in %i secs!", playercallsign.c_str(), koth.TTHseconds);
    else
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) will be King in %i secs!", teamcolor, playercallsign.c_str(), koth.TTHseconds);

    koth.TTHseconds = koth.TTHseconds - 10;
  }
  return;
}

void initiatekoth(bz_eTeamType plyrteam, bz_ApiString plyrcallsign, int plyrID)
{
  koth.team = plyrteam;
  koth.callsign = plyrcallsign.c_str();

  if (koth.callsign.size() > 16)
  {
    std::string tofix = truncate(koth.callsign);
    koth.callsign = tofix;
  }

  koth.id = plyrID;
  koth.startTime = bz_getCurrentTime();
  koth.TTHminutes = (int)(koth.adjustedTime/60 + 0.5);
  koth.TTHseconds = 30;
  koth.toldHillOpen = false;
  bool multipleof30 = false;

  if ((int)((koth.adjustedTime / 30) + 0.5) != (double)(koth.adjustedTime / 30))
    multipleof30 = false;
  else
    multipleof30 = true;

  if (!multipleof30)
  {
    if ((!koth.teamPlay || koth.team == eRogueTeam))
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s has Hill; will be King in %i secs!", koth.callsign.c_str(), (int)koth.adjustedTime);
    else
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) has Hill; will be King in %i secs!", getTeamColor(koth.team), koth.callsign.c_str(), (int)koth.adjustedTime);
  }

  if (koth.soundEnabled)
  {
    bz_APIIntList *playerList = bz_newIntList();
    bz_getPlayerIndexList ( playerList );

    for ( unsigned int i = 0; i < playerList->size(); i++ )
    {
      bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));

      if (player)
      {
	if (player->team != koth.team)
	  bz_sendPlayCustomLocalSound(player->playerID,"flag_alert");
	else
	  bz_sendPlayCustomLocalSound(player->playerID,"teamgrab");
      }

      bz_freePlayerRecord(player);
    }
    bz_deleteIntList(playerList);
  }

  return;
}

bool teamClear(bz_eTeamType teamToCheck)
{
  if (teamToCheck == eRogueTeam || teamToCheck == eNoTeam || !koth.teamPlay)
    return true;

  bz_APIIntList *playerList = bz_newIntList();
  bz_getPlayerIndexList ( playerList );

  bool isOut = true;

  for ( unsigned int i = 0; i < playerList->size(); i++ ) {

    bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));

    if (player)
    {
      if (player->team == teamToCheck && kothzone.pointInZone(player->lastKnownState.pos) && player->spawned)
	isOut = false;
    }

    bz_freePlayerRecord(player);
  }

  bz_deleteIntList(playerList);

  return isOut;
}

void KOTHPlayerPaused ( bz_EventData *eventData )
{
  if (eventData->eventType != bz_ePlayerPausedEvent || !koth.enabled)
    return;

  bz_PlayerPausedEventData_V1 *PauseData = (bz_PlayerPausedEventData_V1*)eventData;
  bz_BasePlayerRecord *player = bz_getPlayerByIndex(PauseData->playerID);

  if (player)
  {
    if (kothzone.pointInZone(player->lastKnownState.pos))
    {
      bz_killPlayer (PauseData->playerID, true, BZ_SERVER);
      bz_sendTextMessage (BZ_SERVER, PauseData->playerID, "Cannot pause while on the Hill.");
    }
  }
  bz_freePlayerRecord(player);

  return;
}

void KOTHPlayerJoined ( bz_EventData *eventData )
{
  if (eventData->eventType != bz_ePlayerJoinEvent || !koth.enabled)
    return;

  autoTime();

  return;
}

void KOTHPlayerLeft ( bz_EventData *eventData )
{
  if (eventData->eventType != bz_ePlayerPartEvent || !koth.enabled)
    return;

  autoTime();

  bz_PlayerJoinPartEventData_V1 *partData = (bz_PlayerJoinPartEventData_V1*)eventData;

  if (partData->playerID == koth.id)
  {
    koth.id = -1;
    koth.team = eNoTeam;
  }

  return;
}

void KOTHPlayerDied( bz_EventData *eventData )
{
  if (eventData->eventType != bz_ePlayerDieEvent || !koth.enabled)
    return;

  bz_PlayerDieEventData_V1 *dieData = (bz_PlayerDieEventData_V1*)eventData;

  if (dieData->playerID == koth.id)
  {
    koth.id = -1;
    koth.team = eNoTeam;
  }

  return;
}

inline void KOTHEventHandler( bz_EventData *eventData )
{
  if (!koth.enabled) // King of the Hill disabled - we can leave
    return;

  if (onePlayer()) // Not enough players - we can leave
    return;

  float pos[3] = {0};

  int playerID = -1;

  switch (eventData->eventType)
  {
   case bz_ePlayerUpdateEvent:
    pos[0] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[0];
    pos[1] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[1];
    pos[2] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[2];
    playerID = ((bz_PlayerUpdateEventData_V1*)eventData)->playerID;
    break;

   case bz_eShotFiredEvent:
    pos[0] = ((bz_ShotFiredEventData_V1*)eventData)->pos[0];
    pos[1] = ((bz_ShotFiredEventData_V1*)eventData)->pos[1];
    pos[2] = ((bz_ShotFiredEventData_V1*)eventData)->pos[2];
    playerID = ((bz_ShotFiredEventData_V1*)eventData)->playerID;
    break;

   default:
    return;
  }

  if (!koth.toldHillOpen && koth.id == -1) // Hill is open - inform players
  {
    bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "Hill is not controlled - take it!");
    koth.toldHillOpen = true;
  }

  if (kothzone.pointInZone(pos)) // player is on Hill
  {
    bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);

    if (player)
    {
      if (player->playerID != koth.playerJustWon && player->spawned)
      {
	if ((koth.id == -1 && player->team != koth.team) || (koth.id == -1 && teamClear(koth.team)))
	  initiatekoth(player->team, player->callsign, player->playerID);

	double timeStanding = bz_getCurrentTime() - koth.startTime;

	if (timeStanding >= koth.adjustedTime && koth.id != -1) // time's up - kill 'em
	{
	  if (koth.teamPlay && koth.team != eRogueTeam)
	    killTeams(koth.team, koth.callsign);
	  else
	    killPlayers(koth.id, koth.callsign);

	  if (!koth.teamPlay || koth.team == eRogueTeam)
	    bz_sendTextMessage (BZ_SERVER, koth.id, "You are King of the Hill!  You must leave hill to retake it.");
	  else
	    bz_sendTextMessage (BZ_SERVER, koth.team, "Your team is King of the Hill!  Entire team must leave hill to retake it.");

	  koth.playerJustWon = koth.id;

	  koth.id = -1;

	  return;
	}
	if (koth.id != -1)
	  sendWarnings(getTeamColor(koth.team), koth.callsign, koth.startTime);
      }
    }

    bz_freePlayerRecord(player);
  }
  else // player is off Hill
  {
    if (playerID == koth.playerJustWon)
      koth.playerJustWon = -1;

    if (playerID == koth.id)
    {
      koth.id = -1;
      koth.team = eNoTeam;
    }
  }
}

void KOTHHandler::Event( bz_EventData *eventData )
{
  if (eventData->eventType == bz_ePlayerUpdateEvent)
    KOTHEventHandler(eventData);
  else if (eventData->eventType == bz_eShotFiredEvent)
    KOTHEventHandler(eventData);
  else if (eventData->eventType == bz_ePlayerDieEvent)
    KOTHPlayerDied(eventData);
  else if (eventData->eventType == bz_ePlayerJoinEvent)
    KOTHPlayerJoined(eventData);
  else if (eventData->eventType == bz_ePlayerPartEvent)
    KOTHPlayerLeft(eventData);
  else if (eventData->eventType == bz_ePlayerPausedEvent)
    KOTHPlayerPaused(eventData);

}


bool KOTHCommands::SlashCommand ( int playerID, bz_ApiString _command, bz_ApiString _message, bz_APIStringList * /*_param*/ )
{
  std::string command = _command.c_str();
  std::string message = _message.c_str();
  const char* kingmessage = _message.c_str();

  if ( command == "kingsay" )
  {
    if (koth.id != -1)
      bz_sendTextMessage (playerID, koth.id, kingmessage);
    else
      bz_sendTextMessage(BZ_SERVER,playerID,"There is no one attempting to be king right now.");

    return true;
  }

  bz_BasePlayerRecord *fromPlayer = bz_getPlayerByIndex(playerID);

  if (fromPlayer) {
    if ( !fromPlayer->admin ) {
      bz_sendTextMessage(BZ_SERVER,playerID,"You must be admin to use the koth commands.");
      bz_freePlayerRecord(fromPlayer);
      return true;
    }

    bz_freePlayerRecord(fromPlayer);
  }

  if ( command == "kothon")
  {
    koth.enabled = true;
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill is enabled.");
    return true;
  }

  if ( command == "kothoff")
  {
    koth.enabled = false;
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill is disabled.");
    return true;
  }

  if ( command == "kothsoundon")
  {
    koth.soundEnabled = true;
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill sounds are enabled.");
    return true;
  }

  if ( command == "kothsoundoff")
  {
    koth.soundEnabled = false;
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill sounds are disabled.");
    return true;
  }

  if ( command == "kothtimemult")
  {
    double inputvalue = ConvertToNum(message, 1, 99);

    if (inputvalue > 0)
    {
      koth.timeMult = (inputvalue/100);
      bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier set to %i percent.", (int)(koth.timeMult*100 + 0.5));
    }
    else
      bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier must be between 1 and 99 percent.", (int)(koth.timeMult*100 + 0.5));

    autoTime();

    return true;
  }

  if ( command == "kothtimemultmin")
  {
    double inputvalue = ConvertToNum(message, 1, 99);

    if (inputvalue > 0)
    {
      koth.timeMultMin = (inputvalue/100);
      bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier minimum set to %i percent.", (int)(koth.timeMultMin*100 + 0.5));
    }
    else
      bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier minimum must be between 1 and 99 percent.");

    autoTime();

    return true;
  }

  if ( command == "kothstatus")
  {
    if (koth.enabled)
      bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill is currently enabled.");

    if (!koth.enabled)
      bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill is currently disabled.");

    if (koth.soundEnabled)
      bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill sounds are currently enabled.");

    if (!koth.soundEnabled)
      bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill sounds are currently disabled.");

    if (koth.autoTimeOn)
      bz_sendTextMessagef (BZ_SERVER, playerID, "Automatic time adjustment is currently enabled.");

    if (!koth.autoTimeOn)
      bz_sendTextMessagef (BZ_SERVER, playerID, "Automatic time adjustment is currently disabled.");

    bz_sendTextMessagef (BZ_SERVER, playerID, "Time multiplier = %i percent.", (int)(koth.timeMult*100 + 0.5));

    bz_sendTextMessagef (BZ_SERVER, playerID, "Time multiplier minimum = %i percent.", (int)(koth.timeMultMin*100 + 0.5));

    int AdjTime = (int)(koth.adjustedTime + 0.5);
    bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill hold time is currently set to: %i seconds", AdjTime);
    return true;
  }

  // explicit time command handler:

  if ( command == "kothtime" )
  {
    double inputvalue = ConvertToNum(message, 1, 7200);

    if (inputvalue > 0 )
    {
      koth.TTH = inputvalue;
      autoTime();
      int AdjTime = (int)(inputvalue + 0.5);
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill hold time has been set to %i seconds.", AdjTime);
    }
    else
      bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill hold time invalid: must be between 1 and 7200 seconds.");

    autoTime();

    return true;
  }

  if ( command == "kothautotimeon")
  {
    koth.autoTimeOn = true;
    autoTime();
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill automatic time adjustment on.");
    return true;
  }

  if ( command == "kothautotimeoff")
  {
    koth.autoTimeOn = false;
    koth.adjustedTime = koth.TTH;
    autoTime();
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill automatic time adjustment off.");
    return true;
  }

  return false;
}
// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
