/*******************************************************************************

  AMXMODX_TO_AMX Library
  Author: KRoT@L
  Version: 1.2.0

  You need AMX 2006.3 or higher.
  
  Credits for the original AmxModX natives/stocks/defines go to AmxModX Dev Team.
  The authors of AMX Mod X are:
    David "BAILOPAN" Anderson, Pavol "PM OnoTo" Marko,
 	  Felix "SniperBeamer" Geyer, Jonny "Got His Gun" Bergstrom,
 		Lukasz "SidLuke" Wlasinski, Christian "Basic-Master" Hammacher,
 	  Borja "faluco" Ferrer, Scott "Damaged Soul" Ehlert.

*******************************************************************************/

/*******************************************************************************
* INSTRUCTIONS
********************************************************************************

Put this file inside your amx/examples/include folder.

--------------------------------------------------------------------------------

Replace all the #include <...> lines with just this line:
#include <amxmodx_to_amx>

For example, replace this:

#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fun>

with just

#include <amxmodx_to_amx>

--------------------------------------------------------------------------------

If the plugin uses csstats, add:
#include <csstats>
BEFORE #include <amxmodx_to_amx>

If the plugin uses dodxmod, add:
#include <dodxmod>
BEFORE #include <amxmodx_to_amx>

*******************************************************************************/

/*******************************************************************************
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*******************************************************************************/

/*******************************************************************************
* INCLUDES
*******************************************************************************/

#include <amxmod>
#include <amxmisc>
#include <cstrike>
#include <fun>
#include <geoip>
#include <sockets>
#include <Vexd_Utilities>
#include <VexdUM_stock>

/*******************************************************************************
* DEFINES
*******************************************************************************/

#define AMXX_VERSION      2006
#define AMXX_VERSION_NUM  2006
#define AMXX_VERSION_STR  AMX_VERSION

#define ADMIN_ADMIN (1<<24)   /* flag "y" */

#define CSW_VEST        31
#define CSW_VESTHELM    32

#define LANG_SERVER     0
#define LANG_PLAYER    -1

#define FMRES_HANDLED   PLUGIN_CONTINUE
#define FMRES_SUPERCEDE PLUGIN_HANDLED
#define FMRES_IGNORED   PLUGIN_CONTINUE
#define FMRES_OVERRIDE  PLUGIN_CONTINUE

#define STAMINA_SET     0
#define STAMINA_RESET   1

#define FUSE_SET        0
#define FUSE_RESET      1

#define PS_NOPRONE      0
#define PS_PRONE        1
#define PS_PRONEDEPLOY  2
#define PS_DEPLOY       3

#define MI_ALLIES_TEAM  0
#define MI_ALLIES_PARAS 1
#define MI_AXIS_PARAS   2

/*******************************************************************************
* AMXMISC.INC
*******************************************************************************/

stock cstrike_running() {
  new mod_name[32];
  get_modname(mod_name,31);
  return (equal(mod_name,"cstrike") || equal(mod_name,"czero"));
}

stock get_configsdir(name[],len) {
  return build_path(name,len,"$configdir");
}

stock get_datadir(name[],len) {
  return build_path(name,len,"$modulesdir");
}

stock get_customdir(name[],len) {
  return build_path(name,len,"$configdir");
}

stock register_menu(title[],keys,function[],outside=0) {
  register_menucmd(register_menuid(title,outside),keys,function);
}

stock AddMenuItem(const MENU_TEXT[], const MENU_CMD[], const MENU_ACCESS, const MENU_PLUGIN[]) {
  new szAccess[16];
  get_flags(MENU_ACCESS, szAccess, 15);
  server_cmd("amx_addmenuitem ^"amxmodmenu^" ^"%s^" ^"%s^" ^"%s^" ^"b^" ^"%s^"",MENU_PLUGIN,MENU_TEXT,MENU_CMD,szAccess);
}

stock constraint_offset(low, high, seed, offset) {
  new numElements = high - low + 1;
  offset += seed - low;
  if(offset >= 0)
    return low + (offset % numElements);
  else
    return high - (abs(offset) % numElements) + 1;
  return 0;
}

