/*******************************************************************************
                               Ultimate Fake C4

  Version: 0.7
  Author: Grind & KRoTaL (Original Author)
  Converted to AMXX by Grind (grindordie@gmail.com) 
  
  Thanks to k007 & teame06 for helping with some bugs.

  Players can plant fake c4s with the "amx_fakec4" command.
  These fake c4s look real: model + sounds + ledglow.
  Players can defuse fake c4s (more quickly with a defuse kit).
  If you defuse a fake c4, you'll see a nice message. :)
  Fake c4s last mp_c4timer seconds.
  Plant fake c4s around the real bomb if you want to annoy the ct team. :-d


  Cvars:

  fakec4_adminonly 0  - 0: all the terrorists can plant fake c4s
                        1: only the admins with the ADMIN_SLAY flag can plant fake c4s

  fakec4_ctdefuse 1   - 0: all the players can defuse fake c4s
                        1: only the ct team can defuse fake c4s

  fakec4_maxnum 1   - sets the maximum number of fake c4s a player is allowed to plant in a round
  
  fakec4_maxdist 0  - non-admin players can't plant a fake c4 if the distance between them and the real bomb is greater than this value
                      set to 0 to disable this check
  
  fakec4_explosion 0 - 0: plays the "witch" sound
                       1: real explosion (sprites/sounds) that doesn't hurt players in the area
                       2: real explosion (sprites/sounds) that hurts/kills players in the area
                       
  fakec4_time -1   -   how many seconds before the fake4 explodes (-1 = mp_c4timer value)



*******************************************************************************/

#include <amxmodx>
#include <amxmisc>
#include <fun>
#include <engine>


#define ADMIN_FAKEC4 ADMIN_SLAY

#define MAX_FAKEC4 64

#define RADIUS_EXPLOSION 1200.0

/******************************************************************************/

#define OFFSET_DEFUSE_PLANT 193
#define HAS_DEFUSE_KIT (1<<16)

new spr_ledglow
new Float:g_c4_timer[MAX_FAKEC4]
new g_c4_num
new g_c4_count[33]
new g_c4_id[MAX_FAKEC4]
new g_defusing[33]
new g_origin1[3], g_origin2[3], Float:g_forigin2[3]
new g_msgSendAudio, g_msgTextMsg, g_msgBarTime, g_msgScreenShake

new g_sprExplosion
new g_sprSmoke
#define MAX_TE_SPRITES 5
new g_TE_SPRITES_tab[MAX_TE_SPRITES]
new g_TE_SPRITES_names[MAX_TE_SPRITES][] = {
"sprites/cexplo.spr",
"sprites/dexplo.spr",
"sprites/eexplo.spr",
"sprites/gexplo.spr",
"sprites/zerogxplode.spr"
}

public plugin_init()
{
  register_plugin("Ultimate Fake C4", "0.7", "Grind")
  register_concmd("amx_fakec4", "plant_c4", 0, "- plants a fake c4")
  register_cvar("fakec4_adminonly", "0")
  register_cvar("fakec4_ctdefuse", "1")
  register_cvar("fakec4_maxnum", "1")
  register_cvar("fakec4_maxdist", "0")
  register_cvar("fakec4_explosion", "1")
  register_cvar("fakec4_time", "-1")

  register_event("ResetHUD","reset_hud","b")
  register_event("TextMsg", "remove_c4", "a", "2&#Game_C", "2&#Game_w")
  register_event("SendAudio", "delay_remove_c4", "a", "2=%!MRAD_terwin", "2=%!MRAD_ctwin", "2=%!MRAD_rounddraw")
  g_c4_num = 0
  g_msgSendAudio = get_user_msgid("SendAudio")
  g_msgTextMsg = get_user_msgid("TextMsg")
  g_msgBarTime = get_user_msgid("BarTime")
  g_msgScreenShake = get_user_msgid("ScreenShake")
}

