#if defined _sdkhooks_included
 #endinput
#endif
#define _sdkhooks_included

// this is obviously _not_ a robust check, but it will solve most conflict and is clean
#if !defined DMG_GENERIC
#define DMG_GENERIC								0					// generic damage was done
#define DMG_CRUSH									(1 << 0)	// crushed by falling or moving object. 
																						// NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage.
																						// DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead.
#define DMG_BULLET								(1 << 1)	// shot
#define DMG_SLASH									(1 << 2)	// cut, clawed, stabbed
#define DMG_BURN									(1 << 3)	// heat burned
#define DMG_VEHICLE								(1 << 4)	// hit by a vehicle
#define DMG_FALL									(1 << 5)	// fell too far
#define DMG_BLAST									(1 << 6)	// explosive blast damage
#define DMG_CLUB									(1 << 7)	// crowbar, punch, headbutt
#define DMG_SHOCK									(1 << 8)	// electric shock
#define DMG_SONIC									(1 << 9)	// sound pulse shockwave
#define DMG_ENERGYBEAM						(1 << 10)	// laser or other high energy beam 
#define DMG_PREVENT_PHYSICS_FORCE	(1 << 11)	// Prevent a physics force 
#define DMG_NEVERGIB							(1 << 12)	// with this bit OR'd in, no damage type will be able to gib victims upon death
#define DMG_ALWAYSGIB							(1 << 13)	// with this bit OR'd in, any damage type can be made to gib victims upon death.
#define DMG_DROWN									(1 << 14)	// Drowning
#define DMG_PARALYZE							(1 << 15)	// slows affected creature down
#define DMG_NERVEGAS							(1 << 16)	// nerve toxins, very bad
#define DMG_POISON								(1 << 17)	// blood poisoning - heals over time like drowning damage
#define DMG_RADIATION							(1 << 18)	// radiation exposure
#define DMG_DROWNRECOVER					(1 << 19)	// drowning recovery
#define DMG_ACID									(1 << 20)	// toxic chemicals or acid burns
#define DMG_SLOWBURN							(1 << 21)	// in an oven
#define DMG_REMOVENORAGDOLL				(1 << 22)	// with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed.
																						// use this to kill an entity that you've already got a server-side ragdoll for
#define DMG_PHYSGUN								(1 << 23)	// Hit by manipulator. Usually doesn't do any damage.
#define DMG_PLASMA								(1 << 24)	// Shot by Cremator
#define DMG_AIRBOAT								(1 << 25)	// Hit by the airboat's gun
#define DMG_DISSOLVE							(1 << 26)	// Dissolving!
#define DMG_BLAST_SURFACE					(1 << 27)	// A blast on the surface of water that cannot harm things underwater
#define DMG_DIRECT								(1 << 28)
#define DMG_BUCKSHOT							(1 << 29)	// not quite a bullet. Little, rounder, different.
#endif

#if !defined DMG_CRIT
	// TF2 crits and minicrits
	#define DMG_CRIT DMG_ACID
#endif

enum SDKHookType
{
	SDKHook_EndTouch,
	SDKHook_FireBulletsPost,
	SDKHook_OnTakeDamage,
	SDKHook_OnTakeDamagePost,
	SDKHook_PreThink,
	SDKHook_PostThink,
	SDKHook_SetTransmit,
	SDKHook_Spawn,
	SDKHook_StartTouch,
	SDKHook_Think,
	SDKHook_Touch,
	SDKHook_TraceAttack,
	SDKHook_TraceAttackPost,
	SDKHook_WeaponCanSwitchTo,
	SDKHook_WeaponCanUse,
	SDKHook_WeaponDrop,
	SDKHook_WeaponEquip,
	SDKHook_WeaponSwitch,
	SDKHook_ShouldCollide,
	SDKHook_PreThinkPost,
	SDKHook_PostThinkPost,
	SDKHook_ThinkPost,
	SDKHook_EndTouchPost,
	SDKHook_GroundEntChangedPost,
	SDKHook_SpawnPost,
	SDKHook_StartTouchPost,
	SDKHook_TouchPost,
	SDKHook_VPhysicsUpdate,
	SDKHook_VPhysicsUpdatePost,
	SDKHook_WeaponCanSwitchToPost,
	SDKHook_WeaponCanUsePost,
	SDKHook_WeaponDropPost,
	SDKHook_WeaponEquipPost,
	SDKHook_WeaponSwitchPost,
	SDKHook_Use,
	SDKHook_UsePost,
	SDKHook_Reload,
	SDKHook_ReloadPost,
	SDKHook_GetMaxHealth,  // ep2v and later
};