/*******************************************************************************
* AMXMODX.INC
*******************************************************************************/

stock user_has_weapon(index,weapon,setweapon=-1) {
  if(setweapon == 0 || setweapon == 1) {
    return set_user_weapon(index, weapon, setweapon);
  }
  return has_user_weapon(index, weapon);
}

stock log_amx(string[], {Float,_}:...) {
  if(string[0]) {}
  new str[512];
  format_args(str, 511, 0);
  new logfile[16];
  get_logfile(logfile, 15);
  return log_to_file(logfile, str);
}

stock change_task(id = 0, Float:newTime=1.0, outside = 0) {
  return change_tasktime(id, new_time, outside);
}

stock is_module_loaded(const name[]) {
  return is_module_running(name);
}

stock is_plugin_loaded(const name[]) {
  return is_plugin_running(name);
}

stock require_module(const module[]) {
  return module[0];
}

stock is_amd64_server() {
  return 0;
}

stock find_plugin_byfile(const filename[], ignoreCase=1) {
  return is_plugin_running(filename);
}

stock log_error(error, const fmt[], ...) {
  new str[512];
  format_args(str, 511, 1);
  return report_error(str);
}

stock abort(error, const fmt[]="", {Float,_}:...) {
  new str[512];
  format_args(str, 511, 1);
  return report_error(str);
}

stock module_exists(const logtag[]) {
  return is_module_running(logtag);
}

stock get_pcvar_flags(pcvar) {
  return get_cvarptr_flags(pcvar);
}

stock get_pcvar_num(pcvar) {
  return get_cvarptr_num(pcvar);
}

stock Float:get_pcvar_float(pcvar) {
  return get_cvarptr_float(pcvar);
}

stock get_pcvar_string(pcvar) {
  return get_cvarptr_string(pcvar);
}

stock set_pcvar_flags(pcvar, flags) {
  return set_cvarptr_flags(pcvar, flags);
}

stock set_pcvar_num(pcvar, num) {
  return set_cvarptr_num(pcvar, num);
}

stock set_pcvar_float(pcvar, Float:num) {
  return set_cvarptr_float(pcvar, num);
}

/*******************************************************************************
* CSX.INC
*******************************************************************************/

#define client_damage(%1,%2,%3,%4,%5,%6) damage_info(%1,%2,%3,%4,%5,%6)
#define client_death(%1,%2,%3,%4,%5) death_info(%1,%2,%3,%4,%5)
#define bomb_explode(%1,%2) bomb_exploded(%1,%2)
#define bomb_defusing(defuser) bomb_defusing(defuser,hasDefuseKit)
#define bomb_defused(defuser) bomb_defused(defuser,hasDefuseKit)

/*******************************************************************************
* DODX.INC
*******************************************************************************/

//#define client_damage(attacker,victim,damage,wpnindex,hitplace,TA) damage_info(attacker,victim,damage,wpnindex,hitplace,TA)
//#define client_death(killer,victim,wpnindex,hitplace,TK) death_info(killer,victim,wpnindex,hitplace,TK)
#define client_score(%1,%2,%3) score_info(%1,%2,%3)

enum {
  XMF_DAMAGE = 0,
  XMF_DEATH,
  XMF_SCORE,
};

stock register_statsfwd(ftype) {
  return ftype;
}

stock dod_get_map_info(info) {
  switch(info) {
    case 0: return detect_allies_team();
    case 1: return detect_allies_paras();
    case 2: return detect_axis_paras();
  }
  return 0;
}

stock xmod_is_melee_wpn(wpnindex) {
  return dod_is_melee(wpnindex);
}

stock xmod_get_wpnname(wpnindex,name[],len) {
  return dod_get_wpnname(wpnindex,name,len);
}

stock xmod_get_wpnlogname(wpnindex,name[],len) {
  return dod_get_wpnlogname(wpnindex,name,len);
}

/*******************************************************************************
* DODFUN.INC
*******************************************************************************/

