#pragma once

#include <lib/warpzone/common.qh>

int autocvar_g_projectiles_damage;
int autocvar_g_projectiles_interact;
bool autocvar_g_projectiles_keep_owner;
float autocvar_sv_strengthsound_antispam_refire_threshold;
float autocvar_sv_strengthsound_antispam_time;

bool W_DualWielding(entity player);
void W_GiveWeapon (entity e, float wep);
void W_PlayStrengthSound(entity player);
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception);
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode);

void adaptor_think2use_hittype_splash(entity this);

bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher);

.float dmg_radius; // reused field, as the distance the laser damage occurs over
.vector dest; // reused field, as the adjusted hit location
void W_LaserPlay(entity this, float rad, float damage, float edgedamage, float burntime, WarpZone_FindRadius_cond_callback_t cb);

float W_SeekOutEnemy(entity this, float speed_decel, float speed_accel, float speed_max, float turn_rate, bool smart, float smart_mindist, float smart_trace_min, float smart_trace_max);

.float dmg_last;
.float teleport_time; // reused field, as the time the damage started
void W_DamageOverTime_Think(entity this, float duration, float duration_power, float damage, float edgedamage, float rad, float force, entity cantbe, float think_delay);

.float misc_bulletcounter;

.int projectiledeathtype;

.float fade_time;
.float fade_rate;

.entity realowner;

#define PROJECTILE_TOUCH(e,t) MACRO_BEGIN if (WarpZone_Projectile_Touch(e,t)) return; MACRO_END

// FIXME: some behaviours can't be achieved or would require kludges in physics code,
// eg we can't make electro bolts hit electro orbs only (without causing other problems) when g_projectiles_interact == 1,
// see also WarpZone_Projectile_Touch_ImpactFilter_Callback().
// Ideally, extend engine to support any combination of 'hit a and b but not x or y' and 'take hits from c and d but not w or z'.
#define PROJECTILE_MAKETRIGGER(e) \
MACRO_BEGIN \
	(e).solid = SOLID_CORPSE; \
	(e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; \
	if (!autocvar_g_projectiles_interact || (autocvar_g_projectiles_interact == 1 && (e).classname != "blasterbolt")) \
		(e).clipgroup = 1; \
MACRO_END

// when doing this, hagar can go through clones
// #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_BBOX

.int missile_flags;
const int MIF_SPLASH = BIT(1);
const int MIF_ARC = BIT(2);
const int MIF_PROXY = BIT(3);
const int MIF_GUIDED_MANUAL = BIT(4);
const int MIF_GUIDED_HEAT = BIT(5);
const int MIF_GUIDED_LASER = BIT(6);
const int MIF_GUIDED_AI = BIT(7);
const int MIF_GUIDED_TAG = BIT(7);
const int MIF_GUIDED_ALL = MIF_GUIDED_MANUAL | MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
const int MIF_GUIDED_TRACKING = MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
const int MIF_GUIDED_CONFUSABLE = MIF_GUIDED_HEAT | MIF_GUIDED_AI;

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