/*
	Alphabetized for easy readability
	
	SDKHook_EndTouch,
	SDKHook_EndTouchPost,
	
	SDKHook_FireBulletsPost,
	
	SDKHook_GetMaxHealth,  (ep2v and later)
	
	SDKHook_GroundEntChangedPost,
	
	SDKHook_OnTakeDamage,
	SDKHook_OnTakeDamagePost,
	
	SDKHook_PreThink,
	SDKHook_PreThinkPost,
	
	SDKHook_PostThink,
	SDKHook_PostThinkPost,
	
	SDKHook_Reload,
	SDKHook_ReloadPost,
	
	SDKHook_SetTransmit,
	
	SDKHook_ShouldCollide,
	
	SDKHook_Spawn,
	SDKHook_SpawnPost,
	
	SDKHook_StartTouch,
	SDKHook_StartTouchPost,
	
	SDKHook_Think,
	SDKHook_ThinkPost,
	
	SDKHook_Touch,
	SDKHook_TouchPost,
	
	SDKHook_TraceAttack,
	SDKHook_TraceAttackPost,
	
	SDKHook_Use,
	SDKHook_UsePost,
	
	SDKHook_VPhysicsUpdate,
	SDKHook_VPhysicsUpdatePost,
	
	SDKHook_WeaponCanSwitchTo,
	SDKHook_WeaponCanSwitchToPost,
	
	SDKHook_WeaponCanUse,
	SDKHook_WeaponCanUsePost,
	
	SDKHook_WeaponDrop,
	SDKHook_WeaponDropPost,
	
	SDKHook_WeaponEquip,
	SDKHook_WeaponEquipPost,
	
	SDKHook_WeaponSwitch,
	SDKHook_WeaponSwitchPost
*/

enum UseType
{
	Use_Off,
	Use_On,
	Use_Set,
	Use_Toggle
};

funcenum SDKHookCB
{
	// PreThink/Post
	// PostThink/Post
	public(client),
	
	// Spawn
	Action:public(entity),
	
	// GroundEntChanged
	// SpawnPost
	// Think/Post
	// VPhysicsUpdate/Post
	public(entity),
	
	// EndTouch
	// StartTouch
	// Touch
	Action:public(entity, other),
	
	// EndTouchPost
	// StartTouchPost
	// TouchPost
	public(entity, other),
	
	// SetTransmit
	Action:public(entity, client),
	
	// WeaponCanSwitchTo
	// WeaponCanUse
	// WeaponDrop
	// WeaponEquip
	// WeaponSwitch
	Action:public(client, weapon),
	
	// WeaponCanSwitchToPost
	// WeaponCanUsePost
	// WeaponDropPost
	// WeaponEquipPost
	// WeaponSwitchPost
	public(client, weapon),
	
	// GetMaxHealth (ep2v and later)
	Action:public(entity, &maxhealth),
	
	// OnTakeDamage
	// Note: Force application is dependent on game and damage type(s)
	// SDKHooks 1.0+
	Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype),
	// SDKHooks 2.0+
	Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3]),
	// SDKHooks 2.1+  (can check for support at runtime using GetFeatureStatus on SDKHook_DmgCustomInOTD capability.
	// DON'T attempt to access 'damagecustom' var if feature status != available
	Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon,
		Float:damageForce[3], Float:damagePosition[3], damagecustom),
	
	// OnTakeDamagePost
	public(victim, attacker, inflictor, Float:damage, damagetype),
	public(victim, attacker, inflictor, Float:damage, damagetype, weapon, const Float:damageForce[3], const Float:damagePosition[3]),
	
	// FireBulletsPost
	public(client, shots, const String:weaponname[]),
	
	// TraceAttack
	Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup),
	
	// TraceAttackPost
	public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup),
	
	// ShouldCollide
	bool:public(entity, collisiongroup, contentsmask, bool:originalResult),
	
	// Use
	Action:public(entity, activator, caller, UseType:type, Float:value),
	
	// UsePost
	public(entity, activator, caller, UseType:type, Float:value),
	
	// Reload
	Action:public(weapon),
	
	// Reload post
	public(weapon, bool:bSuccessful)
};