stock dod_set_stamina(index,set=0,minvalue=0,maxvalue=100) {
  if(set == 0) {
    return set_user_stamina(index,minvalue,maxvalue);
  }
  return reset_user_stamina(index);
}

stock dod_set_fuse(index,set=0,Float:newFuse=5.0,Type=(1<<0)) {
  if(set == 0) {
    return nade_set_fuse(index,newFuse,Type);
  }
  return nade_reset_fuse(index);
}

/*******************************************************************************
* ENGINE.INC
*******************************************************************************/

stock force_use(pPlayer, pEntity) {
  return entity_use(pEntity, pPlayer);
}

stock Float:get_global_float(variable) {
  return global_get_float(variable);
}

stock get_global_int(variable) {
  return global_get_int(variable);
}

stock get_global_string(variable, string[], maxlen) {
  return global_get_string(variable, string, maxlen);
}

stock get_global_vector(variable, Float:vector[3]) {
  return global_get_vector(variable, vector);
}

stock get_global_edict(variable) {
  return global_get_edict(variable);
}

stock Float:entity_range(ida,idb) {
  new Float:orig1[3], Float:orig2[3];
  entity_get_vector(ida, EV_VEC_origin, orig1);
  entity_get_vector(idb, EV_VEC_origin, orig2);
  return vector_distance(orig1, orig2);
}

stock find_ent_by_class(iIndex, szClass[]) {
  if(iIndex == 0) iIndex = -1;
  new ent = find_entity(iIndex, szClass);
  return (ent > 0) ? ent : 0;
}

stock find_ent_by_owner(iIndex, szClass[], iOwner, iJghgType=0) {
  new maxEntities = get_maxentities();
  new string[64];
  switch(iJghgType) {
    case 0: {
      for(new i = iIndex+1 ; i <= maxEntities; ++i) {
        if(!is_entity(i)) continue;
        if(entity_get_edict(i, EV_ENT_owner) == iOwner) {
          string[0] = '^0'
          entity_get_string(i, EV_SZ_classname, string, 63);
          if(equal(szClass, string)) {
            return i;
          }
        }
      }
    }
    case 1: {
      for(new i = iIndex+1 ; i <= maxEntities; ++i) {
        if(!is_entity(i)) continue;
        if(entity_get_edict(i, EV_ENT_owner) == iOwner) {
          string[0] = '^0'
          entity_get_string(i, EV_SZ_target, string, 63);
          if(equal(szClass, string)) {
            return i;
          }
        }
      }
    }
    case 2: {
      for(new i = iIndex+1 ; i <= maxEntities; ++i) {
        if(!is_entity(i)) continue;
        if(entity_get_edict(i, EV_ENT_owner) == iOwner) {
          string[0] = '^0'
          entity_get_string(i, EV_SZ_targetname, string, 63);
          if(equal(szClass, string)) {
            return i;
          }
        }
      }
    }
  }
  return 0;
}

stock find_ent_by_target(iIndex, szClass[]) {
  new maxEntities = get_maxentities();
  new target[64];
  for(new i = iIndex+1 ; i <= maxEntities; i++) {
    if(!is_entity(i)) continue;
    target[0] = '^0'
    entity_get_string(i, EV_SZ_target, target, 63);
    if(equal(szClass, target)) {
      return i;
    }
  }
  return 0;
}

stock find_ent_by_tname(iIndex, szClass[]) {
  new maxEntities = get_maxentities();
  new targetname[64];
  for(new i = iIndex+1 ; i <= maxEntities; i++) {
    if(!is_entity(i)) continue;
    targetname[0] = '^0'
    entity_get_string(i, EV_SZ_targetname, targetname, 63);
    if(equal(szClass, targetname)) {
      return i;
    }
  }
  return 0;
}

stock find_ent_by_model(iIndex, szClass[], szModel[]) {
  if(iIndex == 0) iIndex = -1;
  new model[64];
  new ent = find_entity(iIndex, szClass);
  while(ent > 0) {
    model[0] = '^0'
    entity_get_string(ent, EV_SZ_model, model, 63);
    if(equal(szModel, model)) {
      return ent;
    }
    ent = find_entity(ent, szClass);
  }
  return 0;
}

