//----------------------------------------------------------------------------------------------
// Counter Zombie Class Mod Addon
//----------------------------------------------------------------------------------------------


//--- Created by Streamy


//---------,
// Version |
//---------*

#define VERSION "1.1"



//-----------,
// Changelog |
//-----------*
/*

Version 1.1 - 30/11/08 - Ability to edit each class's money.
                       - Glowing effect added for heal.
                       - Medic class description edited.

Version 1.0 - 20/11/08 - Initial Release.

*/



/*--------,
// Readme |
//--------*

--- NOTE!
- This plugin does not contain any CVARs as most of the settings should only be adjusted once.

--- Terms and Conditions:
- This plugin is freeware.
- You may use and distribute this freely.
- You may alter the source code provided you do not change any of the following:
-- 1. Credits.
-- 2. register_plugin native.

--- Credits:
- Created by Streamy.
- Minda for ideas. (www.mrpanda.net)
- aDonis a.k.a SCHWEDEN for ideas and for kicking my lazy bum ass to finish this plugin xD.
- Cheap_Suit for ESP.

--- Plugin:
- At the start of each round, a menu opens to allow counter zombies(CTs) to choose their class.
- Each class has its pros and cons. So choose wisely.

--- Workable Zombie Mods:
- Mini Midget's Zombie Swarm 2.4
- Infection zombie mods like Zombie Plague might cause shooting problems with Sentry Guns due to the team change when you get infected.
However, the sentry guns can still act as blocks to block out access to some areas.
The classes can still function like normal though.

--- Recommended Addons:
- Pump Knockback by v3x & Chronic
- Sentry Guns by Johnny got his gun
- Laser/Tripmine Entity (Don't know the original author, this plugin was ripped multiple times.)



//---------------------------------------------,
// How to allow mechanics to build structures: |
//---------------------------------------------*

With this plugin alone, mechanics CANNOT build anything!
You MUST add your own plugins. (Eg. Sentry Guns / Laser mines)
The mechanic class gives you $16000 while the other classes have $8000. (Customizable)
Hence, mechanic is the only class with money, and thus, the only class which can build things.

The reason why I did NOT simply insert their codes in this plugin for convenience, is because...
I believe in originality. Hence, I think you should get the code from original authors.
Even if it means I'll get a whole page of questions...

Anyways it goes in 3 simple steps:

Step ONE: Find desired plugin(s) for mechanic. Download and install it.
Step TWO: Customise the plugin(s) such that it costs a lot of money to build.
Step THREE: Compile / Restart server if needed to make changes take effect.

If you still have NO IDEA what I'm talking about, I have a separate "noob-proof" package.
All you have to do is extract it and you're done.
It would already be customised and stuff... So just sit back and relax...

Thank You.



//---------,
// Classes |
//---------*



--- Currently there are 3 classes are available:

--- Hunter:
- Master of Darkness.
- Solo Class.
- Hunts zombies with a passion.

--- Medic
- The hands which heal.
- Support class.
- Heal wounded team mates.

--- Mechanic
- Tools eveready.
- Support class.
- Builds structures to keep zombies at bay.



//--------------,
// ESP Settings |
//--------------*

- Only for Hunter.
- Use ESP to hunt down zombies!!!
*/

#define ESP                    //Comment this out to disable ESP for Hunter.

//Adjust RGB glow of ESP rings:
#define ESP_RED 255            //Red. (Integer)
#define ESP_GREEN 0            //Green. (Integer)
#define ESP_BLUE 0             //Blue. (Integer)

#define ESP_FREQ 1.0           //Adjust frequency of appearance of esp rings. (Float)
#define ESP_RADIUS 400         //Adjust radius of ESP rings. (Integer)
#define ESP_BRIGHTNESS 200     //Adjust brightness. (1-255) (Integer)



