//////////////////////////////////////////////////////////////////
// Mutator: Elite Weapons XX
// Author: *PingFre@K* A.K.A. J.Bishop
// pingfreak@hotmail.com
// Wrote for Elite Weapons By: *PingFre@K*
//////////////////////////////////////////////////////////////////

class MutEM_XX extends Mutator
      config(EM_XX);

///////////////////////////////////
// 3rdPerson Vars
///////////////////////////////////
var config string Validate;
var config float DefaultCameraScale, MinimumCameraScale, MaximumCameraScale;

///////////////////////////////////
// Game Rules Variable
///////////////////////////////////
var class<GameRules> GRClass;
var array<Controller> DodgeJumpOwners;

///////////////////////////////////
// Replacement Variables
///////////////////////////////////
struct ReplacementInfo
{
	/** class name of the weapon we want to get rid of */
	var name OldClassName;
	/** fully qualified path of the class to replace it with */
	var string NewClassPath;
};

var config array<ReplacementInfo> WeaponsToReplace;
var config array<ReplacementInfo> AmmoToReplace;

///////////////////////////////////
// Movement Variables
///////////////////////////////////
var int rMaxAirDodges;
var int rMaxHoverTime;

/**** Global Config Variables ****/

///////////////////////////////////
// My Content
///////////////////////////////////
struct NewContent
{
   var bool bStartIn3rdPerson;
	var bool bHitSounds;
	var bool bShowDMG;
	var bool bHeadshotSounds;
	var bool bHeadshotMessage;
	var bool bHeater;
	var bool bCooler;
	var bool bVampirism;
	var bool bNoSelfDamage;
	var bool bInventoryDrop;
	var bool bDodgeJumping;
	var int iVampHealth;
	var int iHeater;
	var int iHeaterSeconds;
	var int iHeaterHealthLimit;
	var int iCooler;
	var int iCoolerSeconds;
	var int iCoolerHealthLimit;
   var int iMaxNumJumps;
   var int iMaxJumpBoost;
   var int ijumpZ;
   var int iDodgeSpeed;
   var int iDodgeSpeedZ;
   var int iGroundSpeed;
   var float fAirControl;
   var int iMaxHoverTime;
   var int iMaxAirDodges;
   var int iCrouchJumpBoost;
};
var config NewContent Config_Content;

///////////////////////////////////
/**** Weapon Config Variables ****/
///////////////////////////////////

// BIO Rifle //
struct BioRifle
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var float fPriFireInterval;
   var float fSecFireInterval;
   var float fDamageOverlayTime;
   var float fVehicleDamageScaling;
	var float fVehicleMomentumScaling;
	var float fNodeDamageScaling;
	var float fDripTime;
	var float fAIRating;
	var int iDamage;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iHelpRadius;
	var int iAimError;
	var int iShotCost;
   var int iSpeed;
	var int iMaxResting;
	var int iGlobStrength;
	var int iGloblingSpeed;
	var int iDamageRadius;
	var int iBioRecoil;
   var int iSecSpeed;
   var int iSecDamage;
   var int iSecDamageRadius;
};
var config BioRifle Config_Bio_Rifle;

// Impact Hammer //
struct ImpactHammer
{
	var float fMinDmg;
	var float fMaxDmg;
	var float fMinForce;
	var float fMaxForce;
	var float fMinSelfDmg;
	var float fEMPDmg;
	var float fSelfDmgScale;
	var float fSelfForceScale;
	var float fMaxChargeTime;
	var float fMinChargeTime;
   var float fAIRating;
	var bool bUseHammer;
};
var config ImpactHammer Config_ImpactHammer;

// Enforcer //
struct Enforcer
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var float fPriFireInterval;
	var float fSecFireInterval;
	var float fPriSpread;
	var float fSecSpread;
	var float fAIRating;
	var float fDamageOverlayTime;
	var float fVehicleDamageScaling;
	var float fNodeDamageScaling;
   var float fBurstCoolDownTime;
	var float fVehicleMomentumScaling;
	var int iPriDamage;
	var int iSecDamage;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iShotCost;
	var int iHelpRadius;
	var int iAimError;
	var int fAkimboTime;
	var int iEnforcerRecoil;
	var int iBurstMax;
};
var config Enforcer Config_Enforcer;