stock find_ent_in_sphere(start_from_ent, Float:origin[3], Float:radius) {
  if(start_from_ent == 0) start_from_ent = -1;
  new ent = find_entity_sphere(start_from_ent, origin, radius)
  return (ent > 0) ? ent : 0;
}

stock is_valid_ent(iIndex) {
  return is_entity(iIndex);
}

stock entity_count() {
  return get_num_ents();
}

stock velocity_by_aim(iIndex, iVelocity, Float:vRetValue[3]) {
  return VelocityByAim(iIndex, iVelocity, vRetValue);
}

stock point_contents(Float:fCheckAt[3]) {
  return PointContents(fCheckAt);
}

stock angle_vector(Float:angle[3],FRU,Float:ret[3]) {
  return angle_to_vector(angle, FRU, ret);
}

stock Float:halflife_time() {
  return get_gametime();
}

stock find_sphere_class(aroundent,_lookforclassname[],Float:radius,entlist[],maxents,Float:origin[3]={0.0,0.0,0.0}) {
  if(is_entity(aroundent)) {
    entity_get_vector(aroundent, EV_VEC_origin, origin);
  }
  new entnum = 0;
  new classname[64];
  new ent = find_entity_sphere(-1, origin, radius);
  while(ent > 0 && entnum < maxents) {
    classname[0] = '^0'
    entity_get_string(ent, EV_SZ_classname, classname, 63);
    if(equal(classname, _lookforclassname)) {
      entlist[entnum++] = ent;
    }
    ent = find_entity_sphere(ent, origin, radius);
  }
  return entnum;
}

stock is_in_viewcone(entity, Float:origin[3]) {
  return in_view_cone(entity, origin);
}

stock is_visible(entity, target) {
  return can_see(entity, target);
}

#define client_PreThink(%1) client_prethink(%1)
#define client_PostThink(%1) client_postthink(%1)
#define pfn_touch(%1,%2) entity_touch(%1,%2)
#define pfn_think(%1) entity_think(%1)
#define pfn_keyvalue(%1) keyvalue(%1)
#define pfn_spawn(%1) entity_spawn(%1)

/*******************************************************************************
* ENGINE_STOCKS.INC
*******************************************************************************/

stock fakedamage(idvictim,szClassname[],Float:takedmgdamage,damagetype) {
  new entity = create_entity("trigger_hurt");
  if(entity > 0) {
    DispatchKeyValue(entity,"classname","trigger_hurt");
    new szDamage[16];
    format(szDamage,15,"%f",takedmgdamage * 2);
    DispatchKeyValue(entity,"dmg",szDamage);
    format(szDamage,15,"%i",damagetype);
    DispatchKeyValue(entity,"damagetype",szDamage);
    DispatchKeyValue(entity,"origin","8192 8192 8192");
    DispatchSpawn(entity);
    entity_set_string(entity, EV_SZ_classname, szClassname);
    fake_touch(entity,idvictim);
    remove_entity(entity);
    return 1;
  }
  return 0;
}

stock find_ent(iStart, szClassname[]) {
  new ent = find_entity(iStart, szClassname)
  return (ent > 0) ? ent : 0;
}

stock remove_entity_name(eName[]) {
  return remove_entities(eName[]);
}

stock set_entity_visibility(entity, visible = 1) {
  if(visible == 1) {
    entity_set_int(entity, EV_INT_effects, entity_get_int(entity, EV_INT_effects) & ~EF_NODRAW);
  }
  else {
    entity_set_int(entity, EV_INT_effects, entity_get_int(entity, EV_INT_effects) | EF_NODRAW);
  }
  return 1;
}

stock get_entity_visibility(entity) {
  return (entity_get_int(entity, EV_INT_effects) & EF_NODRAW);
}

stock set_user_velocity(entity, Float:vec[3]) {
  return entity_set_vector(entity, EV_VEC_velocity, vec);
}