//---------------,
// Heal Settings |
//---------------*
/*
- Only for Medic.
- Input in console: bind f +heal
- To use heal, aim at a CT when you are near him and HOLD F.
- CTs may heal to their class's starting health and armor only.
- The following defines will effect the healing. Customise to your liking.
- However, note that healing effects are only shown if HEAL_FREQ is set to a minimum of 1.0.
- This is so that speed healing freaks who set it to 0.1 or something don't get bugs.
*/

//Add values for these
#define HEAL_HP 25        // Amount of health replenished each heal. (Integer)
#define HEAL_AP 25        // Amount of armor replenished each heal. (Integer)
#define HEAL_FREQ 2.5     // Frequency of heals. (Float)(Seconds)
#define HEAL_RANGE 70     // Range required for medic to heal team mate. (Integer)
#define HEAL_MISC_HP 100  // Default max health to heal up to for an unknown class. (Integer)
#define HEAL_MISC_AP 100  // Default max armor to heal up to for an unknown class. (Integer)

//Commentables (Lol no such word?)
#define HEAL_HURT       // Comment out to enable medics to heal even when hurt.
#define HEAL_SHOW       // Comment out to disable HUD that informs healed user of healer.
#define HEAL_KNIFE      // Comment out to disable the knife out during healing.
#define BLOCK_MEDIC     // Comment out to enable medics to heal other medics.

//Heal Glow Effect
#define HEAL_GLOW       // Comment out to disable glow effect while being healed.
#define GLOW_R 0        // Adjust Red Value. (Integer)
#define GLOW_G 255      // Adjust Green Value. (Integer)
#define GLOW_B 0        // Adjust Blue Value. (Integer)



//----------------,
// Misc. Settings |
//----------------*

#define DELAY 15.0     /*(Float)(Seconds)
- This sets the time in which the class menu will pop up.
- Note that once this menu pops up, the weapon menu in Zombie Plague disappears as well.
- For ZP: Set this value to be the same as the time taken for the first zombie to be chosen.
- For Swarm: Set to 0.1 - 15s or risk getting raped by zombies.*/

#define NIGHTVISION_MODE 2     /*(Integer 0|1|2)
- This is adjusts how the Hunter class recieves nightvision.
- Set to "1" to give nightvision and turn it on automatically.
- Set to "2" to give nightvision but it has to be turned on manually.
- Set to "0" to disable giving of nightvision.*/

//#define WEAPON_OVERIDE
/*Uncomment this if you do want weapons to be restricted for classes and armed with only these:
1.) Hunter   - Auto Shotgun + Desert Eagle
2.) Medic    - M3 (Pump Shotgun) + Desert Eagle
3.) Mechanic - MP5 Navy + Dual Elites.
Note that all weapons are stripped before given the defaults.*/





//------------------------------,
// Counter Zombie Stats Configs |
//------------------------------*
/*

--- Here you may configure the health, armor and speed points of each zombie class.

HP = Health Points. (Integer)
AP = Armor Points. (Integer)
SPD = Speed Points. (Float)
CASH = Amount of cash each class recieves. (Integer)
MSG = Description of class. Must be in quotes (").(String)

For Zombie Plague:
- If you have configured AP to act as a resistor for being infected, adjust AP of classes here.
- Note that if you set AP to 0, you will also disable AP regeneration when being healed by medic.
- Adjust the following values to suit your gameplay style/mod.


===(!Warning!)===

- When you alter the description of the classes, do NOT remove any of the defines!!!
- And you wish to only use one line, do NOT remove the other line!!!
- Just leave it in blank quotes. ("")
- Ensure that the define is still there and the quotes ("") as well...
- Else the plugin will not compile.

Finally, if you are not sure about editing the descriptions then DO NOT TOUCH THEM!!!

*/



//Hunter
#define HUNTER_HP 200
#define HUNTER_AP 100
#define HUNTER_SPD 350.0
#define HUNTER_CASH 8000
#define HUNTER_MSG1 "[AMXX] You are the Hunter!"
#define HUNTER_MSG2 "[AMXX] Hunt down zombies!!!"