// Shock Rifle //
struct ShockRifle
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var float fFireInterval;
	var float fHeadShotDmgMult;
	var float fSlowHeadshotScale;
	var float fRunningHeadshotScale;
	var float fAIRating;
   var float fDamageOverlayTime;
   var float fNodeDamageScaling;
   var float fVehicleDamageScaling;
   var float fVehicleMomentumScaling;
	var int iDamage;
	var int iDamageRadius;
	var int iInstaDamage;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
//	var int iPriHelpRadius;
//	var int iAimError;
	var int iShotCost;
	var int iInstaRecoil;
	var int iSpeed;
//////////////// ADD THESE ////////////////////
   var float fSecFireInterval;
   var int iComboAmmoCost;
   var int iVortexRadius;
   var int iVortexForcePerSecond;
   var float fVortexDuration;
//	var int iComboDamage;
//	var int iComboDamageRadius;
//   var bool bUseCombo;
   var int iDamageImpulse;
	var int iImpulseRadius;
};
var config ShockRifle Config_Shock_Rifle;

// Stinger //
struct Stinger
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
   var float fPriFireInterval;
   var float fSecFireInterval;
   var float fPriSpread;
   var float fSecSpread;
   var float fAIRating;
	var float fNodeDamageScaling;
	var float fVehicleDamageScaling;
	var float fVehicleMomentumScaling;
	var float fDamageOverlayTime;
   var int iShotCost;
	var int iAimingHelpRadius;
	var int iAimError;
	var int iStingerRecoil;
	var int iAmmoCount;
	var int iMaxAmmoCount;
	var int iSpeed;
	var int iDamage;
	var int iDamageRadius;
	var int iMomentumTransfer;
	var int iLifeSpan;
	var int iSecSpeed;
	var int iSecDamage;
	var int iSecDamageRadius;
	var int iSecBounces;
};
var config Stinger Config_Stinger;

// Sniper Rifle //
struct SniperRifle
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var int iDamage;
	var int iPriHelpRadius;
	var int iAimError;
   var int iSniperRecoil;
	var int iShotCost;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iZoomFOV;
	var int iZoomRate;
	var float fHeadShotDmgMult;
	var float fSlowHeadshotScale;
	var float fRunningHeadshotScale;
	var float fFireInterval;
	var float fAIRating;
   var float fDamageOverlayTime;
   var float fNodeDamageScaling;
   var float fVehicleDamageScaling;
   var float fVehicleMomentumScaling;
};
var config SniperRifle Config_Sniper_Rifle;

// Rocket Launcher //
struct RocketLauncher
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var float fPriFireInterval;
	var float fSecFireInterval;
	var float fAcquireTime;
	var float fAIRating;
   var float fDamageOverlayTime;
   var float fNodeDamageScaling;
   var float fVehicleDamageScaling;
   var float fVehicleMomentumScaling;
	var int iDamage;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iHelpRadius;
	var int iAimError;
	var int iSpeed;
	var int iGrenadeSpeed;
	var int iDamageRadius;
	var int ispreaddist;
	var int igrenadespreaddist;
	var int iLockRange;
	var int iShotCost;
   var int iFlockRadius;
   var int iRocketRecoil;
   var int iFlockStiffness;
   var int iFlockCurlForce;
};
var config RocketLauncher Config_RL_BFG;

// Flak Cannon //
struct FlakCannon
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
   var float fAIRating;
	var float fPriFireRate;
	var float fSecFireRate;
	var float fSpread;
	var float fMaxBonusTime;
	var float fCustomGravityScaling;
   var float fDamageOverlayTime;
   var float fNodeDamageScaling;
   var float fVehicleDamageScaling;
   var float fVehicleMomentumScaling;
   var int iFlakRecoil;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iShotCost;
	var int ispeed;
	var int iDamage;
	var int iDamageRadius;
	var int iMomentum;
	var int iShardBounces;
   var int iCenteredDamageBonus;
	var int iMainBounces;
	var int iSecDamageRadius;
	var int iSecDamage;
	var int iSecspeed;
	var int iTossZ;
};
var config FlakCannon Config_FlakCannon;