stock get_user_velocity(entity, Float:vec[3]) {
  return entity_get_vector(entity, EV_VEC_velocity, vec);
}

stock IsInWorld(ent) {
   new Float:origin[3]
   entity_get_vector(ent,EV_VEC_origin,origin)
   if (origin[0] >= 4096.0) return 0;
   if (origin[1] >= 4096.0) return 0;
   if (origin[2] >= 4096.0) return 0;
   if (origin[0] <= -4096.0) return 0;
   if (origin[1] <= -4096.0) return 0;
   if (origin[2] <= -4096.0) return 0;
   new Float:velocity[3]
   entity_get_vector(ent,EV_VEC_velocity,velocity)
   if (velocity[0] >= 2000) return 0;
   if (velocity[1] >= 2000) return 0;
   if (velocity[2] >= 2000) return 0;
   if (velocity[0] <= -2000) return 0;
   if (velocity[1] <= -2000) return 0;
   if (velocity[2] <= -2000) return 0;
   return 1;
}

/*******************************************************************************
* FAKEMETA.INC
*******************************************************************************/

stock get_pdata_int(_index,_Offset,_linuxdiff=5) {
  return get_offset_int(_index,_Offset,_linuxdiff);
}

stock set_pdata_int(_index,_Offset,_Value,_linuxdiff=5) {
  return set_offset_int(_index,_Offset,_Value,_linuxdiff);
}

/*******************************************************************************
* FILE.INC
*******************************************************************************/

stock filesize(const filename[512],{Float,_}:...) {
  new str[512];
  format_args(str, 511, 0);
  return file_size(str);
}

stock unlink(const filename[512],{Float,_}:...) {
  new str[512];
  format_args(str, 511, 0);
  return delete_file(str);
}

/*******************************************************************************
* FLOAT.INC
*******************************************************************************/

stock Float:floatabs(Float:value) {
  return fabs(value);
}

stock Float:floatsin(Float:value, anglemode:mode=radian) {
  return sin(value, mode);
}

stock Float:floatcos(Float:value, anglemode:mode=radian) {
  return cos(value, mode);
}

stock Float:floattan(Float:value, anglemode:mode=radian) {
  return tan(value, mode);
}

stock Float:floatatan(Float:angle, radix) {
  return atan(angle, anglemode:radix);
}

stock Float:floatacos(Float:angle, radix) {
  return acos(angle, anglemode:radix);
}

stock Float:floatasin(Float:angle, radix) {
  return asin(angle, anglemode:radix);
}

stock Float:floatatan2(Float:x, Float:y, radix) {
  return atan2(x, y, anglemode:radix);
}

stock Float:floatsqroot(Float:value) {
  return fsqroot(value)
}

stock Float:floatpower(Float:value, Float:exponent) {
  return fpower(value, exponent)
}

stock Float:floatlog(Float:value, Float:base=10.0) {
  return flog(value, base)
}

stock Float:floatsinh(Float:angle, anglemode:mode=radian) {
  return sinh(angle, mode);
}

stock Float:floatcosh(Float:angle, anglemode:mode=radian) {
  return cosh(angle, mode);
}

stock Float:floattanh(Float:angle, anglemode:mode=radian) {
  return tanh(angle, mode);
}

/*******************************************************************************
* FUN.INC
*******************************************************************************/

stock spawn(index) {
  return user_spawn(index);
}

/*******************************************************************************
* LANG.INC
*******************************************************************************/

stock get_langsnum() {
  return get_languagesnum();
}

stock get_lang(id, name[3]) {
  return get_language(id, name, 2);
}

stock lang_exists(const name[]) {
  return is_language_known(name);
}

/*******************************************************************************
* MESSAGE_STOCKS.INC
*******************************************************************************/

stock dod_make_deathmsg(killer, victim, weaponNUM) {
	message_begin(MSG_ALL, get_user_msgid("DeathMsg"), {0,0,0}, 0);
	write_byte(killer);
	write_byte(victim);
	write_byte(weaponNUM);
	message_end();
	return 1;
}