//Medic
#define MEDIC_HP 100
#define MEDIC_AP 100
#define MEDIC_SPD 250.0
#define MEDIC_CASH 8000
#define MEDIC_MSG1 "[AMXX] You are a Medic!"
#define MEDIC_MSG2 "[AMXX] bind f +heal --- Aim at a team mate and HOLD F to heal."


//Mechanic
#define MECH_HP 150
#define MECH_AP 100
#define MECH_SPD 300.0
#define MECH_CASH 16000
#define MECH_MSG1 "[AMXX] You are a Mechanic!"
#define MECH_MSG2 "[AMXX] Build structures to keep zombies at bay!!!"



/*

--- Final Notes:
You are now done configuring this plugin. It is now ready for use.
Don't forget to re-compile this to ensure that all changes are applied.

Enjoy!

*/





//----------------------------------------------------------------------------------------------
// The End
//----------------------------------------------------------------------------------------------



















//----------------------------------------------------------------------------------------------
// Source Code
//----------------------------------------------------------------------------------------------



//Includes
#include <amxmodx>
#include <cstrike>
#include <fun>

//Menu Keys
#define Keysclassmenu (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)

//Class Indentities
new bool:speed1[33]
new bool:speed2[33]
new bool:speed3[33]

//Sprite
new white

//Task Unique Id
#define TASK1 33



//----------------------------------------------------------------------------------------------
// Plugin Startup Functions
//----------------------------------------------------------------------------------------------



public plugin_init()
{
    //Plugin Call
    register_plugin("Counter Zombie Class Mod", VERSION, "Streamy") //Do NOT modify.

    //Events
    register_logevent("StartRound", 2, "1=Round_Start")
    register_logevent("EndRound", 2, "0=World triggered", "1=Round_Draw", "1=Round_End")
    register_event("ResetHUD", "Spawn", "be")
    register_event("CurWeapon", "Speeds", "be")
    register_event("Damage", "Damage", "be")
    register_event("DeathMsg", "Death", "a")

    //Client Commands
    register_clcmd( "+heal", "heal")
    register_clcmd( "-heal", "unset_heal")

    //Menu
    register_menucmd(register_menuid("classmenu"), Keysclassmenu, "Pressedclassmenu")

    //Hunter ESP
    #if defined ESP
      set_task(ESP_FREQ, "esp", 0, "", 0, "b")
    #endif
}

public plugin_precache()
{
    white = precache_model("sprites/white.spr")
}



//----------------------------------------------------------------------------------------------
// Menu Functions
//----------------------------------------------------------------------------------------------



public Showclassmenu(id)
{
    if(!is_user_connected(id)) return PLUGIN_HANDLED
    if(!is_user_alive(id)) return PLUGIN_HANDLED

    new CsTeams:team = cs_get_user_team(id)
    if(team == CS_TEAM_CT) {
      new menuBody[512]
      add(menuBody, 511, "\yChoose your survivor class:^n^n")
      add(menuBody, 511, "\w1. Hunter^n")
      add(menuBody, 511, "\w2. Medic^n")
      add(menuBody, 511, "\w3. Mechanic^n")
      show_menu(id, Keysclassmenu, menuBody, -1, "classmenu")
      client_print(id, print_chat, "[AMXX] Select your survivor class!!!")
    }
    return PLUGIN_HANDLED
}

public Pressedclassmenu(id, key)
{
    switch (key) {
      case 0: {
        set_task(0.1,"class1",id)
      }
      case 1: {
        set_task(0.1,"class2",id)
      }
      case 2: {
        set_task(0.1,"class3",id)
      }
    }
    return PLUGIN_HANDLED
}



//----------------------------------------------------------------------------------------------
// Events
//----------------------------------------------------------------------------------------------



