/*
 * ============================================================================
 *
 *  Zombie:Reloaded
 *
 *  File:          healthregen.inc
 *  Type:          Core
 *  Description:   Functions for managing health regeneration on a client.
 *
 *  Copyright (C) 2009-2013  Greyscale, Richard Helgeby
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

new ClientHealthRegenAmount[MAXPLAYERS + 1];
new ClientHealthRegenMax[MAXPLAYERS + 1];
new Handle:tHealthRegen[MAXPLAYERS + 1];

/**
 * Resets all timer handles. (called from classevents)
 */
ClassHealthRegenInit()
{
    for (new client = 0; client < MAXPLAYERS + 1; client++)
    {
        tHealthRegen[client] = INVALID_HANDLE;
    }
}

/**
 * Prepares and starts HP regeneration on a client.
 *
 * @param client        The client to apply HP regeneration on.
 * @param interval      Regeneration interval.
 * @param amount        HP amount per interval.
 * @param max           Regeneration limit. Don't give HP if player HP is above
 *                      this value.
 */
ClassHealthRegenInitClient(client, Float:interval, amount, max)
{
    ClientHealthRegenAmount[client] = amount;
    ClientHealthRegenMax[client] = max;
    ClassHealthRegenStart(client, interval);
}

/**
 * Starts HP regeneration on a client using current client settings.
 *
 * @param client        The client index.
 * @param interval      Regeneration interval.
 */
ClassHealthRegenStart(client, Float:interval)
{
    // Stop timer if it already exist.
    ClassHealthRegenStop(client);

    // Create new timer.
    tHealthRegen[client] = CreateTimer(interval, ClassHealthRegenTimer, client, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}

/**
 * Stops HP regeneration on a client.
 *
 * @param client    The client index.
 */
ClassHealthRegenStop(client)
{
    // Kill the timer if it exist.
    if (tHealthRegen[client] != INVALID_HANDLE)
    {
        KillTimer(tHealthRegen[client]);
        tHealthRegen[client] = INVALID_HANDLE;
    }
}

/**
 * Timer callback for HP regeneration.
 */
public Action:ClassHealthRegenTimer(Handle:timer, any:client)
{
    // Kill the timer if the player is dead or not in game.
    if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
    {
        tHealthRegen[client] = INVALID_HANDLE;
        return Plugin_Stop;
    }

    new health = GetClientHealth(client);

    // Check if the health is below the limit.
    if (health < ClientHealthRegenMax[client])
    {
        if (!GetConVarBool(g_hCvarsList[CVAR_AURA_MZOMBIE]) || !IsMotherZombieNearby(client))
        {
            health += ClientHealthRegenAmount[client]; //default regen
        }
        else
        {
            health += ClientHealthRegenAmount[client] * GetConVarInt(g_hCvarsList[CVAR_AURA_MZOMBIE_MULTIPLIER]); //increased regen when motherzombies are nearby
        }

        // Clamp the health regen to the limit.
        if (health > ClientHealthRegenMax[client])
        {
            health = ClientHealthRegenMax[client];
        }

        // Increase health.
        SetEntityHealth(client, health);
    }

    return Plugin_Continue;
}

/**
 * Returns true if a motherzombie is near the client.
 */
bool:IsMotherZombieNearby(client)
{
    new Float:fVec1[3];
    new Float:fVec2[3];
    GetClientAbsOrigin(client, fVec1);

    for (new i = 1; i <= MaxClients; i++)
    {
        if (!IsClientInGame(i) || !IsPlayerAlive(i) || !InfectIsClientMotherZombie(i))
            continue;

        GetClientAbsOrigin(i, fVec2);

        if (GetVectorDistance(fVec1, fVec2, false) <= GetConVarFloat(g_hCvarsList[CVAR_AURA_MZOMBIE_RANGE]))
            return true;
    }

    return false;
}