// Kamikaze! - Credits AssKicR & Scarzzurs/The_Unbound & {HOJ} Batman

/* CVARS - copy and paste to shconfig.cfg

//Kamikaze
kamikaze_level 0
kamikaze_radius 300            //Radius of people affected by blast
kamikaze_fuse 15            //# of seconds before kamikaze blows Up
kamikaze_maxdamage 125            //Maximum damage to deal to a player

*/

#include <superheromod>

// GLOBAL VARIABLES
new gHeroID
new const gHeroName[] = "Kamikaze"
new bool:gHasKamikaze[SH_MAXSLOTS+1]
new gFuseTime[SH_MAXSLOTS+1]
new const gSoundCountdown[] = "buttons/blip2.wav"
new const gSoundFvox[11][] = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"}
new gSpriteSmoke, gSpriteWhite, gSpriteFire
new gMsgSync
new pCvarRadius, pCvarFuse, pCvarMaxDamage
//----------------------------------------------------------------------------------------------
public plugin_init()
{
    // Plugin Info
    register_plugin("SUPERHERO Kamikaze", SH_VERSION_STR, "AssKicR/JTP10181")

    register_dictionary("sh_kamikaze.txt")

    // DO NOT EDIT THIS FILE TO CHANGE CVARS, USE THE SHCONFIG.CFG
    new pcvarLevel = register_cvar("kamikaze_level", "0")
    pCvarRadius = register_cvar("kamikaze_radius", "300")
    pCvarFuse = register_cvar("kamikaze_fuse", "15")
    pCvarMaxDamage = register_cvar("kamikaze_maxdamage", "125")

    // FIRE THE EVENTS TO CREATE THIS SUPERHERO!
    gHeroID = sh_create_hero(gHeroName, pcvarLevel)
    sh_set_hero_info(gHeroID, "Blow Self Up", "Blow up the enemies with a Kamikaze attack")
    sh_set_hero_bind(gHeroID)

    // Timer loop
    set_task(1.0, "kamikaze_check", _, _, _, "b")

    gMsgSync = CreateHudSyncObj()
}
//----------------------------------------------------------------------------------------------
public plugin_precache()
{
    gSpriteSmoke = precache_model("sprites/steam1.spr")
    gSpriteWhite = precache_model("sprites/white.spr")
    gSpriteFire = precache_model("sprites/explode1.spr")
    precache_sound(gSoundCountdown)
}
//----------------------------------------------------------------------------------------------
public sh_hero_init(id, heroID, mode)
{
    if ( gHeroID != heroID ) return

    gHasKamikaze[id] = mode ? true : false

    sh_debug_message(id, 1, "%s %s", gHeroName, mode ? "ADDED" : "DROPPED")
}
//----------------------------------------------------------------------------------------------
public sh_client_spawn(id)
{
    gPlayerInCooldown[id] = false
    gFuseTime[id] = 0
}
//----------------------------------------------------------------------------------------------
public sh_hero_key(id, heroID, key)
{
    if ( gHeroID != heroID || sh_is_freezetime() ) return
    if ( !is_user_alive(id) || !gHasKamikaze[id] ) return

    if ( key == SH_KEYDOWN ) {
        // Let them know they already used their ultimate if they have
        if ( gPlayerInCooldown[id] ) {
            sh_sound_deny(id)
            return
        }

        gPlayerInCooldown[id] = true
        gFuseTime[id] = get_pcvar_num(pCvarFuse)
    }
}
//----------------------------------------------------------------------------------------------
public kamikaze_check()
{
    if ( !sh_is_active() ) return

    static players[SH_MAXSLOTS], playerCount, player, fuseTime, i
    get_players(players, playerCount, "ah")

    for ( i = 0; i < playerCount; i++ ) {
        player = players[i]

        if ( !gHasKamikaze[player] ) continue

        fuseTime = gFuseTime[player]

        if ( fuseTime > 0 ) {
            emit_sound(player, CHAN_ITEM, gSoundCountdown, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)

            gFuseTime[player] = --fuseTime

            if ( fuseTime <= 0 ) {
                blow_up(player)
            }
            else {
                // Decrement the counter
                set_hudmessage(0, 100, 200, 0.05, 0.65, 2, 0.02, 1.0, 0.01, 0.1, -1)
                ShowSyncHudMsg(player, gMsgSync, "%L", LANG_PLAYER, "SH_KAMIKAZE_YOU_EXPLODE", fuseTime, fuseTime == 1 ? "" : "s")

                // Say Time Remaining to the User Only.
                if ( fuseTime == 11 ) {
                    client_cmd(player, "spk ^"fvox/remaining^"")
                }
                else if ( fuseTime < 11 ) {
                    client_cmd(player, "spk ^"fvox/%s^"", gSoundFvox[fuseTime])
                }
            }
        }
    }
}
//----------------------------------------------------------------------------------------------
public blow_up(id)
{
    if ( !is_user_connected(id) ) return

    new Float:dRatio, Float:distanceBetween, damage
    new Float:idOrigin[3], Float:playerOrigin[3], name[32]
    new Float:dmgRadius = get_pcvar_float(pCvarRadius)
    new maxDamage = get_pcvar_num(pCvarMaxDamage)
    new FFOn = sh_friendlyfire_on()
    new CsTeams:idTeam = cs_get_user_team(id)

    gFuseTime[id] = 0

    pev(id, pev_origin, idOrigin)

    // blowup even if dead
    explode_effect(idOrigin)

    // Kill id first, if alive, because he is the bomb
    if ( is_user_alive(id) ) {
        set_pev(id, pev_takedamage, DAMAGE_AIM)        // Make sure they dont have godmode so we can kill them
        sh_extra_damage(id, id, 0, "suicide bomb", _, SH_DMG_KILL)
    }

    get_user_name(id, name, 31)
    set_hudmessage(0, 100, 200, 0.05, 0.65, 2, 0.02, 1.0, 0.01, 0.1, -1)
    ShowSyncHudMsg(0, gMsgSync, "%L", LANG_PLAYER, "SH_KAMIKAZE_HAS_EXPLODED", name)

    new players[SH_MAXSLOTS], playerCount, player
    get_players(players, playerCount, "ah")

    for ( new i = 0; i < playerCount; i++ ) {
        player = players[i]

        pev(player, pev_origin, playerOrigin)
        distanceBetween = vector_distance(idOrigin, playerOrigin)

        if ( distanceBetween <= dmgRadius ) {
            if ( FFOn || idTeam != cs_get_user_team(player) ) {
                dRatio = distanceBetween / dmgRadius
                damage = maxDamage - floatround(maxDamage * dRatio)
                if ( !damage ) damage = 1    // Incase damage cvar is really low cause something if within the radius 
                sh_extra_damage(player, id, damage, "kamikaze bomb", _, SH_DMG_NORM, true)
            }

            // Add some push and shake effects instead of dmgStun later, and cause it on everyone within radius
        }
    }
}
//----------------------------------------------------------------------------------------------
explode_effect(Float:vec1[3])
{
    // blast circles
    engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, vec1, 0)
    write_byte(TE_BEAMCYLINDER)    // 21
    engfunc(EngFunc_WriteCoord, vec1[0])
    engfunc(EngFunc_WriteCoord, vec1[1])
    engfunc(EngFunc_WriteCoord, vec1[2] + 16)
    engfunc(EngFunc_WriteCoord, vec1[0])
    engfunc(EngFunc_WriteCoord, vec1[1])
    engfunc(EngFunc_WriteCoord, vec1[2] + 1936)
    write_short(gSpriteWhite)
    write_byte(0)        // startframe
    write_byte(0)        // framerate
    write_byte(2)        // life
    write_byte(20)        // width
    write_byte(0)        // noise
    write_byte(188)        // r
    write_byte(220)        // g
    write_byte(255)        // b
    write_byte(255)        // brightness
    write_byte(0)        // speed
    message_end()

    // Explosion2
    message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
    write_byte(TE_EXPLOSION2)    // 12
    engfunc(EngFunc_WriteCoord, vec1[0])
    engfunc(EngFunc_WriteCoord, vec1[1])
    engfunc(EngFunc_WriteCoord, vec1[2])
    write_byte(188)        // scale in 0.1's
    write_byte(10)        // framerate
    message_end()

    // Explosion
    engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, vec1, 0)
    write_byte(TE_EXPLOSION)    // 3
    engfunc(EngFunc_WriteCoord, vec1[0])
    engfunc(EngFunc_WriteCoord, vec1[1])
    engfunc(EngFunc_WriteCoord, vec1[2])
    write_short(gSpriteFire)
    write_byte(60)        // scale in 0.1's
    write_byte(10)        // framerate
    write_byte(TE_EXPLFLAG_NONE)        // flags
    message_end()

    // Smoke
    engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, vec1, 0)
    write_byte(TE_SMOKE)        // 5
    engfunc(EngFunc_WriteCoord, vec1[0])
    engfunc(EngFunc_WriteCoord, vec1[1])
    engfunc(EngFunc_WriteCoord, vec1[2])
    write_short(gSpriteSmoke)
    write_byte(10)        // scale in 0.1's
    write_byte(10)        // framerate
    message_end()
}
//----------------------------------------------------------------------------------------------
public sh_client_death(victim)
{
    if ( victim < 1 || victim > sh_maxplayers() ) return

    if ( gFuseTime[victim] > 0 ) {
        // Delay to avoid recursion
        set_task(0.1, "blow_up", victim)
    }
}
//----------------------------------------------------------------------------------------------
public client_connect(id)
{
    gHasKamikaze[id] = false
    gFuseTime[id] = 0
}
//----------------------------------------------------------------------------------------------
public client_disconnected(id)
{
    gHasKamikaze[id] = false
    gFuseTime[id] = 0
}
//----------------------------------------------------------------------------------------------