#include "common.qh"

#include "misc.qh"

#include "weapon.qh"

.void() w_think;
.float(float action) w_func;
.float attack_finished;
.float w_thought;

.float weapon_imp;
.float weapons;		/* Alas, a bitfield. */

void() weapon_init = {
	weapon_init_weapons();
};

void() weapon_player_init = {
	self.weapons = 0;
	self.weapon_imp = 0;

	weapon_select_by_impulse(0);
};

float(float ex) exp2 = {
	local float n;

	n = 1;

	if (ex >= 0) {
		while (ex-- > 0)
			n *= 2;
	} else {
		while (ex++ < 0)
			n *= 0.5;
	}
	
	return n;
};

float() weapon_player_parm1 = {
	local float parm, ex;

	/* upper 19 bits of mantissa is self.weapons & 0x007fffe0 */
	/* sign is self.weapons & 0x00800000 */
	/* 8 bits of exponent is signed self.weapons & 0x1f */
	/* lower 4 bits of mantissa is (self.weapon_imp << 1) + 1 */

	parm = self.weapons & 8388576;	/* 0x007fffe0 */
	parm |= self.weapon_imp*2 + 1;

	ex = floor(self.weapons & 31);	/* 0x1f */
	if (ex >= 16) ex -= 16;

	parm *= exp2(ex);

	if (parm & 8388608)	/* 0x800000 */
		parm = -parm;

	return parm;
};

float() weapon_player_parm1_default = {
	return 1;	/* weapons 0x000000 weapon_imp 0 */
};

void(float parm) weapon_player_parm1_decode = {
	local float ex, imp, topbit;

	if (parm < 0) {
		topbit = 8388608; /* 0x800000 */
		parm = -parm;
	} else {
		topbit = 0;
	}

	/* Hooo boy.  This is the slow way. */
	ex = 0;
	if (floor(parm) != parm) {
		/* Negative exponent */
		while (floor(parm) != parm) {
			parm *= 2;
			ex--;
		}

		ex += 8;
	} else {
		local float nparm;

		/* Positive exponent */
		nparm = parm * 0.5;
		while (floor(nparm) == nparm) {
			parm = nparm;
			nparm *= 0.5;
			ex++;

			if (ex == 127)
				break;
		}
	}

	self.weapons = topbit | (parm & 8388576) | ex;	/* 0x007fffe0 */
	imp = floor((parm & 31) * 0.5);		/* 0x1f */

	weapon_select_by_impulse(imp);

	if (!self.weapon_imp)
		weapon_select_best();
};

void() _weapon_fire = {
	if (!self.weapon_imp)
		return;

	if (self.w_func(WEAPON_SELECTABLE) <= 0) {
		weapon_select_best();
		if (self.w_func(WEAPON_SELECTABLE) <= 0)
			return;
	}

	self.w_func(WEAPON_FIRE);
};

void() weapon_player_impulse = {
	if (self.attack_finished >= time)
		return;

	if (self.impulse >= 1 && self.impulse <= 8) {
		weapon_select_by_impulse(self.impulse);
		self.impulse = 0;
	}
	
	if (self.button0)
		_weapon_fire();
};

float(float imp) util_impulse_to_IT = {
	if (imp == 1)
		return IT_AXE;
	else if (imp == 2)
		return IT_SHOTGUN;
	else if (imp == 3)
		return IT_SUPER_SHOTGUN;
	else if (imp == 4)
		return IT_NAILGUN;
	else if (imp == 5)
		return IT_SUPER_NAILGUN;
	else if (imp == 6)
		return IT_GRENADE_LAUNCHER;
	else if (imp == 7)
		return IT_ROCKET_LAUNCHER;
	else if (imp == 8)
		return IT_LIGHTNING;
	return 0;
};

void() weapon_set_ammo = {
	self.items &= ~(IT_SHELLS|IT_NAILS|IT_ROCKETS|IT_CELLS);
	if (!self.w_func)
		self.currentammo = 0;
	else
		self.currentammo = self.w_func(WEAPON_AMMO);
};

void(float imp, float idx, float(float action) func) _weapon_select = {
	local float bits, bitmask;

	self.weapon_imp = imp;

	bits = imp*3;
	bitmask = 7*bits;
	bitmask = -bitmask - 1;
	self.weapons &= bitmask;
	self.weapons |= idx*bits;

	self.weapon = util_impulse_to_IT(imp);
	self.w_think = NOTHING_function;
	self.w_func = func;
	self.w_func(WEAPON_SELECT);
};

void(string s) weaponprint = {
	if (is_cl(self))
		centerprint(self, "\[ ", s, " \]\n");
};

float(.float ammo_field, float ammo) util_weapon_use_ammo = {
	if (self.ammo_field < ammo)
		return FALSE;
	self.ammo_field -= ammo;

	return TRUE;
};

float(.float ammo_field, float max_ammo, float ammo) util_weapon_give_ammo = {
	local float ret;

	if (max_ammo > 999) max_ammo = 999;
	ret = increase_field(ammo_field, ammo, max_ammo);

	return ret;
};