// Link Gun //
struct LinkGun
{
   var bool bAmmoRegeneration;
   var bool bDoubles;
	var float fPriFireInterval;
	var float fNodeDamageScaling;
	var float fVehicleDamageScaling;
	var float fVehicleMomentumScaling;
	var float fDamageOverlayTime;
	var float fLinkFlexibility;
	var float fAIRating;
	var int iPriDamage;
	var int iSecDamage;
	var int iMomentum;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iProJSpeed;
	var int iDamageRadius;
	var int iBeamAmmoSec;
	var int iWeaponLinkDistance;
	var int iShotCost;
	var int iBeamRange;
	var int iLucyRecoil;
};
var config LinkGun Config_LinkGun;

// Trans //
struct Trans
{
	var bool bUseTrans;
	var float fFireInterval;
   var float fAIRating;
	var int iRechargeRate;
	var int iTossZ;
	var int iSpeed;
	var int iMaxAmmo;
   var int iBuoyancy;
   var int iMomentumTransfer;
   var int iGibPerterbation;
};
var config Trans Config_TransElite;

// AVRIL //
struct GoliathCannon
{
   var bool bAmmoRegeneration;
	var float fFireInterval;
   var float fNodeDamageScaling;
	var float fVehicleDamageScaling;
	var float fVehicleMomentumScaling;
	var float fZoomFOV;
	var float fAIRating;
	var int iZoomRate;
	var int iDamage;
	var int iDmgRadius;
	var int iMomentum;
	var int iSpeed;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iShotCost;
	var int iGoliathRecoil;
};
var config GoliathCannon Config_GoliathCannon;

// Redeemer //
struct Redeemer
{
   var bool bAmmoRegeneration;
	var int iDamage;
	var int iMomentum;
	var int iRocketSpeed;
	var int iAmmoCount;
	var int iMaxAmmo;
	var int iLifeSpan;
	var int iZoomFOV;
	var int iZoomRate;
   var int iShotCost;
   var float fAIRating;
   var float fNodeDamageScaling;
   var float fVehicleDamageScaling;
   var float fVehicleMomentumScaling;
   var int iDeemerRecoil;
};
var config Redeemer Config_RedeemMachine;

///////////////////////////////////
/**** Begin Code: ****/
///////////////////////////////////

///////////////////////////////////
// Replication
///////////////////////////////////
replication
{
	if(Role == ROLE_Authority)
      rMaxAirDodges,
      rMaxHoverTime;
}

///////////////////////////////////
// Misc Code
///////////////////////////////////
function InitMutator(string Options, out string ErrorMessage)
{
	WorldInfo.Game.AddGameRules( GRClass );

// 3rd Person Stuff
    if ( Validate != "VALID" )
    {
        LogInternal( "EliteLOG -> Elite3rdPersonMutator.InitMutator: Config file was not valid.  Recreating." );
        Validate = "VALID";
        DefaultCameraScale = 9.0;
        MinimumCameraScale = 2.0;
        MaximumCameraScale = 20.0;
    }

    if( MinimumCameraScale > MaximumCameraScale ) { MaximumCameraScale = MinimumCameraScale; }

    if ( MaximumCameraScale > 40.0 ) { MaximumCameraScale = 40.0; }
    if ( MinimumCameraScale < 1.0 ) { MinimumCameraScale = 1.0; }

    if ( DefaultCameraScale > 40.0 ) { DefaultCameraScale = 40.0; }
    if ( DefaultCameraScale < 1.0 ) { DefaultCameraScale = 1.0; }

    SaveConfig();
// Break 3rd Person Stuff

	Super.InitMutator(Options, ErrorMessage);
}