stock user_silentkill(index) {
	static msgid = 0;
	new msgblock;
	if(!msgid) {
		msgid = get_user_msgid("DeathMsg");
	}
	msgblock = get_msg_block(msgid);
	set_msg_block(msgid, BLOCK_ONCE);
	user_kill(index, 1);
	set_msg_block(msgid, msgblock);
	return 1;
}

stock make_deathmsg(killer, victim, headshot, weapon[]) {
	message_begin(MSG_ALL, get_user_msgid("DeathMsg"), {0,0,0}, 0);
	write_byte(killer);
	write_byte(victim);
	new mod_name[32];
	get_modname(mod_name, 31);
	if (equal(mod_name, "cstrike") || equal(mod_name, "czero") || equal(mod_name, "csv15") || equal(mod_name, "cs13"))
		write_byte(headshot);
	write_string(weapon);
	message_end();
	return 1;
}

/*******************************************************************************
* STRING.INC
*******************************************************************************/

stock float_to_str(Float:fl, string[], len) {
  return format(string, len, "%f", fl);
}

stock Float:str_to_float(const string[]) {
  return floatstr(string);
}

stock strcat(dest[], const source[], maxlength) {
  return add(dest, maxlength, source);
}

stock strfind(const string[], const sub[], ignorecase=0, pos=0) {
  if(pos >= strlen(string)) return -1;
  if(ignorecase) {
    return containi(string[pos], sub);
  }
  return contain(string[pos], sub);
}

stock strcmp(const string1[], const string2[], ignorecase=0) {
  if(ignorecase) {
    return (equali(string1, string2)) ? 0 : -1;
  }
  return (equal(string1, string2)) ? 0 : -1;
}

stock ucfirst(string[]) {
  string[0] = toupper(string[0]);
  return 1;
}