/**
 * @brief When an entity is created
 *
 * @param		entity		Entity index
 * @param		classname	Class name
 * @noreturn
 */
forward OnEntityCreated(entity, const String:classname[]);

/**
 * @brief When an entity is destroyed
 *
 * @param		entity		Entity index
 * @noreturn
 */
forward OnEntityDestroyed(entity);

/**
 * @brief When the game description is retrieved
 *
 * @note  Not supported on ep2v.
 *
 * @param		gameDesc		Game description
 * @noreturn
 */
forward Action:OnGetGameDescription(String:gameDesc[64]);

/**
 * @brief When the level is initialized
 *
 * @param		mapName			Name of the map
 * @param		mapEntities	Entities of the map
 * @noreturn
 */
forward Action:OnLevelInit(const String:mapName[], String:mapEntities[2097152]);

/**
 * @brief Hooks an entity
 *
 * @param		entity		Entity index
 * @param		type			Type of function to hook
 * @param		callback	Function to call when hook is called
 * @noreturn
 */
native SDKHook(entity, SDKHookType:type, SDKHookCB:callback);

/**
 * @brief Hooks an entity
 *
 * @param		entity		Entity index
 * @param		type			Type of function to hook
 * @param		callback	Function to call when hook is called
 * @return		bool		Hook Successful
 */
native bool:SDKHookEx(entity, SDKHookType:type, SDKHookCB:callback);

/**
 * @brief Unhooks an entity
 *
 * @param    entity   Entity index
 * @param    type     Type of function to unhook
 * @param    callback Callback function to unhook
 * @noreturn
 */
native SDKUnhook(entity, SDKHookType:type, SDKHookCB:callback);

/**
 * @brief Applies damage to an entity
 *
 * @note Force application is dependent on game and damage type(s)
 *
 * @param    entity         Entity index taking damage
 * @param    inflictor      Inflictor entity index
 * @param    attacker       Attacker entity index
 * @param    damage         Amount of damage
 * @param    damageType     Bitfield of damage types
 * @param    weapon         Weapon index (orangebox and later) or -1 for unspecified
 * @param    damageForce    Velocity of damage force
 * @param    damagePosition Origin of damage
 * @noreturn
 */
native SDKHooks_TakeDamage(entity, inflictor, attacker, Float:damage, damageType=DMG_GENERIC, weapon=-1, const Float:damageForce[3]=NULL_VECTOR, const Float:damagePosition[3]=NULL_VECTOR);

/**
 * @brief				Forces a client to drop the specified weapon
 *
 * @param client		Client index.
 * @param weapon		Weapon entity index.
 * @param vecTarget		Location to toss weapon to, or NULL_VECTOR for default.
 * @param vecVelocity	Velocity at which to toss weapon, or NULL_VECTOR for default.
 * @noreturn
 * @error				Invalid client or weapon entity, weapon not owned by client.
 */
native SDKHooks_DropWeapon(client, weapon, const Float:vecTarget[3]=NULL_VECTOR, const Float:vecVelocity[3]=NULL_VECTOR);

/** Do Not Edit Below This Line **/

public Extension:__ext_sdkhooks =
{
	name = "sdkhooks",
	file = "sdkhooks.ext",
#if defined AUTOLOAD_EXTENSIONS
	autoload = 1,
#else
	autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
	required = 1,
#else
	required = 0,
#endif
};

#if !defined REQUIRE_EXTENSIONS
public __ext_sdkhooks_SetNTVOptional()
{
	MarkNativeAsOptional("SDKHook");
	MarkNativeAsOptional("SDKHookEx");
	MarkNativeAsOptional("SDKUnhook");
	MarkNativeAsOptional("SDKHooks_TakeDamage");
	MarkNativeAsOptional("SDKHooks_DropWeapon");
}
#endif