function PostBeginPlay()
{
	local UTGame Game;
	local int i, Index;

	Super.PostBeginPlay();

	// replace default weapons
	Game = UTGame(WorldInfo.Game);
	if (Game != None)
	{
		for (i = 0; i < Game.DefaultInventory.length; i++)
		{
			if (Game.DefaultInventory[i] != None)
			{
				Index = WeaponsToReplace.Find('OldClassName', Game.DefaultInventory[i].Name);
				if (Index != INDEX_NONE)
				{
					if (WeaponsToReplace[Index].NewClassPath == "")
					{
						// replace with nothing
						Game.DefaultInventory.Remove(i, 1);
						i--;
					}
					Game.DefaultInventory[i] = class<UTWeapon>(DynamicLoadObject(WeaponsToReplace[Index].NewClassPath, class'Class'));
				}
			}
		}

		if (Game.TranslocatorClass != None)
		{
			Index = WeaponsToReplace.Find('OldClassName', Game.TranslocatorClass.Name);
			if (Index != INDEX_NONE)
			{
				if (WeaponsToReplace[Index].NewClassPath == "")
				{
					// replace with nothing
					Game.TranslocatorClass = None;
				}
				else
				{
					Game.TranslocatorClass = class<UTWeapon>(DynamicLoadObject(WeaponsToReplace[Index].NewClassPath, class'Class'));
				}
			}
		}
	}

	if ( Role == ROLE_Authority )
	{
      if(Config_Content.bHeater)
      {
	   SetTimer(Config_Content.iHeaterSeconds, true, 'HealthADJ');
	   }
	
      if(Config_Content.bCooler)
      {
	   SetTimer(Config_Content.iCoolerSeconds, true, 'CoolerADJ');
	   }

	}

//   if (Config_Content.bDodgeJumping)
//   {
//	if (Config_Content.iMaxNumJumps < 0 || Config_Content.iMaxNumJumps > 99)
//		Config_Content.iMaxNumJumps = 4;

//	if (Config_Content.iMaxJumpBoost < 1 || Config_Content.iMaxJumpBoost > 200)
//		Config_Content.iMaxJumpBoost = 4;
//   }

	if ( UTGame(WorldInfo.Game) != None )
	{
		UTGame(WorldInfo.Game).DefaultInventory.Length = 3;

		if( Config_TransElite.bUseTrans )
		{
			Game.defaultpawnclass=class'EM_XX.TransElite_Pawn';
			Game.bAllowTranslocator = True;
			UTGame(WorldInfo.Game).DefaultInventory[1] = Class'EM_XX.TransElite';
		} 
	   if( Config_ImpactHammer.bUseHammer )
	   {
		   UTGame(WorldInfo.Game).DefaultInventory[2] = Class'EM_XX.Elite_Impact_Hammer';
	   }
   }

   WorldInfo.Game.PlayerControllerClass = Class'EM_XX.ElitePlayer';
	WorldInfo.Game.DefaultPawnClass = Class'EM_XX.ElitePawn';
}

