//rewrite of braindawg_request.lua
printl("Player Counter Loaded")

local playercount = 0, playersalive = 0;
local steamids = [];
// local resource = FindByClassname(null, "tf_objective_resource");
// local gamerules = FindByClassname(null, "tf_gamerules");
// local playermanager = FindByClassname(null, "tf_player_manager");
local wavestart = false;

::ApplyBuffs <- function(playersalive)
{
    // foreach(_,i in steamids) 
    //     ClientPrint(null, 3, format("player %s lifestate is %d", GetPropString(GetPlayerFromUserID(i), "m_szNetname"), GetPropInt(GetPlayerFromUserID(i), "m_lifeState")));
    

    printl(format("Players Alive: %d", playersalive) );
    ClientPrint(null, 3, format("Players Alive: %d", playersalive));

    if (!wavestart) return;    

    if (playersalive > 3)
    {
        for (local i = 0; i < steamids.len(); i++)
        {
            local player = GetPlayerFromUserID(steamids[i]);

            if (player.GetHealth() < 1) continue;

            player.RemoveCond(TF_COND_CRITBOOSTED_USER_BUFF);
            player.RemoveCond(TF_COND_CRITBOOSTED_CARD_EFFECT);
            player.RemoveCond(TF_COND_OFFENSEBUFF);
            player.RemoveCond(TF_COND_ENERGY_BUFF);
        }
        return;
    }

    if (playersalive <= 3)
    {
        for (local i = 0; i < steamids.len(); i++)
        {
            local player = GetPlayerFromUserID(steamids[i]);

            if (player.GetHealth() < 1) continue;

            EntFireByHandle(player, "RollRareSpell", "", 0.0, null, null);
            DoEntFire("tankboss_ghost", "SetSpeed", "55", 0.0, null, null);
        }
    }
    if (playersalive <= 2)
    {
        for (local i = 0; i < steamids.len(); i++)
        {
            local player = GetPlayerFromUserID(steamids[i]);

            if (player.GetHealth() < 1) continue;

            //we apply cola and banner minicrits to mitigate losing the effect
            //if a scout uses cola while under buff banner effect this might still get cleared
            //just don't do that lmao
            player.AddCond(TF_COND_OFFENSEBUFF);
            player.AddCond(TF_COND_ENERGY_BUFF);
            DoEntFire("tankboss_ghost", "SetSpeed", "55", 0.0, null, null)
        }
    }
    if (playersalive < 2)
    {
        for (local i = 0; i < steamids.len(); i++)
        {
            local player = GetPlayerFromUserID(steamids[i]);
            
            if (player.GetHealth() < 1) continue;
            
            //canteen crits give sentry firing speed
            //we apply 2 crit conds incase user uses a canteen
            player.AddCond(TF_COND_CRITBOOSTED_USER_BUFF);
            player.AddCond(TF_COND_CRITBOOSTED_CARD_EFFECT);
            DoEntFire("tankboss_ghost", "SetSpeed", "55", 0.0, null, null)
        }
    }
}

//start at max players, then decrement for every dead/disconnected player
::CountAlivePlayers <- function()
{
    if (!wavestart) return;

    local playersalive = steamids.len();
    for (local i = 0; i < steamids.len(); i++)
    {
        if (GetPlayerFromUserID(steamids[i]) == null) steamids.remove(i);
        local player = GetPlayerFromUserID(steamids[i]);
        // printl(i + " : " + player.GetHealth() + " : " + GetPropInt(player, "m_lifeState"))
        
        //bug or something
        //player.GetHealth() always returns 1 even if the player is dead?
        //we shitfix this by not allowing player to survive at 1hp in the player_hurt event lol
        if (GetPropInt(player, "m_lifeState") > 0 || player.GetHealth() < 2)
        {
            playersalive--;
        }
    }

    //fail the wave if everyone dies
    if (playersalive == 0) 
    {
        DoEntFire("bots_win", "RoundWin", "", 0.0, null, null); 
        return;
    }
    //give out buffs on low player count
    DoEntFire("tf_gamerules", "RunScriptCode","ApplyBuffs("+playersalive+")", 0.1, null, null);
}
function OnGameEvent_player_hurt(params)
{
    if (IsPlayerABot(GetPlayerFromUserID(params.userid)) || GetPlayerFromUserID(params.userid).GetTeam() != TF_TEAM_PVE_DEFENDERS || params.health > 1) return;

    if (params.health == 1)
        GetPlayerFromUserID(params.userid).AddCustomAttribute("health drain", -1, 0.0)
}
function OnGameEvent_mvm_wave_complete(params) { wavestart = false; }

function OnGameEvent_mvm_reset_stats(params) { wavestart = false; }

function OnGameEvent_mvm_wave_failed(params) { wavestart = false; }

function OnGameEvent_mvm_begin_wave(params) 
{   
    wavestart = true; 
    CountAlivePlayers();
}

//add players to the array
//this only checks the playercount, playersalive is handled in the CountAlivePlayers() function
//we use post_inventory_application instead of player_spawn because this script is fired on wave init

function OnGameEvent_post_inventory_application(params) 
{
    if (IsPlayerABot(GetPlayerFromUserID(params.userid) || GetPlayerFromUserID(params.userid).GetTeam() != TF_TEAM_PVE_DEFENDERS)) return;

    GetPlayerFromUserID(params.userid).RemoveCustomAttribute("health drain");

    for (local i = 0; i < steamids.len(); i++) if (steamids[i] == params.userid) return;
    
    steamids.append(params.userid);
    playercount = steamids.len()
    printl(format("Players: %d", playercount));
    
}

function OnGameEvent_player_disconnect(params)
{
    local player = GetPlayerFromUserID(params.userid)

    if (IsPlayerABot(player) || player.GetTeam() != TF_TEAM_PVE_DEFENDERS) return;

    //idc enough to fix this correctly just force fail the wave when there's 0 players

    for (local i = 0; i <= steamids.len(); i++) if (steamids[i] == params.userid) steamids.remove(i);
    
    //wrong
    // foreach(_, v in steamids) if (v == params.userid) steamids.remove(v);

    playercount = steamids.len()
    printl(format("Players: %d", playercount) );

    if (playercount < 1 && wavestart)
    {
        DoEntFire("bots_win", "RoundWin", "", 0.0, null, null);
        return;
    }

    CountAlivePlayers();
}

function OnGameEvent_player_spawn(params)
{
    local player = GetPlayerFromUserID(params.userid)

    //set normal blood for bots (does this work?)
    if (IsPlayerABot(player) || player.GetTeam() != TF_TEAM_PVE_DEFENDERS) SetPropInt(player, "m_bloodColor", 2); return;
    
    CountAlivePlayers();
}

function OnGameEvent_player_death(params)
{
    //ignore bots and dead ringer (dead ringer triggers this event but player health is still > 1)
    if (IsPlayerABot(GetPlayerFromUserID(params.userid)) || GetPlayerFromUserID(params.userid).GetTeam() != TF_TEAM_PVE_DEFENDERS || GetPlayerFromUserID(params.userid).GetHealth() > 1) return;

    //force respawn in pre-round to avoid fucking up the counter as soon as the wave starts
    //still technically possible, but harder to time
    if (!wavestart) 
    {
        DoEntFire("tf_gamerules", "RunScriptCode", format("GetPlayerFromUserID(%d).ForceRespawn()", params.userid), 0.0, null, null);
        return;
    }
    // DoEntFire("tf_gamerules", "CallScriptFunction", "CountAlivePlayers", 1, null, null)
    CountAlivePlayers();
}
__CollectGameEventCallbacks(this)