// 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: 4 ***
// c-basic-offset: 4 ***
// indent-tabs-mode: nil ***
// End: ***
// ex: shiftwidth=4 tabstop=4
