
$File = "Port Gen";

$PowerGroupCount = 0;

datablock ELFProjectileData(PortGenConnecter)
{
   beamRange         = 5;
   numControlPoints  = 4;
   restorativeFactor = 3.75;
   dragFactor        = 4.5;
   endFactor         = 2.25;
   randForceFactor   = 2;
   randForceTime     = 0.125;

   mainBeamWidth     = 0.1;           // width of blue wave beam
   mainBeamSpeed     = 9.0;            // speed that the beam travels forward
   mainBeamRepeat    = 0.25;           // number of times the texture repeats

   lightningWidth    = 0.1;
   lightningDist     = 0.15;           // distance of lightning from main beam

   textures[0] = "special/ELFBeam";
   textures[1] = "special/pulse";
   textures[2] = "special/expFlare";

   emitter = ELFSparksEmitter;
};

datablock ShapeBaseImageData(DeployGenImage)
{
   mass = 24.0;
   emap = true;

   shapeFile      = "stackable4l.dts";

   item = DeployGenItem;
   deployed = DeployGen;

   mountPoint = 1;
   offset = "0.8 -0.2 -0.25";
   rotation = "0 1 0 90";

   stateName[0] = "Idle";
   stateTransitionOnTriggerDown[0] = "Activate";

   stateName[1] = "Activate";
   stateScript[1] = "onActivate";
   stateTransitionOnTriggerUp[1] = "Idle";

   maxDepSlope = 15;
};

datablock ItemData(DeployGenItem)
{
   className = Pack;
   catagory = "Deployables";
   shapeFile      = "stackable4l.dts";

   mass = 1.5;
   elasticity = 0.1;
   friction = 0.9;
   pickupRadius = 1;

   rotation = "0 1 0 90";

   image = DeployGenImage;
   pickUpName = "a portable generator";

   computeCRC = true;
   emap = true;
};

datablock StaticShapeData(DeployGen) : StaticShapeDamageProfile 
{   
   className      = Generator;
   catagory       = "Generators";
   shapeFile      = "station_generator_large.dts";

   scale = "0.4 0.4 0.4";

   explosion      = ShapeExplosion;
   maxDamage      = 0.70;
   destroyedLevel = 0.65;
   disabledLevel  = 0.45;

   expDmgRadius = 3.0;
   expDamage = 0.2;
   expImpulse = 600.0;

   item = DeployGenItem;

   dynamicType = $TypeMasks::GeneratorObjectType;

   name = "Emergency Generator";

   providesPower = true;

   isShielded = true;
   energyPerDamagePoint = 80;
   maxEnergy = 30;
   rechargeRate = 0.02;

   humSound = GeneratorHumSound;

   deployedObject = true;
   
   cmdCategory = "Support";
   cmdIcon = "CMDGeneratorIcon";
   cmdMiniIconName = "commander/MiniIcons/com_generator";   

   targetNameTag         = 'Emergency Generator';
   targetTypeTag         = 'Emergency Generator';

   debrisShapeName = "debris_generic.dts";
   debris = StaticShapeDebris;
};

