
class ZWeapon : Weapon
{

	transient CVar replacespriteCVar;
	transient CVar setpitchCVar;
	transient CVar zoomfactorCVar;

	action void A_ReplaceSprite(String myvar, String ssprite, bool pickup=false, float sscale=0.7)
	{
		if(!invoker.replacespriteCVar) invoker.replacespriteCVar = CVar.FindCVar(myvar);
		CVar readsetting = invoker.replacespriteCVar;

		if (readsetting && readsetting.GetInt()==1) {
			if(pickup) {
				invoker.sprite = GetSpriteIndex(ssprite);
				invoker.A_SetScale(sscale);
			} else {
				if (player) Player.GetPSprite(PSP_WEAPON).sprite = GetSpriteIndex(ssprite);
			}
		}
	}

	action void A_SetPitchD3D(String myvar, float ppitch)
	{
		if(!invoker.setpitchCVar) invoker.setpitchCVar = CVar.FindCVar(myvar);
		CVar readsetting = invoker.setpitchCVar;

		if(readsetting)
		{
			float recoilf = readsetting.GetFloat();
			if(recoilf>=0.0 && recoilf<=2.0)
			{
				ppitch = ppitch * recoilf;
			}
		}

		self.A_SetPitch (pitch + ppitch);
	}

	action void A_ZoomFactorD3D(String myvar, float zzoom)
	{
		if(!invoker.zoomfactorCVar) invoker.zoomfactorCVar = CVar.FindCVar(myvar);
		CVar readsetting = invoker.zoomfactorCVar;

		if(readsetting)
		{
			float recoilf = readsetting.GetFloat();
			if(recoilf>=0.0 && recoilf<=2.0)
			{
				zzoom = 1.0 - ((1.0-zzoom) * recoilf);
			}
		}

		//A_ZoomFactor(zzoom);

		let player = self.player;
		if (player != NULL && player.ReadyWeapon != NULL)
		{
			zzoom = 1 / clamp(zzoom, 0.1, 50.0);
			player.ReadyWeapon.FOVScale = zzoom;
		}
	}

	action state A_CheckActorUnmorph(string actortounmorph, float distancerange, StateLabel failstate)
	{
		float closest_distance = (distancerange+1)*(distancerange+1);
		Actor closest = null;

		ThinkerIterator Finder = ThinkerIterator.Create(actortounmorph, STAT_DEFAULT);
		Actor mo = null;

		while ( (mo = Actor(Finder.Next())) )
		{
			if (mo == self || mo.health <= 0 || mo.bDormant || !mo.bShootable) { continue; }
			if (!mo.bISMONSTER || mo.bFriendly) { continue; }
			if (mo.bInvisible || mo.bINVULNERABLE) { continue; }
			if (!CheckSight(mo)) { continue; }
			if (absangle(self.angle,self.angleto(mo))>90) { continue; }
			double mo_distance = self.distance3DSquared(mo);
			if (mo_distance > distancerange*distancerange) { continue; }
			if (closest && mo_distance > closest_distance) { continue; }
			let inv = mo.FindInventory("MonsterPossessed");
			if (inv!=null && inv.Amount>0) { continue; }

			closest = mo;
			closest_distance = mo_distance;
		}

		if(closest) {
			let ashrinkerfx = Spawn("ShrinkerMorphFXOrigin", self.pos);
			ashrinkerfx.master = self;
			ashrinkerfx.bINVISIBLE = true;

			int chealth = closest.health;
			closest.tracer = ashrinkerfx;
			closest.A_Die("Unmorph");
			closest.health = chealth*2.0;
			self.A_TakeInventory("ShrinkerAmmo",7);

			return null;
		} else {
			return ResolveState(failstate);
		}
	}

	action state A_JumpIfTotalAmmo(string item1, string item2, int itemamount, statelabel label)
	{
		int ammo1 = 0;
		int ammo2 = 0;
		let inv1 = self.FindInventory(item1);
		let inv2 = self.FindInventory(item2);

		if (inv1!=null && inv1.Amount>=0) {ammo1 = inv1.Amount;}
		if (inv2!=null && inv2.Amount>=0) {ammo2 = inv2.Amount;}

		int totalammo = ammo1 + ammo2;

		if (totalammo >= itemamount) {
			return ResolveState(label);
		} else {
			return null;
		}
	}

	action void A_TakeCombinedAmmo(string item1, string item2, int totalitemamount, int loadeditemamount)
	{
		int ammo1 = 0;
		int ammo2 = 0;
		let inv1 = self.FindInventory(item1);
		let inv2 = self.FindInventory(item2);

		if ( (inv1!=null && inv1.Amount>=0) && (inv2!=null && inv2.Amount>=0) )
		{
			int delta = inv1.Amount - (totalitemamount - loadeditemamount);

			if (delta >= 0 ) {
				inv1.Amount = delta;
				inv2.Amount = inv2.Amount - loadeditemamount;
			} else {
				inv1.Amount = 0;
				inv2.Amount = inv2.Amount - (loadeditemamount + abs(delta));
			}
		}
	}

	action void A_ForceReFire(bool primary=true, bool secondary=true, statelabel flash = null)
	{
		let player = player;
		if (NULL == player)
		{
			return;
		}

		if ( primary && (player.cmd.buttons & BT_ATTACK) && player.ReadyWeapon.bAltFire )
		{
			player.ReadyWeapon.bAltFire = false;
		}
		else if ( secondary && (player.cmd.buttons & BT_ALTATTACK) && !player.ReadyWeapon.bAltFire )
		{
			player.ReadyWeapon.bAltFire = true;
		}

		if ( (primary && (player.cmd.buttons & BT_ATTACK) ) || (secondary && (player.cmd.buttons & BT_ALTATTACK) ) ) {
			A_ReFire(flash);
		}
	}

	override void PlayPickupSound(Actor toucher)
	{
		super.PlayPickupSound(toucher);

		let inv = toucher.FindInventory("DukeTaunting");
		if (inv==null || inv.Amount==0) {
			toucher.A_PlaySound("duke/weaponup",CHAN_VOICE); 
			toucher.A_GiveInventory("DukeTaunting",1);
		}
	}

	override void AttachToOwner(Actor other)
	{
		if(self.GetClassName() == "Dual Pistol") {
			if (!other.FindInventory("DualPistolClip")) other.A_GiveInventory("DualPistolClip", 24);
		}
		else if(self.GetClassName() == "Shotgun ") {
			if (!other.FindInventory("ShotgunShell")) other.A_GiveInventory("ShotgunShell", 8);
		}
		else if(self.GetClassName() == "SSG") {
			if (!other.FindInventory("SSGShell")) other.A_GiveInventory("SSGShell", 2);
		}

		super.AttachToOwner(other);
	}

	override void OnDrop(Actor dropper)
	{
		if(self.GetClassName() == "Pistol ") {
			ZDukePlayer(dropper).wpistol = null;
		}
		else if(self.GetClassName() == "Shotgun ") {
			ZDukePlayer(dropper).wshotgun = null;
		}
		else if(self.GetClassName() == "Plasma Cannon") {
			ZDukePlayer(dropper).wplasma = null;
		}
		else if(self.GetClassName() == "Expander") {
			ZDukePlayer(dropper).wexpander = null;
		}
		else if(self.GetClassName() == "Incinerator Flamethrower") {
			ZDukePlayer(dropper).wincinerator = null;
		}

		super.OnDrop(dropper);
	}

}