public StartRound()
{
    new players[32], pnum, id
    get_players(players, pnum, "a")
    for (new i = 0; i < pnum; i++) {
      id = players[i]
      if(is_user_connected(id)) {
        set_task(0.1, "reset_speed", id)
      }
    }
    return PLUGIN_HANDLED
}

public EndRound()
{
    new players[32], pnum, id
    get_players(players, pnum, "a")
    for (new i = 0; i < pnum; i++) {
      id = players[i]
      if(task_exists(TASK1 + id)) remove_task(TASK1 + id)
    }
    return PLUGIN_HANDLED
}

public Spawn(id)
{
    new CsTeams:team = cs_get_user_team(id)
    if(team == CS_TEAM_CT) {
      set_task(0.1, "reset_speed", id)
      set_task(DELAY, "Showclassmenu", id)
    }
    if(team == CS_TEAM_T) {
      set_task(0.1, "reset_speed", id)
    }
    return PLUGIN_HANDLED
}

public Speeds(id)
{
    #if defined HEAL_KNIFE
      if(task_exists(TASK1 + id)) remove_task(TASK1 + id)
    #endif
    if(speed1[id]) {
      set_user_maxspeed(id, HUNTER_SPD)
    }
    if(speed2[id]) {
      set_user_maxspeed(id, MEDIC_SPD)
    }
    if(speed3[id]) {
      set_user_maxspeed(id, MECH_SPD)
    }
}

public Damage(id)
{
    #if defined HEAL_HURT
      if(task_exists(TASK1 + id)) remove_task(TASK1 + id)
    #endif
    return PLUGIN_HANDLED
}

public Death()
{
    new id = read_data(2)
    if(task_exists(TASK1 + id)) remove_task(TASK1 + id)
    return PLUGIN_CONTINUE
}



//----------------------------------------------------------------------------------------------
// Class Powers
//----------------------------------------------------------------------------------------------



public class1(id)
{
    if(!is_user_alive(id)) return PLUGIN_HANDLED
    new CsTeams:team = cs_get_user_team(id)
    if(team == CS_TEAM_CT) {
      set_user_health(id, HUNTER_HP)
      set_user_armor(id, HUNTER_AP)
      speed1[id] = true

      cs_set_user_money(id, HUNTER_CASH)

      #if defined WEAPON_OVERIDE
        strip_user_weapons(id)
        give_item(id, "weapon_smokegrenade")
        give_item(id, "weapon_hegrenade")
        give_item(id, "weapon_flashbang")
        give_item(id, "weapon_knife")
        give_item(id, "weapon_deagle")
        give_item(id, "weapon_xm1014")
      #endif

      if (!cs_get_user_nvg(id)) {

        #if(NIGHTVISION_MODE == 1)
          cs_set_user_nvg(id, 1)
          engclient_cmd(id, "nightvision")
        #endif

        #if(NIGHTVISION_MODE == 2)
          cs_set_user_nvg(id, 1)
        #endif
      }

      client_print(id, print_chat, HUNTER_MSG1)
      client_print(id, print_chat, HUNTER_MSG2)
    }
    else if(team == CS_TEAM_T) {
      client_print(id, print_chat, "[AMXX] You need to be CT!!!")
    }
    return PLUGIN_HANDLED
}

public class2(id)
{
    if(!is_user_alive(id)) return PLUGIN_HANDLED
    new CsTeams:team = cs_get_user_team(id)
    if(team == CS_TEAM_CT) {
      set_user_health(id, MEDIC_HP)
      set_user_armor(id, MEDIC_AP)
      speed2[id] = true

      cs_set_user_money(id, MEDIC_CASH)

      #if defined WEAPON_OVERIDE
        strip_user_weapons(id)
        give_item(id, "weapon_smokegrenade")
        give_item(id, "weapon_hegrenade")
        give_item(id, "weapon_flashbang")
        give_item(id, "weapon_knife")
        give_item(id, "weapon_deagle")
        give_item(id, "weapon_m3")
      #endif

      client_print(id, print_chat, MEDIC_MSG1)
      client_print(id, print_chat, MEDIC_MSG2)
    }
    else if(team == CS_TEAM_T) {
      client_print(id, print_chat, "[AMXX] You need to be CT!!!")
    }
    return PLUGIN_HANDLED
}