public plugin_precache()
{
  precache_sound("weapons/c4_explode1.wav")
  precache_sound("radio/negative.wav")
  precache_sound("weapons/c4_plant.wav")
  precache_sound("weapons/c4_disarm.wav")
  precache_sound("weapons/c4_beep1.wav")
  precache_sound("weapons/c4_beep2.wav")
  precache_sound("weapons/c4_beep3.wav")
  precache_sound("weapons/c4_beep4.wav")
  precache_sound("weapons/c4_beep5.wav")
  precache_sound("radio/bombpl.wav")
  precache_model("models/w_c4.mdl")
  spr_ledglow = precache_model("sprites/ledglow.spr")
  g_sprSmoke = precache_model("sprites/steam1.spr")
  g_sprExplosion = precache_model("sprites/fexplo.spr")
  for(new i = 0; i < MAX_TE_SPRITES; i++) {
    g_TE_SPRITES_tab[i] = precache_model(g_TE_SPRITES_names[i])
  }
}

public reset_hud(id)
{
  g_defusing[id] = 0
  g_c4_count[id] = 0
}

public delay_remove_c4() {
  set_task(4.5, "remove_c4", 1238779)
}

public remove_c4()
{
  new players[32], inum
  get_players(players, inum, "c")
  for(new i = 0 ; i < inum ; i++)
  {
    client_cmd(players[i], "-use")
    message_begin( MSG_ONE, g_msgBarTime, {0,0,0}, players[i] )
    write_byte( 0 )
    write_byte( 0 )
    message_end()
  }
  new iEntity = find_ent_by_class(-1, "fake_c4")
  while(iEntity > 0)
  {
    if(task_exists(1234567+iEntity))
      remove_task(1234567+iEntity)
    if(task_exists(2345678+iEntity))
      remove_task(2345678+iEntity)
    remove_entity(iEntity)
    iEntity = find_ent_by_class(-1, "fake_c4")
  }
  g_c4_num = 0
  return PLUGIN_CONTINUE
}

