//================================================================================
// - UTEW_ShockRifle Mutator by SC]-[LONG_{HoF}
// - Additional code provided from BlackCheetah's UT2004 Weapons for UT99.
// - Additional code provided from Wormbo's Enhanced Items.
// - Possibly code that isn't required but I was to lazy to remove it. -SC
// - If anyone would like to improve on this weapon please feel free. Just please leave documentation. -SC
//================================================================================
class UTEW_ShockMut expands Mutator;

// additional HUD mutator variables
var PlayerPawn PlayerOwner;	// the PlayerPawn owning the HUD this mutator is registered to
var HUD MyHUD;	// HUD this mutator is registered to
var ChallengeHUD MyChallengeHUD;	// ChallengeHUD this mutator is registered to
var bool bPendingHUDRegistration;	// the RegisterHUDMutator() function has failed, so try again later
var bool bKeepStationaryPawns;	// Excludes StationaryPawn classes from CheckReplacement()

function AddMutator(Mutator M)
{
	if ( M == Self )
		return;	// I'm already added to the mutators list
	else if ( M.Class == Class )
		M.Destroy();	// already have a mutator of this class
	Super.AddMutator(M);
}

function bool AlwaysKeep(Actor Other)
{
	local bool bTemp;
	
	if ( bKeepStationaryPawns && Other.IsA('StationaryPawn') )
		return true;

	if ( NextMutator != None )
		return ( NextMutator.AlwaysKeep(Other) );
	return false;
}

function bool CheckReplacement(Actor Other, out byte bSuperRelevant)
{
	local Inventory Inv;

	bSuperRelevant = 1;

	Inv = Inventory(Other);
 	if ( Inv == None )
	{
		bSuperRelevant = 0;
		if ( Other.IsA('TorchFlame') )
			Other.NetUpdateFrequency = 0.5;
		return true;
	}

	if ( (Other.IsA('Weapon')) || ( Other.IsA('TournamentWeapon')) || ( Other.IsA('UIWeapon')) )
	{

		if (Other.Class==Class'ShockRifle')
		{
			ReplaceWith(Other, "UTEW_ShockRifle.UTEW_ShockRifle");
			return false;
		}

		bSuperRelevant = 0;
		return true;

	}

	if (Other.IsA('Ammo') )
	{

		if (Other.Class==Class'ShockCore')
		{
			ReplaceWith(Other,"UTEW_ShockRifle.UTEW_ShockCore");
			return false;
		}

		bSuperRelevant = 0;
		return true;

	}

	bSuperRelevant = 0;
	return true;

}

// correctly unregister this mutator from all linked mutator chains
simulated function Destroyed()
{
	local Mutator M;
	local HUD H;
	
	if ( Level.Game != None )
	{
		if ( Level.Game.BaseMutator == Self )
			Level.Game.BaseMutator = NextMutator;
		if ( Level.Game.DamageMutator == Self )
			Level.Game.DamageMutator = NextDamageMutator;
		if ( Level.Game.MessageMutator == Self )
			Level.Game.MessageMutator = NextMessageMutator;
	}
	ForEach AllActors(Class'Engine.HUD', H)
		if ( H.HUDMutator == Self )
			H.HUDMutator = NextHUDMutator;
	ForEach AllActors(Class'Engine.Mutator', M)
	{
		if ( M.NextMutator == Self )
			M.NextMutator = NextMutator;
		if ( M.NextHUDMutator == Self )
			M.NextHUDMutator = NextHUDMutator;
		if ( M.NextDamageMutator == Self )
			M.NextDamageMutator = NextDamageMutator;
		if ( M.NextMessageMutator == Self )
			M.NextMessageMutator = NextMessageMutator;
	}
}

// Give a weapon to a player and optionally bring it up as current weapon.
function Weapon GiveWeapon(Pawn PlayerPawn, string aClassName, optional bool bBringUp)
{
	local class<Weapon> WeaponClass;
	local Weapon NewWeapon;

	WeaponClass = class<Weapon>(DynamicLoadObject(aClassName, class'Class'));

	if ( PlayerPawn.FindInventoryType(WeaponClass) != None )
		return None;
	newWeapon = Spawn(WeaponClass);
	if ( newWeapon != None )
	{
		newWeapon.RespawnTime = 0.0;
		newWeapon.GiveTo(PlayerPawn);
		newWeapon.bHeldItem = true;
		newWeapon.GiveAmmo(PlayerPawn);
		newWeapon.SetSwitchPriority(PlayerPawn);
		newWeapon.WeaponSet(PlayerPawn);
		newWeapon.AmbientGlow = 0;
		if ( PlayerPawn.IsA('PlayerPawn') )
			newWeapon.SetHand(PlayerPawn(PlayerPawn).Handedness);
		else
			newWeapon.GotoState('Idle');
		if ( bBringUp )
		{
			PlayerPawn.Weapon.GotoState('DownWeapon');
			PlayerPawn.PendingWeapon = None;
			PlayerPawn.Weapon = newWeapon;
			PlayerPawn.Weapon.BringUp();
		}
	}
	return newWeapon;
}

