
   /*
   * AMXMOD script.
   *
   *
   *        Plugin : Headshot Deluxe v0.7
   *
   *
   * This file is provided as is (no warranties).
   * Feel free to use it or modify it.
   * Report bugs at danrazor@yahoo.fr THX
   *
   * Author: DanRaZor
   *
   * Based on :
   *    Ultimate Sounds by Hephos
   *    welcome HUDMsg by JustinHoMi
   *    lots from OLO
   *
   * THX.
   *
   */
   /* CHANGELOG
   *
   * 2002/12/31 : v0.0   - Just trying to do something ...
   * 2003/01/02 : v0.1   - Added    : Tags <HUD> and <CHAT> ( HTML Like )
   *  2003/01/04  :  v0.2   -  Added    : amx_hs_set_wav, amx_hs_set_hud,
   amx_hs_set_txt
   * 2003/01/05 : v0.3   - Added    : New flags c,d,e
   *                     -   Added    :  Replacement  of  %distFeet%  and
   %weapon% in text FX
   *                     -  Added    :  New  command  "say  /hs"  display
   player's Headshot rank ( for current map )
   * 2003/01/09 : v0.4   - Modified : Way of displaying /hs and flags cde
   *                     -  toDo     : New command "say /hstop5" displays
   top 5 at Headshots ( current map only )
   * 2003/01/10 : v0.5   - Modified : Command say /hstop5 modified to say
   /hsAll, displays all player(s)
   *                                who have made headshots ( for current
   map, not classified ... )
   *                     - Fixed    : Bugs for first headshot
   * 2003/01/20 : v0.5.2 - Removed  : Some debug traces remaining
   *  2003/02/01  :  v0.6   - Modified : The cvar amx_hs_wav can now have
   the 3 types of users ...
   *                     -  Fixed    : Dynamic precache for sounds in the
   cvar amx_hs_wav
   *  2003/02/15  : v0.7   - Added    : Command amx_hs_save_config "file"
   to store cvars
   *
   *
   */
   /*   HELP
   *
   * New cvars:
   *
   *** amx_hs_event "flags"
   *
   *      flags
   *         "a" - text  FX
   *         "b" - sound FX
   *         "c"  -  display  number of headshots ( for killer only , and
   current map )
   *         "d"  -  display percentage of frags by headshot ( for killer
   only , and current map )
   *         "e"  -  display  headshot  ranking  (  for killer only , and
   current map )
   *
   *      default "abcde"
   *
   *
   *** amx_hs_txt
   "<HUD><ALL>...textToDisplayinHUD</HUD><CHAT><ALL>...textToDisplayInCha
   t</CHAT>"
   *
   *      <ALL>    for displaying to all players
   *      <VICTIM> for displaying to victim only
   *      <KILLER> for displaying to killer only
   *
   *      examples :
   *           "<HUD><VICTIM>::        Headshot        by        %killer%
   ::</HUD><CHAT><ALL>%killer%  made  headshot  on %victim% at %distance%
   m</CHAT>"
   *           "<HUD><KILLER>Headshot<HUD><CHAT><KILLER>Headshot       at
   %distance% m</CHAT>"
   *           "<CHAT><ALL>%killer%   made   headshot   on   %victim%  at
   %distance% m</CHAT><HUD><ALL>Someone lost is head ...</HUD>"
   *
   *      use only one text betweem <HUD>...</HUD> or <CHAT>...</CHAT>
   *      you cannot use more than once HUD or CHAT
   *
   *      %killer%, %victim%, %distance%, %distFeet% and %weapon% will be
   replaced by the good values
   *
   *      default  "<CHAT><ALL>*  %killer%  made  headshot on %victim% at
   %distance% m ( %distFeet% ft ) with
   %weapon%</CHAT><HUD><VICTIM>Headshot by %killer%</HUD>"
   *
   *      use commands listed below to update in game ... it's easier
   *
   *
   *** amx_hs_wav "wavFile"
   *
   *      example :
   *        <KILLER>misc/youman</KILLER><ALL>misc/headshot</ALL>
   *        <VICTIM>misc/killkenny</VICTIM>
   *        <VICTIM>misc/headshot</VICTIM><KILLER>barney/ba_gotone</KILLE
   R>
   *
   *      Only one wav file for each category ( ALL , KILLER or VICTIM )
   *
   *      tip  :  you can use the ones on the pak0.pak in valve directory
   ...
   *            try <KILLER>barney/ba_gotone.wav</KILLER>
   *             or <ALL>barney/aimforhead</ALL>    ... pretty fun
   *
   *      use only wav format files ...
   *
   *      default
   "<ALL>misc/headshot</ALL><KILLER>barney/ba_gotone</KILLER><VICTIM>misc
   /ow</VICTIM>"
   *
   *
   * New commands :
   *
   *** amx_hs_set_wav <users> <wavPathFile>
   *
   *      adds or modify the wav for specified user(s)
   *
   *      use : amx_hs_set_wav "V" "misc/headshot"
   *
   *      users possibilities :
   *           "A"        : for ALL
   *           "V"        : for victim
   *           "K"        : for killer
   *
   *      access to ADMIN_CVAR needed ...
   *
   *
   *** amx_hs_set_hud <users> <text>
   *
   *      adds or modify the hud text for specified user(s)
   *
   *      use : amx_hs_set_hud "V" "Headshot by %killer%"
   *
   *      users possibilities :
   *           "A"        : for ALL
   *           "V"        : for victim
   *           "K"        : for killer
   *           "VK" or KV : for killer and victim
   *
   *      %killer%, %victim%, %distance%, %distFeet% and %weapon% will be
   replaced by the good values
   *
   *      access to ADMIN_CVAR needed ...
   *
   *
   *** amx_hs_set_chat <users> <text>
   *
   *      adds or modify the chat text for specified user(s)
   *
   *      use  :  amx_hs_set_chat "A" "%killer% made headshot on %victim%
   at %distance%"
   *
   *      users possibilities :
   *           "A"        : for ALL
   *           "V"        : for victim
   *           "K"        : for killer
   *           "VK" or KV : for killer and victim
   *
   *      %killer%, %victim%, %distance%, %distFeet% and %weapon% will be
   replaced by the good values
   *
   *      access to ADMIN_CVAR needed ...
   *
   *
   *** amx_hs_save_config <file>
   *
   *      stores the cvars in specified file
   *      if you use a path, it has to already exist ... cannot create it
   *      plus, you cannot use "../" because i dont want ( don't ask ! )
   *      all "../" will be removed
   *
   *      use : amx_hs_save_config "headshotDeluxe.cfg"
   *
   *      access to ADMIN_RCON needed ...
   *
   *
   *** say /hs
   *            Displays your rank at headshots ( and number of headshots
   )
   *
   *
   *** say /hsAll
   *            Displays score for all players who have made headshot(s)
   *            for current map ( Not Classified, working on it ...)
   *
   *
   */
   #define MAX_TXT_LEN    300
   #define MAX_TXT_LEN_1    299
   #define COEF_FEETS    12
   #define MAX_RANK    5
   #define MAX_STAT    4
   #include <amxmod>
   #include <amxmisc>
   #include <csstats>
   new killer        = 0
   new vict        = 0
   new maxPlayersHS    = 0
   replace_vars ( ioText[] ) {
       /* replacement of
                   %killer%
                   %victim%
                   %distance%
                   %distFeet%
                   %weapon%
       */
       new distance,vorigin[3],korigin[3]
       new killerStr[80], victimStr[80], distStr[8], distFtStr[8]
       get_user_origin(vict,vorigin)
       get_user_origin(killer,korigin)
       distance = get_distance(vorigin,korigin)
       new Float:distFt = ( float(distance) * 0.08333 )
       format(distFtStr,7,"%.1f",distFt)
       new Float:dist   = distFt * 0.304
       format(distStr,7,"%.1f",dist)
       get_user_name(killer,killerStr,79)
       get_user_name(vict,victimStr,79)
       new wpnId,clip,ammo,wpn[32]
       wpnId = get_user_weapon(killer,clip,ammo)
       get_weaponname ( wpnId , wpn ,31 )
       /* here we have for example wpn = "weapon_m4a1" so ... */
       replace(wpn,31,"weapon_","") /* it's nicer */
       replace(ioText,MAX_TXT_LEN_1,"%killer%",killerStr)
       replace(ioText,MAX_TXT_LEN_1,"%victim%",victimStr)
       replace(ioText,MAX_TXT_LEN_1,"%distance%",distStr)
       replace(ioText,MAX_TXT_LEN_1,"%distFeet%",distFtStr)
       replace(ioText,MAX_TXT_LEN_1,"%weapon%",wpn)
       return PLUGIN_CONTINUE
   }
   get_HUD_TXT ( iText[], oText[] ) {
       /* gets HUD Text from amx_hs_txt with affected users in */
       new startPos = containi(iText,"<HUD>")
       new endPos = containi(iText,"</HUD>")
       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+5) ) )  {
           new size = ( endPos - startPos ) - 5
           for ( new k = 0 ; k < size ; ++k ) {
               oText[k] = iText[startPos+5+k]
           }
           return 1

       }
       return 0
   }
   set_HUD_TXT ( text[], users[] , oFullText[] ) {
       /*  sets  HUD  Text  from  amx_hs_txt  with  affected  users in on
   oFullText */
       new userTxt[MAX_TXT_LEN]
       new count = 0
       if ( containi ( users , "A" ) > -1 ) {
           copy ( userTxt , MAX_TXT_LEN , "<ALL>" )
           ++count
       }
       else {
           if ( containi ( users , "V" ) > -1 ) {
               add ( userTxt , MAX_TXT_LEN , "<VICTIM>" )
               ++count
           }
           if ( containi ( users , "K" ) > -1 ) {
               add ( userTxt , MAX_TXT_LEN , "<KILLER>" )
               ++count
           }


       }
       if ( count > 0 ) {
           new fullText[MAX_TXT_LEN]
           get_cvar_string("amx_hs_txt",fullText,MAX_TXT_LEN_1)
           new startPos = containi(fullText,"<HUD>")
           new endPos = containi(fullText,"</HUD>")
           if  (  (  endPos  >  -1  )  && ( startPos > -1 ) && ( endPos >
   (startPos+5) ) )  {
               /* Already have a hud Text */
               new textBeforeHud[MAX_TXT_LEN],textAfterHud[MAX_TXT_LEN]
               for ( new l = 0 ; l < startPos ; ++l ) {
                   textBeforeHud[l] = fullText[l]
               }
               copy ( textAfterHud , MAX_TXT_LEN , fullText[endPos+6] )
               copy ( oFullText , MAX_TXT_LEN , textBeforeHud )
               add ( oFullText ,  MAX_TXT_LEN , "<HUD>" )
               add ( oFullText ,  MAX_TXT_LEN , userTxt )
               add ( oFullText ,  MAX_TXT_LEN , text  )
               add ( oFullText ,  MAX_TXT_LEN , "</HUD>" )
               add ( oFullText ,  MAX_TXT_LEN , textAfterHud )
           }
           else {

               /* No hud Text */
               copy ( oFullText , MAX_TXT_LEN , fullText )
               add ( oFullText ,  MAX_TXT_LEN , "<HUD>" )
               add ( oFullText ,  MAX_TXT_LEN , userTxt )
               add ( oFullText ,  MAX_TXT_LEN , text  )
               add ( oFullText ,  MAX_TXT_LEN , "</HUD>" )

           }
       }
       return count
   }
   get_CHAT_TXT ( iText[], oText[] ) {
       /* gets CHAT Text from amx_hs_txt with affected users in */
       new startPos = containi(iText,"<CHAT>")
       new endPos = containi(iText,"</CHAT>")
       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+6) ) )  {
           new size = ( endPos - startPos ) - 6
           for ( new m = 0 ; m < size ; ++m ) {
               oText[m] = iText[startPos+6+m]
           }
           return 1
       }
       return 0
   }
   set_CHAT_TXT ( text[], users[] , oFullText[] ) {
       /*  sets  CHAT  Text  from  amx_hs_txt  with  affected users in on
   oFullText */
       new userTxt[MAX_TXT_LEN]
       new count = 0
       if ( containi ( users , "A" ) > -1 ) {
           copy ( userTxt , MAX_TXT_LEN , "<ALL>" )
           ++count
       }
       else {
           if ( containi ( users , "V" ) > -1 ) {
               add ( userTxt , MAX_TXT_LEN , "<VICTIM>" )
               ++count
           }
           if ( containi ( users , "K" ) > -1 ) {
               add ( userTxt , MAX_TXT_LEN , "<KILLER>" )
               ++count
           }


       }
       if ( count > 0 ) {
           new fullText[MAX_TXT_LEN]
           get_cvar_string("amx_hs_txt",fullText,MAX_TXT_LEN_1)
           new startPos = containi(fullText,"<CHAT>")
           new endPos = containi(fullText,"</CHAT>")
           if  (  (  endPos  >  -1  )  && ( startPos > -1 ) && ( endPos >
   (startPos+6) ) )  {
               /* Already have a chat Text */
               new textBeforeChat[MAX_TXT_LEN],textAfterChat[MAX_TXT_LEN]
               for ( new n = 0 ; n < startPos ; ++n ) {
                   textBeforeChat[n] = fullText[n]
               }

               copy ( textAfterChat , MAX_TXT_LEN , fullText[endPos+7] )
               copy ( oFullText , MAX_TXT_LEN , textBeforeChat )
               add ( oFullText ,  MAX_TXT_LEN , "<CHAT>" )
               add ( oFullText ,  MAX_TXT_LEN , userTxt )
               add ( oFullText ,  MAX_TXT_LEN , text  )
               add ( oFullText ,  MAX_TXT_LEN , "</CHAT>" )
               add ( oFullText ,  MAX_TXT_LEN , textAfterChat )

           }
           else {

               /* No chat Text */

               copy ( oFullText , MAX_TXT_LEN , fullText )
               add ( oFullText ,  MAX_TXT_LEN , "<CHAT>" )
               add ( oFullText ,  MAX_TXT_LEN , userTxt )
               add ( oFullText ,  MAX_TXT_LEN , text  )
               add ( oFullText ,  MAX_TXT_LEN , "</CHAT>" )

           }
       }
       return count
   }
   display_HS_TXTEvent() {
       /* displays Text FX */
       /* text FX in HUD tags */
       new fullText[MAX_TXT_LEN]
       get_cvar_string("amx_hs_txt",fullText,MAX_TXT_LEN_1)
       new HUDText[MAX_TXT_LEN]
       get_HUD_TXT( fullText, HUDText )
       replace_vars ( HUDText )
       set_hudmessage(0,80,220,-1.0,0.30,0,6.0,6.0,0.5, 0.15, 9)
       /* Restricted users */
       if ( containi ( HUDText , "<ALL>" ) > -1 ) {
           replace(HUDText,MAX_TXT_LEN_1,"<ALL>","")
           show_hudmessage(0,HUDText)
       }
       else {
           if ( containi ( HUDText , "<VICTIM>" ) > -1 ) {
               replace(HUDText,MAX_TXT_LEN_1,"<VICTIM>","")
               show_hudmessage(vict,HUDText)
           }
           if ( containi ( HUDText , "<KILLER>" ) > -1 ) {
               replace(HUDText,MAX_TXT_LEN_1,"<KILLER>","")
               show_hudmessage(killer,HUDText)
           }
       }
       /* text FX in CHAT tags */
       new CHATText[MAX_TXT_LEN]
       get_CHAT_TXT( fullText, CHATText )
       replace_vars ( CHATText )
       /* Restricted users */
       if ( containi ( CHATText , "<ALL>" ) > - 1 ) {
           replace(CHATText,MAX_TXT_LEN_1,"<ALL>","")
           client_print(0,print_chat,CHATText )
       }
       else {
           if ( containi ( CHATText , "<VICTIM>" ) > -1 ) {
               replace(CHATText,MAX_TXT_LEN_1,"<VICTIM>","")
               client_print(vict,print_chat,CHATText )
           }
           if ( containi ( CHATText , "<KILLER>" ) > -1 ) {
               replace(CHATText,MAX_TXT_LEN_1,"<KILLER>","")
               client_print(killer,print_chat,CHATText )
           }
       }
       return PLUGIN_CONTINUE
   }
   play_HS_SOUNDEvent() {
       /* Play the wav amx_hs_wav for correct users */
       new wav[MAX_TXT_LEN]
       new count = 0
       get_cvar_string("amx_hs_wav",wav,MAX_TXT_LEN_1)
       /* Restricted users */

       new startPos = containi(wav,"<KILLER>")
       new endPos = containi(wav,"</KILLER>")

       new killerWav[MAX_TXT_LEN]
       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+8) ) )  {
           new size = ( endPos - startPos ) - 8
           for ( new k = 0 ; k < size ; ++k ) {
               killerWav[k] = wav[startPos+8+k]
           }

           if ( killerWav[0] != 0 ) {
               ++count
               new textK[MAX_TXT_LEN]
               format(textK,MAX_TXT_LEN_1,"spk %s",killerWav)
               client_cmd(killer,textK)
           }


       }

       startPos = containi(wav,"<VICTIM>")
       endPos = containi(wav,"</VICTIM>")

       new victimWav[MAX_TXT_LEN]
       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+8) ) )  {
           new size = ( endPos - startPos ) - 8
           for ( new k = 0 ; k < size ; ++k ) {
               victimWav[k] = wav[startPos+8+k]
           }

           if ( victimWav[0] != 0 ) {
               count = count + 2
               new textV[MAX_TXT_LEN]
               format(textV,MAX_TXT_LEN_1,"spk %s",victimWav)
               client_cmd(vict,textV)
           }


       }

       startPos = containi(wav,"<ALL>")
       endPos = containi(wav,"</ALL>")

       new allWav[MAX_TXT_LEN]
       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+5) ) )  {
           new size = ( endPos - startPos ) - 5
           for ( new k = 0 ; k < size ; ++k ) {
               allWav[k] = wav[startPos+5+k]
           }

           if ( allWav[0] != 0 ) {

               if ( count == 0 ) {

                   /* For all players */

                   new textA[MAX_TXT_LEN]
                   format(textA,MAX_TXT_LEN_1,"spk %s",allWav)
                   client_cmd(0,textA)
               }
               else {
                   /*  For  all  except killer and victim if already done
   for them */

                   for ( new y = 1 ; y < get_maxplayers() ; ++ y ) {

                       if ( is_user_connected ( y ) ) {

                           if     ( ( y == killer ) && ( count & 1 ) ) {}
                           else if ( ( y == vict     ) && ( count & 2 ) )
   {}
                           else {
                               new textAA[MAX_TXT_LEN]
                               format(textAA,MAX_TXT_LEN_1,"spk
   %s",allWav)
                               client_cmd(y,textAA)
                           }
                       }
                   }
               }
           }
       }

       return PLUGIN_CONTINUE
   }
   public amx_hsChangeHud ( id , level , cid ) {
       if (!cmd_access(id,level,cid,3))
           return PLUGIN_HANDLED
       new users[32], Txt[MAX_TXT_LEN]
       read_argv(1,users,31)
       read_argv(2,Txt,MAX_TXT_LEN_1)
       if ( users[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_hud  :  No users found ...
   aborting")
           return PLUGIN_HANDLED
       }
       if ( Txt[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_hud  :  No  text found ...
   aborting")
           return PLUGIN_HANDLED
       }
       new newText[MAX_TXT_LEN]
       if ( set_HUD_TXT( Txt , users , newText ) > 0 ) {
           new authid[16],nameP[32]
           get_user_authid(id,authid,15)
           get_user_name(id,nameP,31)
           log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^"  set cvar
   (name ^"%s^") (value ^"%s^")",
               nameP,get_user_userid(id),authid,  "amx_hs_txt"  , newText
   )
           set_cvar_string("amx_hs_txt",newText)
           console_print(id,"Cvar         ^"%s^"        changed        to
   ^"%s^"","amx_hs_txt",newText)
       }
       else {
           console_print(id,"[AMX]  amx_hs_set_hud  :  No correct user(s)
   found ... aborting")
       }

       return PLUGIN_HANDLED_MAIN

   }
   public amx_hsChangeChat ( id , level, cid ) {
       if (!cmd_access(id,level,cid,3))
           return PLUGIN_HANDLED
       new users[32], tt[MAX_TXT_LEN]
       read_argv(1,users,31)
       read_argv(2,tt,MAX_TXT_LEN_1)
       if ( users[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_chat  : No users found ...
   aborting")
           return PLUGIN_HANDLED
       }
       if ( tt[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_chat  :  No text found ...
   aborting")
           return PLUGIN_HANDLED
       }
       new newText[MAX_TXT_LEN]
       if ( set_CHAT_TXT( tt , users , newText ) > 0 ) {
           new authid[16],namePl[32]
           get_user_authid(id,authid,15)
           get_user_name(id,namePl,31)
           log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^"  set cvar
   (name ^"%s^") (value ^"%s^")",
               namePl,get_user_userid(id),authid,  "amx_hs_txt" , newText
   )
           set_cvar_string("amx_hs_txt",newText)
           console_print(id,"Cvar         ^"%s^"        changed        to
   ^"%s^"","amx_hs_txt",newText)

       }
       else {
           console_print(id,"[AMX]  amx_hs_set_chat  : No correct user(s)
   found ... aborting")
       }
       return PLUGIN_HANDLED_MAIN
   }
   public amx_hsChangeWav ( id , level, cid ) {
       if (!cmd_access(id,level,cid,3))
           return PLUGIN_HANDLED

       new soundFile[MAX_TXT_LEN]
       get_cvar_string ( "amx_hs_wav" , soundFile , MAX_TXT_LEN_1)

       new modifiedSoundFile[MAX_TXT_LEN]
       new users[32], path[64]
       read_argv(1,users,31)
       read_argv(2,path ,63)
       if ( users[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_wav  :  No users found ...
   aborting")
           return PLUGIN_HANDLED
       }
       if ( path[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_set_wav : No path for wav file
   found ... aborting")
           return PLUGIN_HANDLED
       }
       if ( containi ( users , "A" ) > -1) {

           new startPos = containi(soundFile,"<ALL>")
           new endPos = containi(soundFile,"</ALL>")

           if  (  (  endPos  >  -1  )  && ( startPos > -1 ) && ( endPos >
   (startPos+5) ) )  {
               /* Already have a Wav for all */
               new textBefore[MAX_TXT_LEN],textAfter[MAX_TXT_LEN]
               for ( new n = 0 ; n < startPos ; ++n ) {
                   textBefore[n] = soundFile[n]
               }

               copy ( textAfter , MAX_TXT_LEN , soundFile[endPos+6] )
               copy ( modifiedSoundFile , MAX_TXT_LEN , textBefore )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "<ALL>"    )
               add  ( modifiedSoundFile , MAX_TXT_LEN , path       )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "</ALL>"   )
               add  ( modifiedSoundFile , MAX_TXT_LEN , textAfter  )

           }
           else {

               /* No Wav for all, just adding it */

               add  ( soundFile , MAX_TXT_LEN , "<ALL>"    )
               add  ( soundFile , MAX_TXT_LEN , path       )
               add  ( soundFile , MAX_TXT_LEN , "</ALL>"   )

           }
       }
       else if ( containi ( users , "V" ) > -1) {

           new startPos = containi(soundFile,"<VICTIM>")
           new endPos = containi(soundFile,"</VICTIM>")

           if  (  (  endPos  >  -1  )  && ( startPos > -1 ) && ( endPos >
   (startPos+8) ) )  {
               /* Already have a Wav for victim */
               new textBefore[MAX_TXT_LEN],textAfter[MAX_TXT_LEN]
               for ( new n = 0 ; n < startPos ; ++n ) {
                   textBefore[n] = soundFile[n]
               }

               copy ( textAfter , MAX_TXT_LEN , soundFile[endPos+9] )
               copy ( modifiedSoundFile , MAX_TXT_LEN , textBefore )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "<VICTIM>" )
               add  ( modifiedSoundFile , MAX_TXT_LEN , path       )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "</VICTIM>")
               add  ( modifiedSoundFile , MAX_TXT_LEN , textAfter  )

           }
           else {

               /* No Wav for victim, just adding it */

               add  ( soundFile , MAX_TXT_LEN , "<VICTIM>"  )
               add  ( soundFile , MAX_TXT_LEN , path        )
               add  ( soundFile , MAX_TXT_LEN , "</VICTIM>" )

           }

       }
       else if ( containi ( users , "K" ) > -1) {

           new startPos = containi(soundFile,"<KILLER>")
           new endPos = containi(soundFile,"</KILLER>")

           if  (  (  endPos  >  -1  )  && ( startPos > -1 ) && ( endPos >
   (startPos+8) ) )  {
               /* Already have a Wav for killer */
               new textBefore[MAX_TXT_LEN],textAfter[MAX_TXT_LEN]
               for ( new n = 0 ; n < startPos ; ++n ) {
                   textBefore[n] = soundFile[n]
               }

               copy ( textAfter , MAX_TXT_LEN , soundFile[endPos+9] )
               copy ( modifiedSoundFile , MAX_TXT_LEN , textBefore )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "<KILLER>" )
               add  ( modifiedSoundFile , MAX_TXT_LEN , path       )
               add  ( modifiedSoundFile , MAX_TXT_LEN , "</KILLER>")
               add  ( modifiedSoundFile , MAX_TXT_LEN , textAfter  )

           }
           else {

               /* No Wav for killer, just adding it */

               add  ( soundFile , MAX_TXT_LEN , "<KILLER>"  )
               add  ( soundFile , MAX_TXT_LEN , path        )
               add  ( soundFile , MAX_TXT_LEN , "</KILLER>" )

           }

       }
       else {
           console_print(id,"[AMX]   amx_hs_set_wav  :  Bad  user(s)  ...
   aborting")
           return PLUGIN_HANDLED_MAIN
       }
       new authid[16],nameS[32]
       get_user_authid(id,authid,15)
       get_user_name(id,nameS,31)
       log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^"    set   cvar
   (name ^"%s^") (value ^"%s^")",
           nameS,get_user_userid(id),authid,        "amx_hs_wav"        ,
   modifiedSoundFile )
       set_cvar_string("amx_hs_wav",modifiedSoundFile)
       console_print(id,"Cvar ^"%s^" changed to
   ^"%s^"","amx_hs_wav",modifiedSoundFile)

       return PLUGIN_HANDLED_MAIN
   }
   public display_event_Text ( id ) {
       new nbText[MAX_TXT_LEN]
       new ratioText[MAX_TXT_LEN]
       new rankText[MAX_TXT_LEN]
       new output[MAX_TXT_LEN]
       new stats1[8],body1[8]
       get_user_wstats(killer,0,stats1,body1)
       new cnt = 0
       new hsflgs[6]
       get_cvar_string("amx_hs_event",hsflgs,5)
       new nbHS     = stats1[2]
       new nbFrags    = stats1[0]
       if ( nbHS == 0 ) {
           /*  here we can have 0 ???!!!! FIrst Event HS seems wrong ....
   */
           nbHS = 1
           /* correction */
       }
       if ( nbFrags == 0 ) {
           /* Same trouble */
           nbFrags = 1
           /* nbFrags */
       }
       if ( read_flags(hsflgs)&4) {
           ++cnt
           new done = 0
           if ( nbHS == 50 ) {
               format    (   nbText   ,   MAX_TXT_LEN   ,   "Unbelievable
   !!!^n          %d Headshots" , nbHS )
               done = 1
           }
           if ( ( nbHS == 20 ) && ( done == 0 ) ) {
               format  (  nbText , MAX_TXT_LEN , "Great !!!^n          %d
   Headshots" , nbHS )
               done = 1
           }
           if ( ( nbHS == 10 ) && ( done == 0 ) ) {
               format    (    nbText    ,   MAX_TXT_LEN   ,   "Good   Job
   !!!^n          %d Headshots" , nbHS )
               done = 1
           }
           if ( ( nbHS > 1 ) && ( done == 0 ) ) {
               format ( nbText , MAX_TXT_LEN , "^n          %d Headshots"
   , nbHS )
               done = 1
           }
           if ( done == 0 ) {
               format  (  nbText  , MAX_TXT_LEN , "^n          Your first
   Headshot" )
           }
           copy ( output , MAX_TXT_LEN , nbText )
       }
       if ( read_flags(hsflgs)&8) {
           ++cnt
           new Float:percent = 0.0
           percent  = ( float(nbHS) / float(nbFrags) ) * 100
           format  (  ratioText , MAX_TXT_LEN , "^n          %.2f percent
   of frags" , percent )
           add ( output , MAX_TXT_LEN , ratioText )
       }
       if ( read_flags(hsflgs)&16) {
           ++cnt
           new nbPlayer = 0
           new nbBest = 1
           for ( new r = 1 ; r < maxPlayersHS + 1 ; ++r ) {
               if ( r == killer )
                   ++ nbPlayer
               else {
                   if ( is_user_connected(r) ) {
                       new stats3[8],body3[8]
                       get_user_wstats(r,0,stats3,body3)
                       if ( stats3[2] > stats1[2] )
                           ++nbBest
                       if ( stats3[2] > 0 )
                           ++nbPlayer
                   }
               }
           }
           format  (  rankText , MAX_TXT_LEN , "^n          RANK %d/%d" ,
   nbBest , nbPlayer )
           add ( output , MAX_TXT_LEN , rankText )
       }
       if ( cnt > 0 ) {
           set_hudmessage(0,80,220,0.1,0.6,0,6.0,4.0,0.5,0.15,8)
           show_hudmessage(killer,output)
       }
       return PLUGIN_CONTINUE
   }
   public display_HS_RANK ( id ) {
       new rkText[MAX_TXT_LEN]
       new r = 1
       new n = 0
       new stats[8],body[8]
       get_user_wstats(id,0,stats,body)
       if ( stats[2] > 0 ) {
           for ( new z = 1 ; z < maxPlayersHS + 1 ; ++z ) {
               if ( z == id )
                   ++ n
               else {
                   if ( is_user_connected(z) ) {
                       new statsT[8],bodyT[8]
                       get_user_wstats(z,0,statsT,bodyT)
                       if ( statsT[2] > stats[2] )
                           ++r
                       if ( statsT[2] > 0 )
                           ++n
                   }
               }
           }
           format  ( rkText , MAX_TXT_LEN_1 , "Headshot rank : %d/%d ( %d
   HeadShot(s) )" , r , n , stats[2] )

       }
       else {
           format   (  rkText  ,  MAX_TXT_LEN_1  ,  "No  headshot  :  Try
   later  ..." , r , n )
       }
       client_print(id,print_chat,rkText )

       return PLUGIN_CONTINUE

   }
   public display_HS_TOP ( id ) {
       new title[80]
       new top5Text[MAX_TXT_LEN]
       new NameP[40]

       format ( title , 79 ,"    HEADSHOT Killer(s)" )
       new NB = 0
       for ( new d = 0 ; d < maxPlayersHS + 1 ; ++d ) {

           if ( is_user_connected(d) ) {
               new st[8],bd[8]
               get_user_wstats(d,0,st,bd)

               if ( d == killer ) {
                   if ( st[2] == 0 ) {
                       st[2] = 1
                   }
               }

               if ( st[2] > 0 ) {
                   get_user_name ( d , NameP , 39 )
                   new Float:percent  = ( float(st[2]) / float(st[0]) ) *
   100

                   new temp[MAX_TXT_LEN]
                   format   (  temp  ,  MAX_TXT_LEN  ,  "^n%s^n       %4d
   Headshot(s) - %.2f %% of frags" ,NameP,st[2],percent)
                   add( top5Text,MAX_TXT_LEN_1,temp)
                   ++NB

               }
           }
       }
       if ( NB == 0 ) {
           format     (     top5Text     ,MAX_TXT_LEN_1,    "^n^n^n    No
   Headshots^n^n       Try later ..." )
       }
       show_motd(id,top5Text,title)
       return PLUGIN_CONTINUE

   }
   public made_hs(id){
       killer = read_data(1)
       vict = read_data(2)
       if ( killer >= maxPlayersHS )
           maxPlayersHS = killer

       new hsflags[6]
       get_cvar_string("amx_hs_event",hsflags,5)
       if ( read_flags(hsflags)&1) {
           display_HS_TXTEvent()
       }
       if ( read_flags(hsflags)&2) {
           play_HS_SOUNDEvent()
       }
       display_event_Text ( id )
       killer = 0
       vict = 0
       return PLUGIN_CONTINUE
   }
   public save_to_file ( id , level, cid ) {
       if (!cmd_access(id,level,cid,2))
           return PLUGIN_HANDLED
       new cfgFile[MAX_TXT_LEN]
       read_argv(1,cfgFile,MAX_TXT_LEN_1)

       if ( cfgFile[0] == 0 ) {
           console_print(id,"[AMX]  amx_hs_save_config  : No path or file
   found ... aborting")
           return PLUGIN_HANDLED
       }

       if ( containi(cfgFile,".cfg" ) == -1 ) {
           console_print(id,"[AMX]  amx_hs_save_config  : You have to use
   cfg extension for file ... aborting")
           return PLUGIN_HANDLED
       }

       replace(cfgFile,MAX_TXT_LEN_1,"../","")

       new counter = 0

       if ( file_exists( cfgFile ) ) {
           console_print(id,"[AMX]  amx_hs_save_config  :  File found ...
   adding config at end of file")

           new temp1[MAX_TXT_LEN]= "amx_hs_event ^""
           new hsCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_event" , hsCfg , MAX_TXT_LEN_1)
           add ( temp1 , MAX_TXT_LEN_1 , hsCfg )
           add ( temp1 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp1,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_event ... skipping")
           }

           new temp2[MAX_TXT_LEN]= "amx_hs_txt ^""
           new textCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_txt" , textCfg , MAX_TXT_LEN_1)
           add ( temp2 , MAX_TXT_LEN_1 , textCfg )
           add ( temp2 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp2,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_txt ... skipping")
           }

           new temp3[MAX_TXT_LEN]= "amx_hs_wav ^""
           new soundCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_wav" , soundCfg , MAX_TXT_LEN_1)
           add ( temp3 , MAX_TXT_LEN_1 , soundCfg )
           add ( temp3 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp3,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_wav ... skipping")
           }

       }
       else {
           console_print(id,"[AMX]  amx_hs_save_config  :  File not found
   ... trying to create it")

           new temp1[MAX_TXT_LEN]= "amx_hs_event ^""
           new hsCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_event" , hsCfg , MAX_TXT_LEN_1)
           add ( temp1 , MAX_TXT_LEN_1 , hsCfg )
           add ( temp1 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp1,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_event ... skipping")
           }

           new temp2[MAX_TXT_LEN]= "amx_hs_txt ^""
           new textCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_txt" , textCfg , MAX_TXT_LEN_1)
           add ( temp2 , MAX_TXT_LEN_1 , textCfg )
           add ( temp2 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp2,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_txt ... skipping")
           }

           new temp3[MAX_TXT_LEN]= "amx_hs_wav ^""
           new soundCfg[MAX_TXT_LEN]
           get_cvar_string ( "amx_hs_wav" , soundCfg , MAX_TXT_LEN_1)
           add ( temp3 , MAX_TXT_LEN_1 , soundCfg )
           add ( temp3 , MAX_TXT_LEN_1 , "^"" )

           if ( write_file(cfgFile,temp3,-1) == 0 ) {
               ++counter
               console_print(id,"[AMX]  amx_hs_save_config  :  Failed  to
   write config for amx_hs_wav ... skipping")
           }

       }

       if ( counter > 0 ) {
           console_print(id,"[AMX] amx_hs_save_config : Configuration for
   HS-Deluxe stored ( %d write error(s) )" , counter )
       }
       else {
           console_print(id,"[AMX] amx_hs_save_config : Configuration for
   HS-Deluxe stored successfully" )
       }

       return PLUGIN_HANDLED_MAIN

   }
   public plugin_precache() {

       new killerWav[MAX_TXT_LEN]
       new victimWav[MAX_TXT_LEN]
       new allWav[MAX_TXT_LEN]

       new soundFile[MAX_TXT_LEN]
       get_cvar_string ( "amx_hs_wav" , soundFile , MAX_TXT_LEN_1)

       if ( soundFile[0] == 0 ) {
           /* First time launched, cvar doesn't exists so ...    */
           /* Because plugin_precache starts before plugin_init    */
           precache_sound ( "misc/headshot.wav" )
           precache_sound ( "misc/ow.wav" )
           return PLUGIN_CONTINUE
       }

       new startPos = containi(soundFile,"<KILLER>")
       new endPos = containi(soundFile,"</KILLER>")

       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+8) ) )  {
           new size = ( endPos - startPos ) - 8
           for ( new k = 0 ; k < size ; ++k ) {
               killerWav[k] = soundFile[startPos+8+k]
           }

       }

       startPos = containi(soundFile,"<VICTIM>")
       endPos = containi(soundFile,"</VICTIM>")

       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+8) ) )  {
           new size = ( endPos - startPos ) - 8
           for ( new k = 0 ; k < size ; ++k ) {
               victimWav[k] = soundFile[startPos+8+k]
           }

       }

       startPos = containi(soundFile,"<ALL>")
       endPos = containi(soundFile,"</ALL>")

       if  (  (  endPos  >  -1  )  &&  (  startPos  >  -1 ) && ( endPos >
   (startPos+5) ) )  {
           new size = ( endPos - startPos ) - 5
           for ( new k = 0 ; k < size ; ++k ) {
               allWav[k] = soundFile[startPos+5+k]
           }

       }

       if ( killerWav[0] != 0 ) {
           add ( killerWav , MAX_TXT_LEN , ".wav" )
           precache_sound ( killerWav )
       }
       if ( victimWav[0] != 0 ) {
           add ( victimWav , MAX_TXT_LEN , ".wav" )
           precache_sound ( victimWav )
       }
       if ( allWav[0] != 0 ) {
           add ( allWav , MAX_TXT_LEN , ".wav" )
           precache_sound ( allWav )
       }

       return PLUGIN_CONTINUE
   }
   public plugin_init(){

       maxPlayersHS    = 0

       register_plugin    ("headshot_deluxe","0.7","DanRaZor")
       register_event    ("DeathMsg","made_hs","ade","3=1","5=0")
       register_cvar    ("amx_hs_event","abcde")
       register_cvar    ("amx_hs_txt"  ,"<CHAT><ALL>*    %killer%    made
   headshot   on  %victim%  at  %distance%  m  (  %distFeet%  ft  )  with
   %weapon%</CHAT><HUD><VICTIM>Headshot by %killer%</HUD>")
       register_cvar    ("amx_hs_wav"  ,"<ALL>misc/headshot</ALL><KILLER>
   barney/ba_gotone</KILLER><VICTIM>misc/ow</VICTIM>")
       register_concmd    ("amx_hs_set_hud"            ,"amx_hsChangeHud"
   ,ADMIN_CVAR,"^"users^" ^"text^" ( users = A,V,K,VK or KV )")
       register_concmd    ("amx_hs_set_chat","amx_hsChangeChat",ADMIN_CVA
   R,"^"users^" ^"text^" ( users = A,V,K,VK or KV )")
       register_concmd    ("amx_hs_set_wav"            ,"amx_hsChangeWav"
   ,ADMIN_CVAR,"^"users^" ^"wavPathFile^" ( users = A,V,K )")

       register_concmd    ("amx_hs_save_config"           ,"save_to_file"
   ,ADMIN_RCON,"^"cfgPathFile^"")
       register_clcmd    ("say /hs"          ,"display_HS_RANK")
       register_clcmd    ("say_team /hs"     ,"display_HS_RANK")
       register_clcmd    ("say /hsAll"       ,"display_HS_TOP")
       register_clcmd    ("say_team /hsAll"  ,"display_HS_TOP")
       return PLUGIN_CONTINUE
   }