function DeployGenImage::onActivate(%Data, %Player, %Slot)
{
   // If all of the item has been deployed.
   if ($TeamDeployedCount[%Player.team, DeployGenImage] >= $TeamDeployableMax[DeployGenImage])
   {
      messageClient(%Player.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.%1', '~wfx/misc/misc.error.wav');
      %Player.setImageTrigger(%Slot, false);
      return;
   }

   // Check along a player's field of view   
   %Object = %Player.searchView(3, $EverythingMask);

   // If nothing was found, then we say so and stop
   if (%Object $= "0")
   {
      messageClient(%Player.client, 'MsgDeployFailed', '\c2Item to power must be within reach.%1', '~wfx/misc/misc.error.wav');
      %Player.setImageTrigger(%Slot, false);
      return;
   }

   // Make sure it is what we want
   %ObjectName = %Object.getDataBlock().getName();

   if (%ObjectName $= "SensorLargePulse" || %ObjectName $= "SensorMediumPulse" || %ObjectName $= "StationInventory" || %ObjectName $= "StationVehicle" || %ObjectName $= "StationVehiclePad" || %ObjectName $= "TurretBaseLarge" || %ObjectName $= "SentryTurret")
   {
      // For simplicity we do it this way
   } else {
      messageClient(%Player.client, 'MsgDeployFailed', '\c2Can not be used to power that.%1', '~wfx/misc/misc.error.wav');
      %Player.setImageTrigger(%Slot, false);
      return;
   }

   // Take the deployable off the player's back and out of inventory
   %Player.unmountImage(%Slot);
   %Player.decInventory(DeployGenItem, 1);  

   // Load where the play is
   %Transform = %Player.getTransform();
   %Position = posFromTransform(%Transform);
   %Rotation = rotFromTransform(%Transform);

   // Make the new Generator at the player feet
   %Generator = new StaticShape()
   {
      dataBlock = DeployGen;
      position = %Position;
      rotation = %Rotation;
      scale = DeployGen.scale;
      owner = %Player.client;
      team = %Player.team;
   };
   MissionCleanUp.Add(%Generator);

   // play the deploy sound
   serverPlay3D(%Item.deploySound, %Position);

   // Move the Generator to the new group
   PortableMoveItem(%Object);

   // Schedule the Object to resume power in 2.2 seconds
   schedule(2200, 0, PortablePowerItem, %Generator, %Object);

   // increment the team count for this deployed object
   $TeamDeployedCount[%Player.team, DeployGenImage]++;

   %Generator.target = createTarget(%Generator, "", "", "", %Generator.getDataBlock().targetTypeTag, %Player.team, 0);
   setTargetSensorGroup(%Generator.getTarget(), %Player.team);

   %ObjectName = %Object.getName();
   if (%ObjectName $= "")
      %ObjectName = %Object.getDataBlock().Name;

   %Message = "Backup Generator installed to maintain power to " @ %ObjectName @ ".";
   messageClient(%Player.client, '', %Message);

   return(%Generator);
}

// This function removes the item from the group it is in and puts it
// in a new group that it uses.  It intentionally disrupts the flow of
// power by calling the losepower.  It also records the original group
// so that it can be put back into the original group if the generator
// is destroyed.
function PortableMoveItem(%Item)
{
   %Item.OriginalGroup = %Item.getGroup();

   // Make sure that there is a deployables group
   %DeployablesGroup = nameToID("MissionCleanup/Deployables");
   if(%DeployablesGroup <= 0)
   {
      %DeployablesGroup = new SimGroup("Deployables");
      MissionCleanup.add(%DeployablesGroup);
   }

   // Increment the counter
   $PowerGroupCount++;

   // Make sure there is a new power group
   %PowerGroup = new SimGroup("PowerGroup" @ $PowerGroupCount);
   %DeployablesGroup.add(%PowerGroup);
   
   %PowerGroup.add(%Item);
   %Item.getDatablock().losePower(%Item);
   %Item.getDataBlock().onLosePowerDisabled(%Item);

   %Pad = %Item.pad;
   if (%Pad !$= "")
      %PowerGroup.Add(%Pad);
}

// This is a seperate function so that it can be scheduled seperately.
// It moves the generator into the group with the item and starts
// powering it.
function PortablePowerItem(%Generator, %Item)
{
   echo("Generator: " @ %Generator);
   echo("Item: " @ %Item);

   // Move the Generator into the group with the item you wish to power
   %ItemGroup = %Item.getGroup();
   %ItemGroup.Add(%Generator);
   %ItemGroup.powerInit(1);

   // Start the powering of the item
   %Item.getDatablock().gainPower(%Item);

   // Record which item you are powering
   %Generator.Powering = %Item;

   %ItemName = %Item.getName();
   if (%ItemName $= "")
      %ItemName = %Item.getDataBlock().Name;

   %Message = %ItemName @ " is now being powered by the portable generator.";
   messageClient(%Player.client, '', %Message);

   %Object = getWord(%Item, 0);
   %ObjectPosition = getWords(%Item, 1, 3);

   %VectorBetween = VectorSub(%ObjectPosition, %Position);

   %Projectile = new ELFProjectile()
   {
      dataBlock        = PortGenConnecter;
      initialDirection = %VectorBetween;
      initialPosition  = %Position;
      sourceObject     = %Generator;
      sourceSlot       = 0;
      targetId         = %Object;
   };
   MissionCleanup.add(%Projectile);

   echo("Portable Generator Beam: " @ %PRojectile);

}

function PortableRestoreItem(%Item)
{
   %OldGroup = %Item.getGroup;

   // Put the item back in the original group
   %ItemGroup = %Item.OriginalGroup;
   %ItemGroup.Add(%Item);

   // If a vehicle pad, move the pad too
   %Pad = %Item.pad;
   if (%Pad !$= "")
      %ItemGroup.Add(%Pad);
   
   // Sound of regaining of power
   if (%Item.isPowered() == true)
   {
      %Item.playAudio(0, BasePowerOn);

      %Item.getDatablock().gainPower(%Item);
      %Item.getDataBlock().onGainPowerDisabled(%Item);
   }

   %OldGroup.delete();
}

function DeployGen::damageObject(%Data, %Generator, %SourceObject, %Position, %Amount, %DamageType)
{
   if (%SourceObject !$= "" && %SourceObject != 0)
   {
      %Generator.lastDamagedBy = %sourceObject.client;
      %Generator.lastDamagedByTeam = %sourceObject.client.team;
      %Generator.damageTimeMS = GetSimTime();
   }

   // Scale damage type & include shield calculations...
   if (%data.isShielded == true)
      %Amount = %Data.checkShields(%Generator, %Position, %Amount, %DamageType);

   %DamageScale = %Data.damageScale[%DamageType];
   if (%DamageScale !$= "")
      %Amount *= %DamageScale;

   // if there's still damage to apply
   if (%Amount > 0)
      %Generator.applyDamage(%Amount);

   %DamageLevel = %Generator.getDamageLevel();
   if (%DamageLevel > %Data.disabledLevel)
   {
      %Item = %Generator.Powering;

      %Item.getDatablock().loosePower(%Item);
      %Item.getDataBlock().onLosePowerDisabled(%Item);

      schedule(1600, 0, PortableRestoreItem, %Item);
      %Item.playAudio(0, BasePowerOff);

      Parent::onDisabled(%Data, %Generator, %prevState);

      %ItemGroup = %Item.getGroup();
      %ItemGroup.powerInit(0);
      
      if (%DamageLevel > %Data.destroyedLevel)
      {
         // Schedule the Deletion of the generator
         %Generator.setDamageState(Destroyed);
         %Generator.schedule(550, delete);

         $TeamDeployedCount[%Generator.team, DeployGenImage]--;  

         %ItemGroup = %Item.getGroup();
      }   
   }
}

function DeployGen::ItemSwap(%Data, %Object)
{
   %Transform = %Object.getTransform();
   %Position = posFromTransform(%Transform);

   %ItemData = %Object.getDataBlock().item;

   %NewItem = new Item()
   {
      dataBlock = %ItemData;
      position = %Position;
   };
   MissionCleanup.add(%NewItem);

   $TeamDeployedCount[%Object.team, DeployGenImage]--;

   %NewItem.applyImpulse(%Position, "0 0 10");

   %Item = %Object.Powering;

   %Item.getDatablock().loosePower(%Item);
   %Item.getDataBlock().onLosePowerDisabled(%Item);

   schedule(1600, 0, PortableRestoreItem, %Item);
   %Item.playAudio(0, BasePowerOff);

   Parent::onDisabled(%Data, %Object, %prevState);

   %Object.delete();

   %ItemGroup = %Item.getGroup();
   %ItemGroup.powerInit(0);

   %NewItem.schedulePop();
}