function bool CheckReplacement(Actor Other)
{
	local UTWeaponPickupFactory WeaponPickup;
	local UTWeaponLocker Locker;
	local UTAmmoPickupFactory AmmoPickup, NewAmmo;
	local int i, Index;
	local class<UTAmmoPickupFactory> NewAmmoClass;

	WeaponPickup = UTWeaponPickupFactory(Other);
	if (WeaponPickup != None)
	{
		if (WeaponPickup.WeaponPickupClass != None)
		{
			Index = WeaponsToReplace.Find('OldClassName', WeaponPickup.WeaponPickupClass.Name);
			if (Index != INDEX_NONE)
			{
				if (WeaponsToReplace[Index].NewClassPath == "")
				{
					// replace with nothing
					return false;
				}
				WeaponPickup.WeaponPickupClass = class<UTWeapon>(DynamicLoadObject(WeaponsToReplace[Index].NewClassPath, class'Class'));
				WeaponPickup.InitializePickup();
			}
		}
	}
	else
	{
		Locker = UTWeaponLocker(Other);
		if (Locker != None)
		{
			for (i = 0; i < Locker.Weapons.length; i++)
			{
				if (Locker.Weapons[i].WeaponClass != None)
				{
					Index = WeaponsToReplace.Find('OldClassName', Locker.Weapons[i].WeaponClass.Name);
					if (Index != INDEX_NONE)
					{
						if (WeaponsToReplace[Index].NewClassPath == "")
						{
							// replace with nothing
							Locker.ReplaceWeapon(i, None);
						}
						else
						{
							Locker.ReplaceWeapon(i, class<UTWeapon>(DynamicLoadObject(WeaponsToReplace[Index].NewClassPath, class'Class')));
						}
					}
				}
			}
		}
		else
		{
			AmmoPickup = UTAmmoPickupFactory(Other);
			if (AmmoPickup != None)
			{
				Index = AmmoToReplace.Find('OldClassName', AmmoPickup.Class.Name);
				if (Index != INDEX_NONE)
				{
					if (AmmoToReplace[Index].NewClassPath == "")
					{
						// replace with nothing
						return false;
					}
					NewAmmoClass = class<UTAmmoPickupFactory>(DynamicLoadObject(AmmoToReplace[Index].NewClassPath, class'Class'));
					if (NewAmmoClass == None)
					{
						// replace with nothing
						return false;
					}
					else if (NewAmmoClass.default.bStatic || NewAmmoClass.default.bNoDelete)
					{
						// transform the current ammo into the desired class
						AmmoPickup.TransformAmmoType(NewAmmoClass);
						return true;
					}
					else
					{
						// spawn the new ammo, link it to the old, then disable the old one
						NewAmmo = AmmoPickup.Spawn(NewAmmoClass);
						NewAmmo.OriginalFactory = AmmoPickup;
						AmmoPickup.ReplacementFactory = NewAmmo;
						return false;
					}
				}
			}
		}
	}

	return true;
}

///////////////////////////////////
// Heater Code
///////////////////////////////////
function HealthADJ()
{
	local Pawn P;

   foreach worldInfo.AllPawns(class'Pawn', P)
   {
   if (P.Health < Config_Content.iHeaterHealthLimit)
      {
      P.Health += Config_Content.iHeater;
      }
   }
}

///////////////////////////////////
// Cooler Code
///////////////////////////////////
function CoolerADJ()
{
	local Pawn P;

   foreach worldInfo.AllPawns(class'Pawn', P)
   {
   if (P.Health > Config_Content.iCoolerHealthLimit)
      {
      P.Health += Config_Content.iCooler;
      }
   }
}

///////////////////////////////////
// Movement Modification
///////////////////////////////////
function ModifyPlayer(Pawn Other)
{
	local UTPawn P;
//	local DodgeJump_Info A;
//	local int i, j;

	P = UTPawn(Other);
	if ( P != None )
	{
      P.JumpZ = Config_Content.ijumpZ;
      P.DodgeSpeed = Config_Content.iDodgeSpeed;
      P.DodgeSpeedZ = Config_Content.iDodgeSpeedZ;
      P.GroundSpeed = Config_Content.iGroundSpeed;
	}

// Dodge then Jump // 
/*
   if (Config_Content.bDodgeJumping)
   {
	   if( P.Controller.IsA('UTPlayerController') )
         {
		   j = DodgeJumpOwners.Length;
		   for( i = 0; i < j; i ++ )
		   {
			   if( P.Controller == DodgeJumpOwners[i] )
			   {
				   Super.ModifyPlayer(P);
				   return;
			   }
		   }
   }

		// Create one for this controller.
		DodgeJumpOwners[DodgeJumpOwners.Length] = P.Controller;
		A = Spawn( Class'DodgeJump_Info', P.Controller );
		A.Mutator = Self;
	}
*/
  // Elite Mover //
   if(P.Controller.IsA('ElitePlayer'))
   {
      ElitePlayer(P.Controller).AirResistance = Config_Content.fAirControl; //5.0;
      ElitePlayer(P.Controller).MaxHoverTime = Config_Content.iMaxHoverTime;
      ElitePawn(P).MaxAirDodges = Config_Content.iMaxAirDodges;
      ElitePawn(P).AirDodgeRemaining = Config_Content.iMaxAirDodges;
      ElitePawn(P).WallDodgeRemaining = Config_Content.iMaxAirDodges;
      ElitePawn(P).MaxWallDodges = Config_Content.iMaxAirDodges;
   }

	Super.ModifyPlayer(P);
}