public class3(id)
{
    if(!is_user_alive(id)) return PLUGIN_HANDLED
    new CsTeams:team = cs_get_user_team(id)
    if(team == CS_TEAM_CT) {
      set_user_health(id, MECH_HP)
      set_user_armor(id, MECH_AP)
      speed3[id] = true

      cs_set_user_money(id, MECH_CASH)

      #if defined WEAPON_OVERIDE
        strip_user_weapons(id)
        give_item(id, "weapon_smokegrenade")
        give_item(id, "weapon_hegrenade")
        give_item(id, "weapon_flashbang")
        give_item(id, "weapon_knife")
        give_item(id, "weapon_elite")
        give_item(id, "weapon_mp5navy")
      #endif

      client_print(id, print_chat, MECH_MSG1)
      client_print(id, print_chat, MECH_MSG2)
    }
    else if(team == CS_TEAM_T) {
      client_print(id, print_chat, "[AMXX] You need to be CT!!!")
    }
    return PLUGIN_HANDLED
}



//----------------------------------------------------------------------------------------------
// Heal Functions
//----------------------------------------------------------------------------------------------



public heal(id)
{
    if(!is_user_alive(id) || !speed2[id]) return PLUGIN_HANDLED
    set_task(HEAL_FREQ, "heal_team", TASK1 + id, "", 0, "b")
    #if defined HEAL_KNIFE
      engclient_cmd(TASK1 + id, "weapon_knife")
    #endif
    return PLUGIN_HANDLED
}

public unset_heal(id)
{
    if(task_exists(TASK1 + id)) remove_task(TASK1 + id)
    #if defined HEAL_KNIFE
      new task1_id2 = id - TASK1
      engclient_cmd(task1_id2, "lastinv")
    #endif
    return PLUGIN_HANDLED
}