stock remove_filepath(szFilePath[], szFile[], pMax) {
	new len = strlen(szFilePath);
	while((--len >= 0) && (szFilePath[len] != '/') && (szFilePath[len] != '\')) { }
	copy(szFile, pMax, szFilePath[len + 1]);
	return 1;
}

/*******************************************************************************
* TIME.INC
*******************************************************************************/

/* Time unit types for get_time_length() */
enum
{
    timeunit_seconds = 0,
    timeunit_minutes,
    timeunit_hours,
    timeunit_days,
    timeunit_weeks,
}

// seconds are in each time unit
#define SECONDS_IN_MINUTE 60
#define SECONDS_IN_HOUR   3600
#define SECONDS_IN_DAY    86400
#define SECONDS_IN_WEEK   604800

/* Stock by Brad */
stock get_time_length(id, unitCnt, type, output[], outputLen)
{
// IMPORTANT: 	You must add register_dictionary("time.txt") in plugin_init()

// id:          The player whose language the length should be translated to (or 0 for server language).
// unitCnt:     The number of time units you want translated into verbose text.
// type:        The type of unit (i.e. seconds, minutes, hours, days, weeks) that you are passing in.
// output:      The variable you want the verbose text to be placed in.
// outputLen:	The length of the output variable.

    if (unitCnt > 0)
    {
        // determine the number of each time unit there are
        new weekCnt = 0, dayCnt = 0, hourCnt = 0, minuteCnt = 0, secondCnt = 0;

        switch (type)
        {
            case timeunit_seconds: secondCnt = unitCnt;
            case timeunit_minutes: secondCnt = unitCnt * SECONDS_IN_MINUTE;
            case timeunit_hours:   secondCnt = unitCnt * SECONDS_IN_HOUR;
            case timeunit_days:    secondCnt = unitCnt * SECONDS_IN_DAY;
            case timeunit_weeks:   secondCnt = unitCnt * SECONDS_IN_WEEK;
        }

        weekCnt = secondCnt / SECONDS_IN_WEEK;
        secondCnt -= (weekCnt * SECONDS_IN_WEEK);

        dayCnt = secondCnt / SECONDS_IN_DAY;
        secondCnt -= (dayCnt * SECONDS_IN_DAY);

        hourCnt = secondCnt / SECONDS_IN_HOUR;
        secondCnt -= (hourCnt * SECONDS_IN_HOUR);

        minuteCnt = secondCnt / SECONDS_IN_MINUTE;
        secondCnt -= (minuteCnt * SECONDS_IN_MINUTE);

        // translate the unit counts into verbose text
        new maxElementIdx = -1;
        new timeElement[5][33];

        if (weekCnt > 0)
            format(timeElement[++maxElementIdx], 32, "%i %L", weekCnt, id, (weekCnt == 1) ? "TIME_ELEMENT_WEEK" : "TIME_ELEMENT_WEEKS");
        if (dayCnt > 0)
            format(timeElement[++maxElementIdx], 32, "%i %L", dayCnt, id, (dayCnt == 1) ? "TIME_ELEMENT_DAY" : "TIME_ELEMENT_DAYS");
        if (hourCnt > 0)
            format(timeElement[++maxElementIdx], 32, "%i %L", hourCnt, id, (hourCnt == 1) ? "TIME_ELEMENT_HOUR" : "TIME_ELEMENT_HOURS");
        if (minuteCnt > 0)
            format(timeElement[++maxElementIdx], 32, "%i %L", minuteCnt, id, (minuteCnt == 1) ? "TIME_ELEMENT_MINUTE" : "TIME_ELEMENT_MINUTES");
        if (secondCnt > 0)
            format(timeElement[++maxElementIdx], 32, "%i %L", secondCnt, id, (secondCnt == 1) ? "TIME_ELEMENT_SECOND" : "TIME_ELEMENT_SECONDS");

        switch(maxElementIdx)
        {
            case 0: format(output, outputLen, "%s", timeElement[0]);
            case 1: format(output, outputLen, "%s %L %s", timeElement[0], id, "TIME_ELEMENT_AND", timeElement[1]);
            case 2: format(output, outputLen, "%s, %s %L %s", timeElement[0], timeElement[1], id, "TIME_ELEMENT_AND", timeElement[2]);
            case 3: format(output, outputLen, "%s, %s, %s %L %s", timeElement[0], timeElement[1], timeElement[2], id, "TIME_ELEMENT_AND", timeElement[3]);
            case 4: format(output, outputLen, "%s, %s, %s, %s %L %s", timeElement[0], timeElement[1], timeElement[2], timeElement[3], id, "TIME_ELEMENT_AND", timeElement[4]);
        }
    }
}

/*******************************************************************************
* XTRAFUN.INC
*******************************************************************************/

stock get_entity_velocity(id, velocity[3]) {
  new Float:vel[3];
  entity_get_vector(id, EV_VEC_velocity, vel);
  FVecIVec(vel, velocity);
}

stock set_entity_velocity(id, velocity[3]) {
  new Float:vel[3];
  IVecFVec(velocity, vel);
  entity_set_vector(id, EV_VEC_velocity, vel);
}

stock get_entity_origin(id, origin[3]) {
  new Float:orig[3];
  entity_get_vector(id, EV_VEC_origin, orig);
  FVecIVec(orig, origin);
}

stock set_entity_origin(id, origin[3]) {
  new Float:orig[3];
  IVecFVec(origin, orig);
  entity_set_vector(id, EV_VEC_origin, orig);
}

stock get_grenade_id(id, model[], len, grenadeid) {
  grenadeid = get_grenade(id, grenadeid);
  entity_get_string(grenadeid, EV_SZ_model, model, len);
  return grenadeid;
}

stock get_grenade_index(index, model[], len, grenadeindex = 0) {
  if(grenadeindex == 0) grenadeindex = -1;
  new entfind = grenadeindex;
  new entowner = index;
  for(;;) {
    entfind = find_entity(entfind, "grenade");
    if(entfind > 0 && is_entity(entfind)) {
      if(entity_get_edict(entFind, EV_ENT_owner) == entowner) {
        entity_get_string(entfind, EV_SZ_model, model, len);
        return entfind;
      }
    }
    else {
      return 0;
    }
  }
}

stock current_num_ents() {
  return get_num_ents();
}