// Modified version of the ReplaceWith function
// Replaces an inventory Other with an inventory of class aClassName and
// returns a reference to it
final function Inventory ReplaceWithItem(Inventory Other, coerce string aClassName)
{
	local Inventory A;
	local class<Inventory> aClass;
	local bool bAllowItemFall, bForceItemFall;
	local bool bAllowItemRotation, bForceItemRotation;

	if ( Other.Location == vect(0,0,0) )
		return None;
	aClass = class<Inventory>(DynamicLoadObject(aClassName, class'Class'));
	if ( aClass != None )
		A = Spawn(aClass, Other.Owner, Other.Tag, Other.Location + (aClass.Default.CollisionHeight - Other.CollisionHeight) * vect(0,0,1), Other.Rotation);
	
	if ( Other.MyMarker != None ) {
		Other.MyMarker.markedItem = A;
		if ( A != None )
			A.MyMarker = Other.MyMarker;
		Other.MyMarker = None;
	}
	else if ( A != None ) {
		A.bHeldItem = true;
		A.Respawntime = 0.0;
	}
	
	if ( A != None ) {
		if ( Other.Physics != Other.Class.Default.Physics ) {
			if ( Other.Physics == PHYS_Falling )
				bForceItemFall = True;
			else if ( Other.Class.Default.Physics == PHYS_Falling )
				bAllowItemFall = False;
		}
		if ( (!Other.bRotatingPickup || Other.RotationRate == rot(0,0,0))
				&& (Other.Rotation.Pitch != 0 || Other.Rotation.Roll != 0) )
			bAllowItemRotation = False;
		else
			bAllowItemRotation = (Other.RotationRate != rot(0,0,0) && Other.bRotatingPickup)
					|| !Other.default.bRotatingPickup || Other.default.RotationRate == rot(0,0,0);
		bForceItemRotation = Other.RotationRate != rot(0,0,0) && Other.bRotatingPickup
				&& (!Other.default.bRotatingPickup || Other.default.RotationRate == rot(0,0,0));
		
		if ( A.Physics == PHYS_Falling && !bAllowItemFall )
			A.SetPhysics(PHYS_None);
		else if ( A.Physics != PHYS_Falling && bForceItemFall )
			A.SetPhysics(PHYS_Falling);
		A.bRotatingPickup = bAllowItemRotation && (A.bRotatingPickup || bForceItemRotation);
		
		A.Event = Other.Event;
		A.Tag = Other.Tag;
		return A;
	}
	return None;
}


// also add bPendingHUDRegistration=True to make the mutator automatically register itself as HUD mutator
simulated function RegisterHUDMutator()
{
	local PlayerPawn P;
	local Mutator M;
	
	bPendingHUDRegistration = False;
	
	if ( PlayerPawn(Owner) != None ) 
	{
		P = PlayerPawn(Owner);
		if ( P.MyHUD != None )
		{
			For (M = P.MyHUD.HUDMutator; M != None; M = M.NextHUDMutator)
				if ( M.Class == Class )
					break;
			if ( M == None || M.Class != Class ) 
			{
				NextHUDMutator = P.MyHUD.HUDMutator;
				MyHUD = P.MyHUD;
				MyChallengeHUD = ChallengeHUD(MyHud);
				if ( P.MyHUD.HUDMutator != None )
					log("RegisterHUDMutator: Registered"@Name$", NextHUDMutator is"@P.MyHUD.HUDMutator.Name);
				P.MyHUD.HUDMutator = Self;
				PlayerOwner = P;
				bHUDMutator = True;
			}
		}
	}
	else ForEach AllActors(class'Engine.PlayerPawn', P)
		if ( P.MyHUD != None )
		{
			For (M = P.MyHUD.HUDMutator; M != None; M = M.NextHUDMutator)
				if ( M.Class == Class )
					break;
			if ( M != None && M.Class == Class )
				continue;	// already registered, check next PlayerPawn
			NextHUDMutator = P.MyHUD.HUDMutator;
			MyHUD = P.MyHUD;
			MyChallengeHUD = ChallengeHUD(MyHud);
			if ( P.MyHUD.HUDMutator != None )
				log("RegisterHUDMutator: Registered"@Name$", NextHUDMutator is"@P.MyHUD.HUDMutator.Name);
			P.MyHUD.HUDMutator = Self;
			PlayerOwner = P;
			bHUDMutator = True;
		}
	
	if ( !bHUDMutator )
	{
		bPendingHUDRegistration = True;
		Enable('Tick');
	}
}

// always call Super.Tick(DeltaTime) to ensure the HUD registration works
simulated function Tick(float DeltaTime)
{
	if ( Level.NetMode != NM_DedicatedServer && !bHUDMutator && bPendingHUDRegistration )
		RegisterHUDMutator();
}

// this is missing in the original PostRender() function of Engine.Mutator
simulated function PostRender(Canvas Canvas)
{
	if ( NextHUDMutator != None )
		NextHUDMutator.PostRender(Canvas);
}

defaultproperties
{
     bAlwaysRelevant=True
     bNetTemporary=True
     RemoteRole=ROLE_SimulatedProxy
}