public heal_team(id)
{

    new task1_id = id - TASK1

    if(!is_user_alive(task1_id) || !speed2[task1_id]) return PLUGIN_CONTINUE
    new vid, vbody
    get_user_aiming(task1_id, vid, vbody, HEAL_RANGE)

    if(vid == 0.0) return PLUGIN_CONTINUE
    if(!is_user_alive(vid)) return PLUGIN_CONTINUE

    if(get_user_team(task1_id) == get_user_team(vid)) {

      #if defined BLOCK_MEDIC
        if(speed2[vid]) return PLUGIN_CONTINUE
      #endif

      if(speed1[vid]) {

        new oldhealth1 = get_user_health(vid) + HEAL_HP

        if(oldhealth1 < HUNTER_HP) {
          set_user_health(vid, oldhealth1)
        } else {
          set_user_health(vid, HUNTER_HP)
        }

        new oldarmor1 = get_user_armor(vid) + HEAL_AP

        if(oldarmor1 < HUNTER_AP) {
          set_user_armor(vid, oldarmor1)
        } else {
          set_user_armor(vid, HUNTER_AP)
        }

      }

      if(speed2[vid]) {

        new oldhealth2 = get_user_health(vid) + HEAL_HP

        if(oldhealth2 < MEDIC_HP) {
          set_user_health(vid, oldhealth2)
        } else {
          set_user_health(vid, MEDIC_HP)
        }

        new oldarmor2 = get_user_armor(vid) + HEAL_AP

        if(oldarmor2 < MEDIC_AP) {
          set_user_armor(vid, oldarmor2)
        } else {
          set_user_armor(vid, MEDIC_AP)
        }

      }

      if(speed3[vid]) {

        new oldhealth3 = get_user_health(vid) + HEAL_HP

        if(oldhealth3 < MECH_HP) {
          set_user_health(vid, oldhealth3)
        } else {
          set_user_health(vid, MECH_HP)
        }

        new oldarmor3 = get_user_armor(vid) + HEAL_AP

        if(oldarmor3 < MECH_AP) {
          set_user_armor(vid, oldarmor3)
        } else {
          set_user_armor(vid, MECH_AP)
        }

      }

      else {

        new oldhealth4 = get_user_health(vid) + HEAL_HP

        if(oldhealth4 < HEAL_MISC_HP) {
          set_user_health(vid, oldhealth4)
        } else {
          set_user_health(vid, HEAL_MISC_HP)
        }

        new oldarmor4 = get_user_armor(vid) + HEAL_AP

        if(oldarmor4 < HEAL_MISC_AP) {
          set_user_armor(vid, oldarmor4)
        } else {
          set_user_armor(vid, HEAL_MISC_AP)
        }

      }

      if(HEAL_FREQ >= 1.0) {

        #if defined HEAL_SHOW
          //Make allowances for the code to run.
          new Float:fade = HEAL_FREQ - 0.5
          new name[33]
          get_user_name(task1_id, name, 33)
          set_hudmessage(255, 255, 255, -1.0, 0.25, 0, 1.0, fade, 0.1, 0.1, 4)
          show_hudmessage(vid, "<%s> is healing you...", name)
        #endif

        #if defined HEAL_GLOW
          //Make allowances for the code to run.
          new Float:fade2 = HEAL_FREQ - 0.5
          message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, vid)
          write_short(1<<10)
          write_short(1<<10)
          write_short(0x0000)
          write_byte(GLOW_R)
          write_byte(GLOW_G)
          write_byte(GLOW_B)
          write_byte(75)
          message_end()
          set_user_rendering(vid, kRenderFxGlowShell, GLOW_R, GLOW_G, GLOW_B, kRenderNormal, 25)
          set_task(fade2, "Unglow", vid)
       #endif

      }

    }
    return PLUGIN_CONTINUE
}



//----------------------------------------------------------------------------------------------
// Unglow Function
//----------------------------------------------------------------------------------------------



public Unglow(vid)
{
    set_user_rendering(vid, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
    return PLUGIN_CONTINUE
}



//----------------------------------------------------------------------------------------------
// Speed Reset Function
//----------------------------------------------------------------------------------------------



public reset_speed(id)
{
    if(!is_user_connected(id)) {
      speed1[id] = false
      speed2[id] = false
      speed3[id] = false
    }
    return PLUGIN_CONTINUE
}



//----------------------------------------------------------------------------------------------
// ESP Function
//----------------------------------------------------------------------------------------------



public esp()
{
    new players[32], pnum, id
    get_players(players, pnum, "a")
    for (new i = 0; i < pnum; i++) {
      id = players[i]
      if(is_user_alive(id) && speed1[id]) {
        for(new zombie = 1; zombie <= get_maxplayers(); zombie++) {
          if(is_user_alive(zombie)) {
            if(cs_get_user_team(id) != cs_get_user_team(zombie)) {
              if((zombie != id)) {
                new vec1[3]
                get_user_origin(zombie, vec1, 0)
                message_begin(MSG_ONE, SVC_TEMPENTITY, vec1, id)
                write_byte(21)
                write_coord(vec1[0])
                write_coord(vec1[1])
                write_coord(vec1[2] +16)
                write_coord(vec1[0])
                write_coord(vec1[1])
                write_coord(vec1[2] + ESP_RADIUS)
                write_short(white)
                write_byte(0)
                write_byte(1)
                write_byte(6)
                write_byte(8)
                write_byte(1)
                write_byte(ESP_RED)
                write_byte(ESP_GREEN)
                write_byte(ESP_BLUE)
                write_byte(ESP_BRIGHTNESS)
                write_byte(0)
                message_end()
              }
            }
          }
        }
      }
    }
}



//----------------------------------------------------------------------------------------------
// End of File
//----------------------------------------------------------------------------------------------