#include "swapper.qh"

#ifdef SVQC
MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon)
{
	if (MUTATOR_RETURNVALUE || game_stopped)
		return;

	entity player = M_ARGV(0, entity);
	if (!StatusEffects_active(BUFF_SWAPPER, player))
		return;

	entity head = WarpZone_FindRadius(player.origin, autocvar_g_buffs_swapper_range, false);
	entity closest = NULL;
	float head_dist2, best_dist2 = autocvar_g_buffs_swapper_range ** 2;
	for (; head; head = head.chain)
		if (IS_PLAYER(head) && DIFF_TEAM(head, player)
		&& !IS_DEAD(head) && !STAT(FROZEN, head) && !head.vehicle)
		{
			head_dist2 = vlen2(head.WarpZone_findradius_dist);
			if (head_dist2 < best_dist2)
			{
				best_dist2 = head_dist2;
				closest = head;
			}
		}
	if (closest == NULL)
		return;

	vector my_org = player.origin;
	vector my_vel = player.velocity;
	vector my_ang = player.angles;
	vector their_org = closest.origin;
	vector their_vel = closest.velocity;
	vector their_ang = closest.angles;

	Drop_Special_Items(closest);

	MUTATOR_CALLHOOK(PortalTeleport, player); // initiate flag dropper

	setorigin(player, their_org);
	setorigin(closest, my_org);

	closest.velocity = my_vel;
	closest.angles = my_ang;
	if (IS_BOT_CLIENT(closest))
	{
		closest.v_angle = closest.angles;
		bot_aim_reset(closest);
	}
	closest.fixangle = true;
	closest.oldorigin = my_org;
	closest.oldvelocity = my_vel;
	player.velocity = their_vel;
	player.angles = their_ang;
	if (IS_BOT_CLIENT(player))
	{
		player.v_angle = player.angles;
		bot_aim_reset(player);
	}
	player.fixangle = true;
	player.oldorigin = their_org;
	player.oldvelocity = their_vel;

	// set pusher so player gets the kill if they fall into void
	closest.pusher = player;
	closest.pushltime = time + autocvar_g_maxpushtime;
	closest.istypefrag = PHYS_INPUT_BUTTON_CHAT(closest);

	Send_Effect(EFFECT_ELECTRO_COMBO, their_org, '0 0 0', 1);
	Send_Effect(EFFECT_ELECTRO_COMBO, my_org, '0 0 0', 1);

	sound(player,  CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);
	sound(closest, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);

	// TODO: add a counter to handle how many times one can teleport, and a delay to prevent spam
	buff_RemoveAll(player, STATUSEFFECT_REMOVE_NORMAL);
	return true;
}
#endif // SVQC
#ifdef MENUQC
METHOD(SwapperBuff, describe, string(SwapperBuff this))
{
	TC(SwapperBuff, this);
	PAGE_TEXT_INIT();
	PAR(_("The %s buff allows you to press %s to switch places with a nearby enemy once."), COLORED_NAME(this), strcat("^3", _("drop weapon"), "^7"));
	PAR(_("A common usage of this buff is to jump over the map's void, then swap with an enemy, to cause them to fall into the void."));
	PAR(_("The range that the buff works over is limited, so sometimes it may do nothing if there are no enemies nearby."));
	return PAGE_TEXT;
}
#endif // MENUQC