public plant_c4(id)
{
  if(!(get_user_flags(id) & ADMIN_FAKEC4) && get_cvar_num("fakec4_adminonly") == 1) {
    console_print(id, "[AMX] 你沒有對那指令的權限")
    return PLUGIN_HANDLED
  }

  new fakec4_maxnum = get_cvar_num("fakec4_maxnum")
  if(g_c4_count[id] >= fakec4_maxnum) {
    console_print(id, "[AMX] You can only plant %d fake c4(s) in a round.", fakec4_maxnum)
    client_print(id, print_chat, "[AMX] 你只能安裝 %d 假c4(s) 在一個回合中。", fakec4_maxnum)
    return PLUGIN_HANDLED
  }

  if(!(get_user_flags(id) & ADMIN_FAKEC4))
  {
    new model[32]
    new ent = find_ent_by_class(-1, "grenade")
    while(ent > 0) {
      entity_get_string(ent, EV_SZ_model, model, 31)
      if(equal(model, "models/w_c4.mdl")) break
      ent = find_ent_by_class(ent, "grenade")
    }
    if(ent > 0) {
      new maxdist = get_cvar_num("fakec4_maxdist")
      new curdist = get_entity_distance(id, ent)
      if(curdist > maxdist) {
        console_print(id, "[AMX] You can't plant so far away from the real bomb (maxdist=%d, your dist=%d).", maxdist, curdist)
        client_print(id, print_chat, "[AMX] 你不能安裝在距離真正的c4太遠的地方 (maxdist=%d, your dist=%d).", maxdist, curdist)
        return PLUGIN_HANDLED
      }
    }
  }
  
  if(g_c4_num >= MAX_FAKEC4) {
    console_print(id, "[AMX] Too many fake c4s on the map.")
    client_print(id, print_chat, "[AMX] 在地圖上的假c4太多了。")
    return PLUGIN_HANDLED
  }
  
  new c4_ent = create_entity("info_target")

  if(c4_ent <= 0) {
    return PLUGIN_HANDLED
  }

  entity_set_string(c4_ent, EV_SZ_classname, "fake_c4")

  entity_set_int(c4_ent, EV_INT_solid, 2)
  entity_set_int(c4_ent, EV_INT_movetype, 6)
  entity_set_model(c4_ent, "models/w_c4.mdl")

  entity_set_size(c4_ent, Float:{-1.0,-1.0,-0.000001}, Float:{1.0,1.0,0.000001})

  new Float:PlayerOrigin[3]
  entity_get_vector(id, EV_VEC_origin, PlayerOrigin)
  entity_set_origin(c4_ent, PlayerOrigin)

  entity_set_edict(c4_ent, EV_ENT_owner, id)
  set_task(1.8, "reset_owner", c4_ent)

  emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_plant.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)

  g_c4_id[g_c4_num] = c4_ent

  message_begin(MSG_BROADCAST, g_msgSendAudio, {0,0,0}, 0)
  write_byte(0)
  write_string("%!MRAD_BOMBPL")
  message_end()

  message_begin(MSG_ALL, g_msgTextMsg, {0,0,0}, 0)
  write_byte(4)
  write_string("#Bomb_Planted")
  message_end()

  client_cmd(0, "spk radio/bombpl.wav")

  new Float:timer = float(get_cvar_num("fakec4_time"))
  if(timer == -1.0) timer = get_cvar_float("mp_c4timer")
  
  if(timer < 2.0) {
    new fakec4_explosion = get_cvar_num("fakec4_explosion")
    switch(fakec4_explosion) {
      case 0: {
        emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_explode1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
      }
      case 1: {
        doExplosion(c4_ent, 0)
        return PLUGIN_HANDLED
      }
      case 2: {
        doExplosion(c4_ent, 1)
        return PLUGIN_HANDLED
      }
    }
    remove_entity(c4_ent)
    return PLUGIN_HANDLED
  }
  
  g_c4_timer[g_c4_num] = timer - 1.48

  new param[3]
  param[0]= c4_ent
  param[1]= g_c4_num

  set_task(2.0,"c4_ledglow",1234567+c4_ent,param,2,"b")
  set_task(1.48,"c4_sound",2345678+c4_ent,param,2,"b")

  g_c4_num++
  g_c4_count[id]++

  return PLUGIN_HANDLED
}

public reset_owner(c4_ent)
{
  entity_set_edict(c4_ent, EV_ENT_owner, 0)
}

public c4_ledglow(param[])
{
  new c4_ent = param[0]
  if(!is_valid_ent(c4_ent)) {
    remove_task(1234567+c4_ent)
    return
  }

  new Float:forigin[3], origin[3]
  entity_get_vector(c4_ent, EV_VEC_origin, forigin)

  FVecIVec(forigin, origin)

  origin[2] = origin[2] + 5

  message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  write_byte(23)
  write_coord(origin[0])
  write_coord(origin[1])
  write_coord(origin[2])
  write_short(spr_ledglow)
  write_byte(1)
  write_byte(3)
  write_byte(255)
  message_end()

  return
}

