
   /*
   *    AMXMOD script.
   *    (plugin_gore.sma)
   *    by mike_cao <mike@mikecao.com>
   *    This file is provided as is (no warranties).
   *
   *    This plugin adds gore effects. It is configured
   *    with the cvar "amx_gore" using these flags:
   *
   *    a - Headshot blood
   *    b - Extra blood effects
   *    c - Bleeding on low health
   *    d - Gib explosion (knife, HE, high damage only)
   *
   */
   #include <amxmod>
   #define MAX_NAME_LENGTH 32
   #define MAX_VAR_LENGTH 64
   #define MAX_PLAYERS 32
   #define MAX_TEXT_LENGTH 512
   #define GORE_HEADSHOT         (1<<0) // "a"
   #define GORE_BLOOD             (1<<1) // "b"
   #define GORE_BLEEDING         (1<<2) // "c"
   #define GORE_GIB            (1<<3) // "d"
   #define TE_BLOODSPRITE        115
   #define    TE_BLOODSTREAM        101
   #define TE_MODEL            106
   #define TE_WORLDDECAL        116
   /************************************************************
   * MAIN
   ************************************************************/
   new gHealthIndex[MAX_PLAYERS+1]
   new mdl_gib_flesh
   new mdl_gib_head
   new mdl_gib_legbone
   new mdl_gib_lung
   new mdl_gib_meat
   new mdl_gib_spine
   new spr_blood_drop
   new    spr_blood_spray
   public event_damage()
   {
       new iFlags = get_gore_flags()
       new iVictim = read_data(0)
       gHealthIndex[iVictim] = get_user_health(iVictim)

       if (iFlags&GORE_BLOOD) {
           new iOrigin[3]
           get_user_origin(iVictim,iOrigin)
           fx_blood(iOrigin)
           fx_blood_small(iOrigin,10)
       }
       return PLUGIN_CONTINUE
   }
   public event_death()
   {
       new iFlags = get_gore_flags()
       new iOrigin[3]
       new sWeapon[MAX_NAME_LENGTH]
       new iVictim = read_data(2)
       new iHeadshot = read_data(3)

       read_data(4,sWeapon,MAX_NAME_LENGTH)

       if (iFlags&GORE_HEADSHOT && iHeadshot) {
           get_user_origin(iVictim,iOrigin)
           fx_headshot(iOrigin)
       }
       else    if    (iFlags&GORE_GIB   &&   (equal(sWeapon,"knife")   ||
   equal(sWeapon,"grenade")       ||       (gHealthIndex[iVictim]       -
   get_user_health(iVictim)) > 100)) {
           get_user_origin(iVictim,iOrigin)
           // Effects
           fx_trans(iVictim,0)
           fx_gib_explode(iOrigin,5)
           fx_blood_large(iOrigin,3)
           fx_blood_small(iOrigin,20)
           // Hide body
           iOrigin[2] = iOrigin[2]-20
           set_user_origin(iVictim,iOrigin)
       }
   }
   public event_blood()
   {
       new iFlags = get_gore_flags()
       if (iFlags&GORE_BLEEDING) {
           new iPlayer, iPlayers[MAX_PLAYERS], iNumPlayers, iOrigin[3]
           get_players(iPlayers,iNumPlayers,"a")
           for (new i = 0; i < iNumPlayers; i++) {
               iPlayer = iPlayers[i]
               if (get_user_health(iPlayer) < 20) {
                   get_user_origin(iPlayer,iOrigin)
                   fx_bleed(iOrigin)
                   fx_blood_small(iOrigin,5)
               }
           }
       }
   }
   public event_respawn(id)
   {
       gHealthIndex[id] = get_user_health(id)
       return PLUGIN_CONTINUE
   }
   public get_gore_flags()
   {
       new sFlags[24]
       get_cvar_string("amx_gore",sFlags,24)
       return read_flags(sFlags)
   }
   /************************************************************
   * FX FUNCTIONS
   ************************************************************/
   static fx_trans(player,amount)
   {
       set_user_rendering(player,kRenderFxNone,0,0,0,kRenderTransAlpha,am
   ount)
       return PLUGIN_CONTINUE
   }
   public fx_blood(origin[3])
   {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(TE_BLOODSPRITE)
           write_coord(origin[0]+random_num(-20,20))
           write_coord(origin[1]+random_num(-20,20))
           write_coord(origin[2]+random_num(-20,20))
           write_short(spr_blood_spray)
           write_short(spr_blood_drop)
           write_byte(248) // color index
           write_byte(10) // size
           message_end()
   }
   public fx_bleed(origin[3])
   {
       // Blood spray
       message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
       write_byte(TE_BLOODSTREAM)
       write_coord(origin[0])
       write_coord(origin[1])
       write_coord(origin[2]+10)
       write_coord(random_num(-100,100)) // x
       write_coord(random_num(-100,100)) // y
       write_coord(random_num(-10,10)) // z
       write_byte(70) // color
       write_byte(random_num(50,100)) // speed
       message_end()
   }
   static fx_blood_small(origin[3],num)
   {
       // Blood decals
       static const blood_small[7] = {190,191,192,193,194,195,197}

       // Small splash
       for (new j = 0; j < num; j++) {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(TE_WORLDDECAL)
           write_coord(origin[0]+random_num(-100,100))
           write_coord(origin[1]+random_num(-100,100))
           write_coord(origin[2]-36)
           write_byte(blood_small[random_num(0,6)]) // index
           message_end()
       }
   }
   static fx_blood_large(origin[3],num)
   {
       // Blood decals
       static const blood_large[2] = {204,205}
       // Large splash
       for (new i = 0; i < num; i++) {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(TE_WORLDDECAL)
           write_coord(origin[0]+random_num(-50,50))
           write_coord(origin[1]+random_num(-50,50))
           write_coord(origin[2]-36)
           write_byte(blood_large[random_num(0,1)]) // index
           message_end()
       }
   }
   static fx_gib_explode(origin[3],num)
   {
       new flesh[3], x, y, z
       flesh[0] = mdl_gib_flesh
       flesh[1] = mdl_gib_meat
       flesh[2] = mdl_gib_legbone
       // Gib explosion
       // Head
       message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
       write_byte(TE_MODEL)
       write_coord(origin[0])
       write_coord(origin[1])
       write_coord(origin[2])
       write_coord(random_num(-100,100))
       write_coord(random_num(-100,100))
       write_coord(random_num(100,200))
       write_angle(random_num(0,360))
       write_short(mdl_gib_head)
       write_byte(0) // bounce
       write_byte(500) // life
       message_end()

       // Spine
       message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
       write_byte(TE_MODEL)
       write_coord(origin[0])
       write_coord(origin[1])
       write_coord(origin[2])
       write_coord(random_num(-100,100))
       write_coord(random_num(-100,100))
       write_coord(random_num(100,200))
       write_angle(random_num(0,360))
       write_short(mdl_gib_spine)
       write_byte(0) // bounce
       write_byte(500) // life
       message_end()

       // Lung
       for(new i = 0; i < random_num(1,2); i++) {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(TE_MODEL)
           write_coord(origin[0])
           write_coord(origin[1])
           write_coord(origin[2])
           write_coord(random_num(-100,100))
           write_coord(random_num(-100,100))
           write_coord(random_num(100,200))
           write_angle(random_num(0,360))
           write_short(mdl_gib_lung)
           write_byte(0) // bounce
           write_byte(500) // life
           message_end()
       }

       // Parts, 5 times
       for(new i = 0; i < 5; i++) {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(TE_MODEL)
           write_coord(origin[0])
           write_coord(origin[1])
           write_coord(origin[2])
           write_coord(random_num(-100,100))
           write_coord(random_num(-100,100))
           write_coord(random_num(100,200))
           write_angle(random_num(0,360))
           write_short(flesh[random_num(0,2)])
           write_byte(0) // bounce
           write_byte(500) // life
           message_end()
       }

       // Blood
       for(new i = 0; i < num; i++) {
           x = random_num(-100,100)
           y = random_num(-100,100)
           z = random_num(0,100)
           for(new j = 0; j < 5; j++) {
               message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
               write_byte(TE_BLOODSPRITE)
               write_coord(origin[0]+(x*j))
               write_coord(origin[1]+(y*j))
               write_coord(origin[2]+(z*j))
               write_short(spr_blood_spray)
               write_short(spr_blood_drop)
               write_byte(248) // color index
               write_byte(15) // size
               message_end()
           }
       }
   }
   public fx_headshot(origin[3])
   {
       // Blood spray, 5 times
       for (new i = 0; i < 5; i++) {
           message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
           write_byte(101)
           write_coord(origin[0])
           write_coord(origin[1])
           write_coord(origin[2]+30)
           write_coord(random_num(-20,20)) // x
           write_coord(random_num(-20,20)) // y
           write_coord(random_num(50,300)) // z
           write_byte(70) // color
           write_byte(random_num(100,200)) // speed
           message_end()
       }
   }
   /************************************************************
   * PLUGIN FUNCTIONS
   ************************************************************/
   public plugin_precache()
   {
       spr_blood_drop = precache_model("sprites/blood.spr")
       spr_blood_spray = precache_model("sprites/bloodspray.spr")
       mdl_gib_flesh = precache_model("models/Fleshgibs.mdl")
       mdl_gib_head = precache_model("models/GIB_Skull.mdl")
       mdl_gib_legbone = precache_model("models/GIB_Legbone.mdl")
       mdl_gib_lung = precache_model("models/GIB_Lung.mdl")
       mdl_gib_meat = precache_model("models/GIB_B_Gib.mdl")
       mdl_gib_spine = precache_model("models/GIB_B_Bone.mdl")
   }
   public plugin_init()
   {
       register_plugin("Plugin Gore","1.0","mike_cao")
       register_event("DeathMsg","event_death","a")
       register_event("Damage","event_damage","b","2!0","3=0","4!0")
       register_event("ResetHUD","event_respawn","be","1=1")
       register_cvar("amx_gore","abcd")
       set_task(1.0,"event_blood",0,"",0,"b")
       return PLUGIN_CONTINUE
   }