///////////////////////////////////
// Multi Jump Infomation
///////////////////////////////////
function NotifyLogin(Controller NewPlayer)
{
	local MultiJump_Info A;

   if( UTPlayerController( NewPlayer ) != None )
   {
		A = Spawn( Class'EM_XX.MultiJump_Info', NewPlayer );
		A.riMaxNumJumps = Config_Content.iMaxNumJumps;
		A.riMaxJumpBoost = Config_Content.iMaxJumpBoost;
   }

	Super.NotifyLogin(NewPlayer);
}

defaultproperties
{
   GRClass=Class'EM_XX.EliteMachine_GameRules'
   
   Validate="VALID"
   DefaultCameraScale=9.000000
   MinimumCameraScale=2.000000
   MaximumCameraScale=20.000000

   WeaponsToReplace(0)=(OldClassName="UTWeap_RocketLauncher",NewClassPath="EM_XX.Elite_Rocket_Launcher")
   WeaponsToReplace(1)=(OldClassName="UTWeap_BioRifle_Content",NewClassPath="EM_XX.Elite_Bio_Rifle")
   WeaponsToReplace(2)=(OldClassName="UTWeap_FlakCannon",NewClassPath="EM_XX.Elite_FlakCannon")
   WeaponsToReplace(3)=(OldClassName="UTWeap_SniperRifle",NewClassPath="EM_XX.Elite_Sniper_Rifle")
   WeaponsToReplace(4)=(OldClassName="UTWeap_LinkGun",NewClassPath="EM_XX.Elite_Link")
   WeaponsToReplace(5)=(OldClassName="UTWeap_ImpactHammer",NewClassPath="EM_XX.Elite_Impact_Hammer")
   WeaponsToReplace(6)=(OldClassName="UTWeap_Enforcer",NewClassPath="EM_XX.Elite_Enforcer")
   WeaponsToReplace(7)=(OldClassName="UTWeap_ShockRifle",NewClassPath="EM_XX.Elite_Shock")
   WeaponsToReplace(8)=(OldClassName="UTWeap_Stinger",NewClassPath="EM_XX.Elite_Stinger")
   WeaponsToReplace(9)=(OldClassName="UTWeap_Avril_Content",NewClassPath="EM_XX.Goliath_Cannon")
   WeaponsToReplace(10)=(OldClassName="UTWeap_Redeemer_Content",NewClassPath="UTWeap_Redeemer_Content")

   AmmoToReplace(0)=(OldClassName="UTAmmo_RocketLauncher",NewClassPath="")
   AmmoToReplace(1)=(OldClassName="UTAmmo_BioRifle_Content",NewClassPath="")
   AmmoToReplace(2)=(OldClassName="UTAmmo_FlakCannon",NewClassPath="")
   AmmoToReplace(3)=(OldClassName="UTAmmo_SniperRifle",NewClassPath="")
   AmmoToReplace(4)=(OldClassName="UTAmmo_LinkGun",NewClassPath="")
   AmmoToReplace(5)=(OldClassName="",NewClassPath="")
   AmmoToReplace(6)=(OldClassName="UTAmmo_Enforcer",NewClassPath="")
   AmmoToReplace(7)=(OldClassName="UTAmmo_ShockRifle",NewClassPath="")
   AmmoToReplace(8)=(OldClassName="UTAmmo_Stinger",NewClassPath="")
   AmmoToReplace(9)=(OldClassName="UTAmmo_AVRiL",NewClassPath="")
   AmmoToReplace(10)=(OldClassName="",NewClassPath="")

   RemoteRole=ROLE_SimulatedProxy
   bAlwaysRelevant=True
   Name="MutEM_XX"
}