public c4_sound(param[])
{
  new c4_ent = param[0]
  if(!is_valid_ent(c4_ent)) {
    remove_task(2345678+c4_ent)
    return
  }
  new c4num = param[1]

  if(g_c4_timer[c4num] >= 34)
  {
    emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_beep1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  }
  if(g_c4_timer[c4num] < 34 && g_c4_timer[c4num] >= 24)
  {
    emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_beep2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  }
  if(g_c4_timer[c4num] < 24 && g_c4_timer[c4num] >= 15)
  {
    emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_beep3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  }
  if(g_c4_timer[c4num] < 15 && g_c4_timer[c4num] >= 6)
  {
    emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_beep4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  }
  else if(g_c4_timer[c4num] < 6)
  {
    if(g_c4_timer[c4num] <= 0)
    {
      remove_task(1234567+c4_ent)
      remove_task(2345678+c4_ent)
      new fakec4_explosion = get_cvar_num("fakec4_explosion")
      switch(fakec4_explosion) {
        case 0: {
          emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_explode1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
        }
        case 1: {
          doExplosion(c4_ent, 0)
          return
        }
        case 2: {
          doExplosion(c4_ent, 1)
          return
        }
      }
      remove_entity(c4_ent)
      return
    }
    emit_sound(c4_ent, CHAN_WEAPON, "weapons/c4_beep5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  }

  g_c4_timer[c4num] -= 1.48

  return
}

public client_PreThink(id)
{
  
  if(g_c4_num > 0 && (get_cvar_num("fakec4_ctdefuse") == 0 || get_user_team(id) == 2))
  {
    if(get_user_button(id) & IN_USE)
    {
      if(g_defusing[id])
      {
        new Float:origin[3]
        entity_get_vector(g_defusing[id], EV_VEC_origin, origin)
        if(!is_in_viewcone(id, origin) || !(entity_get_int(id, EV_INT_flags) & FL_ONGROUND))
        {
          set_user_maxspeed(id, 240.0)
          g_defusing[id] = 0
          remove_task(3456789+id)
          message_begin(MSG_ONE, g_msgBarTime, {0,0,0}, id)
          write_byte(0)
          write_byte(0)
          message_end()
          if(!(entity_get_int(id, EV_INT_flags) & FL_ONGROUND))
          {
            message_begin(MSG_ONE, g_msgTextMsg, {0,0,0}, id)
            write_byte(4)
            write_string("#C4_Defuse_Must_Be_On_Ground")
            message_end()
          }
        }
        else
        {
          set_user_maxspeed(id, -1.0)
        }
        return PLUGIN_CONTINUE
      }
      new closest_c4 = 0, distance = 9999, c4_id
      new Float:origin[3]
      new dist
      for(new i = 0; i < g_c4_num; i++)
      {
        c4_id = g_c4_id[i]
        if(is_valid_ent(c4_id))
        {
          entity_get_vector(c4_id, EV_VEC_origin, origin)
          if(is_in_viewcone(id, origin))
          {
            dist = get_entity_distance(id, c4_id)
            if(dist < distance)
            {
              closest_c4 = c4_id
              distance = dist
            }
          }
        }
      }
      new targetid, body
      get_user_aiming(id, targetid, body)
      if(closest_c4) targetid = closest_c4
      if(targetid)
      {
        new c4ClassName[32]
        entity_get_string(targetid, EV_SZ_classname, c4ClassName, 31)
        if(equal(c4ClassName,"fake_c4"))
        {
          get_user_origin(id, g_origin1)
          entity_get_vector(targetid, EV_VEC_origin, g_forigin2)
          FVecIVec(g_forigin2, g_origin2)
          distance = get_distance(g_origin1,g_origin2)
          if(distance < 72)
          {
            g_defusing[id] = targetid
            set_user_maxspeed(id, -1.0)
            emit_sound(targetid, CHAN_WEAPON, "weapons/c4_disarm.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
            if(entity_get_byte(id, OFFSET_DEFUSE_PLANT) & HAS_DEFUSE_KIT)
            {
              message_begin(MSG_ONE, g_msgBarTime, {0,0,0}, id)
              write_byte(5)
              write_byte(0)
              message_end()
              new param[3]
              param[0] = targetid
              param[1] = id
              set_task(5.0, "defused", 3456789+id, param, 2)
              message_begin(MSG_ONE, g_msgTextMsg, {0,0,0}, id)
              write_byte(4)
              write_string("#Defusing_Bomb_With_Defuse_Kit")
              message_end()
            }
            else
            {
              message_begin(MSG_ONE, g_msgBarTime, {0,0,0}, id)
              write_byte(10)
              write_byte(0)
              message_end()
              new param[3]
              param[0] = targetid
              param[1] = id
              set_task(10.0, "defused", 3456789+id, param, 2)
              message_begin(MSG_ONE, g_msgTextMsg, {0,0,0}, id)
              write_byte(4)
              write_string("#Defusing_Bomb_Without_Defuse_Kit")
              message_end()
            }
          }
        }
      }
    }
    else if(g_defusing[id])
    {
      set_user_maxspeed(id, 240.0)
      g_defusing[id] = 0
      remove_task(3456789+id)
      message_begin(MSG_ONE, g_msgBarTime, {0,0,0}, id)
      write_byte(0)
      write_byte(0)
      message_end()
    }
  }
  return PLUGIN_CONTINUE
}

public defused(param[])
{
  new c4_ent = param[0]
  new id = param[1]
  emit_sound(c4_ent, CHAN_WEAPON, "radio/negative.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
  remove_task(1234567+c4_ent)
  remove_task(2345678+c4_ent)
  if(is_valid_ent(c4_ent)) remove_entity(c4_ent)
  set_hudmessage(255, 255, 255, -1.0, 0.3, 0, 0.01, 6.0, 0.01, 0.01, 2)
  show_hudmessage(id, "你已經拆除了一個假c4， 你被騙了! 哈哈哈哈!")
  g_defusing[id] = 0
  set_user_maxspeed(id, 240.0)
  return PLUGIN_CONTINUE
}

doExplosion(ent, hurtPlayers) {
  new Float:forigin[3], origin[3], origin2[3]
  entity_get_vector(ent, EV_VEC_origin, forigin)
  if(hurtPlayers) {
          radius_damage(forigin, 1200, 200)
  }
  FVecIVec(forigin, origin)
  new i, j
  for(i = 0; i < 5; i++) {
    origin2[0] = origin[0] + random_num(-200,200)
    origin2[1] = origin[1] + random_num(-200,200)
    origin2[2] = origin[2] + random_num(30,90)
    message_begin(MSG_PVS, SVC_TEMPENTITY, origin2, 0)
    write_byte(3)
    write_coord(origin2[0])
    write_coord(origin2[1])
    write_coord(origin2[2])
    write_short(g_sprExplosion)
    write_byte(30)
    write_byte(15)
    write_byte(0)
    message_end()
  }
  new players[32], inum
  get_players(players, inum, "ac")
  for(i = 0; i < inum; i++) {
    if(get_entity_distance(players[i], ent) < RADIUS_EXPLOSION) {
      message_begin(MSG_ONE, g_msgScreenShake, {0,0,0}, players[i])
      write_short(65535)
      write_short(4096)
      write_short(38400)
      message_end()
    }
  }
  for(i = 0; i < 4; i++) {
    origin2[0] = origin[0] + random_num(-200,200)
    origin2[1] = origin[1] + random_num(-200,200)
    origin2[2] = origin[2] + random_num(35,50)
    j = random_num(0, MAX_TE_SPRITES-1)
    message_begin(MSG_PVS, SVC_TEMPENTITY, origin2, 0)
    write_byte(17)
    write_coord(origin2[0])
    write_coord(origin2[1])
    write_coord(origin2[2])
    write_short(g_TE_SPRITES_tab[j])
    write_byte(-105)
    write_byte(150)
    message_end()
  }
  for(i = 0; i < 6; i++) {
    origin2[0] = origin[0] + random_num(-200,200)
    origin2[1] = origin[1] + random_num(-200,200)
    origin2[2] = origin[2] + random_num(30,90)
    message_begin(MSG_PVS, SVC_TEMPENTITY, origin2, 0)
    write_byte(5)
    write_coord(origin2[0])
    write_coord(origin2[1])
    write_coord(origin2[2])
    write_short(g_sprSmoke)
    write_byte(30)
    write_byte(12)
    message_end()
  }
  for(i = 0; i < 50; i++) {
    origin2[0] = origin[0] + random_num(-125,125)
    origin2[1] = origin[1] + random_num(-125,125)
    origin2[2] = origin[2] + random_num(40,300)
    message_begin(MSG_PVS, SVC_TEMPENTITY, origin2, 0)
    write_byte(9)
    write_coord(origin2[0])
    write_coord(origin2[1])
    write_coord(origin2[2])
    message_end()
  }
  if(is_valid_ent(ent)) remove_entity(ent)
}
