#pragma once

#include <common/weapons/_all.qh>

bool autocvar_g_throughfloor_debug;
float autocvar_g_throughfloor_damage;
float autocvar_g_throughfloor_force;
float autocvar_g_throughfloor_damage_max_stddev;
float autocvar_g_throughfloor_force_max_stddev;
float autocvar_g_throughfloor_min_steps_player;
float autocvar_g_throughfloor_max_steps_player;
float autocvar_g_throughfloor_min_steps_other;
float autocvar_g_throughfloor_max_steps_other;
float autocvar_g_mirrordamage;
bool autocvar_g_mirrordamage_virtual;
bool autocvar_g_mirrordamage_onlyweapons;
float autocvar_g_maxpushtime;
float autocvar_g_balance_damagepush_speedfactor;
int autocvar_g_balance_firetransfer_damage;
int autocvar_g_balance_firetransfer_time;
float autocvar_g_balance_armor_blockpercent;
float autocvar_g_teamdamage_resetspeed;
float autocvar_g_teamdamage_threshold;
bool autocvar_g_teamkill_punishing;
float autocvar_g_balance_selfdamagepercent;
float autocvar_g_friendlyfire;
float autocvar_g_friendlyfire_virtual;
float autocvar_g_friendlyfire_virtual_force;

.void(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) event_damage;

.bool(entity targ, entity inflictor, float amount, float limit) event_heal;

.float dmg;
.float dmg_edge;
.float dmg_force;
.float dmg_radius;

bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);

void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);

float checkrules_firstblood;

.float damagedbycontents;
.float damagedbytriggers;

float yoda;
int impressive_hits;

.float pain_finished; // Added by Supajoe

.float dmg_team;
.float teamkill_complain;
.float teamkill_soundtime;
.entity teamkill_soundsource;
.entity pusher;
.bool istypefrag;
.float taunt_soundtime;

.float spawnshieldtime;

.int totalfrags;

.bool canteamdamage;

.vector death_origin;

.float hitsound_damage_dealt;
.int typehitsound, killsound;

// used for custom deathtype
string deathmessage;

float IsFlying(entity a);

// NOTE: f=0 means still count as a (positive) kill, but count no frags for it
void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
void GiveFrags (entity attacker, entity targ, float f, int deathtype, .entity weaponentity);

string AppendItemcodes(string s, entity player);

void LogDeath(string mode, int deathtype, entity killer, entity killed);

void Obituary_SpecialDeath(
	entity notif_target,
	bool murder,
	bool msg_from_ent,
	int deathtype,
	string s1, string s2, string s3, string s4,
	float f1, float f2, float f3);

float w_deathtype;
float Obituary_WeaponDeath(
	entity notif_target,
	float murder,
	int deathtype,
	string s1, string s2, string s3,
	float f1, float f2);

void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .entity weaponentity);

// WEAPONTODO
#define DMG_NOWEP (weaponentities[0])

int autocvar_g_player_damageplayercenter;

// NOTE: the .weaponentity parameter can be set to DMG_NOWEP if the attack wasn't caused by a weapon or player
void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);

bool RadiusDamage_running;
float RadiusDamageForSource(
	entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker,
	float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
	bool inflictorselfdamage, float forceintensity, vector forcexyzscale,
	int deathtype, .entity weaponentity, entity directhitentity);
	// Returns total damage applies to creatures

float RadiusDamage(
	entity inflictor, entity attacker,
	float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
	float forceintensity,
	int deathtype, .entity weaponentity, entity directhitentity);

.float damageforcescale;
const float MIN_DAMAGEEXTRARADIUS = 0.1;
const float MAX_DAMAGEEXTRARADIUS = 16;
.float damageextraradius;

// Calls .event_heal on the target so that they can handle healing themselves
// a limit of RES_LIMIT_NONE should be handled by the entity as its max health (if applicable)
bool Heal(entity targ, entity inflictor, float amount, float limit);

.float fire_damagepersec;
.float fire_deathtype;
.entity fire_owner;
.float fire_hitsound;

float Fire_AddDamage(entity e, entity o, float d, float t, float dt);

void Fire_ApplyDamage(entity e);

IntrusiveList g_damagedbycontents;
STATIC_INIT(g_damagedbycontents)
{
	g_damagedbycontents = IL_NEW();
}
