// TruPhysics engine v0.6 - physics engine by DynaBlade
// Mainly used for vehicles but can be expanded.

// String Table
$TruPhysics::Enabled = true;
$TruPhysics::maxVelocity = 1500; // 1500 m/s or about 5400 KPH, T2's universal speed limit

function capVelocity(%vel)
{
   if(velToSingle(%vel) > $TruPhysics::maxVelocity)
      return $TruPhysics::maxVelocity;
   else
      return mFloor(%vel);
}

function VehicleData::onCollision(%data,%obj,%col,%mod,%pos,%normal)
{

    if(%data.disablePhysics || !$TruPhysics::Enabled) // !enabled = default vehicle physics, local or global scope
        return;

    %className = %data.className;

    if(%col.isPlayer()) // player is dead and wants to be run over / annihilated.
    {
       %mass = -0.25 * %col.getMass();
       %vec = vectorScale(vectorScale(%col.getVelocity(), 0.25), %mass);
       %obj.applyImpulse(%col.getPosition(), %vec);
    }
    else if(%col.isVehicle())                                       // phreakynasty!
    {
         if(%col.getDamageState() $= "Destroyed")                          // nothing to collide with here, get back to movement!
             return;

         %AMass = %obj.getMass();
         %AiVec = vectorScale(%obj.getVelocity(), %mass);
         %APos = vectorNormalize(%obj.getForwardVector());

         %BMass = %obj.getMass();
         %BiVec = vectorScale(%obj.getVelocity(), %mass);
         %BPos = vectorNormalize(%obj.getForwardVector());

         %obj.applyImpulse(%BPos, %BiVec);
         %col.applyImpulse(%APos, %AiVec);
    }
}


function checkWaterPhysics(%obj)
{

    if(%obj.isWet)
    {
        // water absorbs about 75% of your velocity when you hit it.
        %mass = %obj.getMass() * 0.75;
        %iVec = vectorScale(%obj.getVelocity(), %mass);
        %obj.applyImpulse(%obj.getTransform(), %iVec);

        // speed tolerance checking (in KPH)
        %mass = %obj.getMass();
        %pct = %obj.getDamagePct() / 4;
        %max = %pct * (%data.minDrag * 10);
        %maxSpeed = %max - (%mass / getRandom(10, 12));
        %vel = msToKPH(velToSingle(%obj.getVelocity()));

        if(%maxSpeed > %vel)
            %obj.getDatablock().damageObject(%obj, 0, "0 0 0", %maxSpeed - %vel, $DamageType::Default);

        schedule(100, %obj, "checkWaterPhysics", %obj);
    }
}

function VehicleData::onEnterLiquid(%data, %obj, %coverage, %type)
{
    if(!%data.disableWaterPhysics && $TruPhysics::Enabled)
    {
        %obj.isWet = true;
        checkWaterPhysics(%obj);
    }

   switch(%type)
   {
      case 0:
         //Water
         %obj.setHeat(0.0);
      case 1:
         //Ocean Water
         %obj.setHeat(0.0);
      case 2:
         //River Water
         %obj.setHeat(0.0);
      case 3:
         //Stagnant Water
         %obj.setHeat(0.0);
      case 4:
         //Lava
         %obj.liquidDamage(%data, $VehicleDamageLava, $DamageType::Lava);
      case 5:
         //Hot Lava
         %obj.liquidDamage(%data, $VehicleDamageHotLava, $DamageType::Lava);
      case 6:
         //Crusty Lava
         %obj.liquidDamage(%data, $VehicleDamageCrustyLava, $DamageType::Lava);
      case 7:
         //Quick Sand
   }
}

function VehicleData::onLeaveLiquid(%data, %obj, %type)
{
    %obj.isWet = false;
    // exiting from the water becomes easier if your engines are on... speed doubles?
    if(!%data.disableWaterPhysics && $TruPhysics::Enabled)
    {
        %mass = %obj.getMass() * 0.375;
        %iVec = capVel(vectorScale(%obj.getVelocity(), %mass));
        %obj.applyImpulse(%obj.getTransform(), %iVec);
    }

   switch(%type)
   {
      case 0:
         //Water
         %obj.setHeat(1.0);
      case 1:
         //Ocean Water
         %obj.setHeat(1.0);
      case 2:
         //River Water
         %obj.setHeat(1.0);
      case 3:
         //Stagnant Water
         %obj.setHeat(1.0);
      case 4:
         //Lava
      case 5:
         //Hot Lava
      case 6:
         //Crusty Lava
      case 7:
         //Quick Sand
   }

   if(%obj.lDamageSchedule !$= "")
   {
      cancel(%obj.lDamageSchedule);
      %obj.lDamageSchedule = "";
   }
}

datablock AudioProfile(EngineAlertSound)
{
   filename    = "gui/vote_nopass.WAV";
   description = AudioExplosion3d;
   preload = true;
};

function VDUndo(%obj)
{
   %obj.vdOverride = false;
   %obj.dmgApplyImp = false;
}

function vDmgApplyImpulse(%obj)
{
   if(%obj.getDatablock().forceSensitive)
      return;

    %obj.dmgApplyImp = true;
    %lastPct = %obj.lastDmgPct;
    %pct = %obj.getDamagePct();

    if(%lastPct > %pct)
    {
       %obj.vdOverride = true;
       schedule(1000, 0, "VDUndo", %obj);
    }

    %obj.tp_sndCnt++;

    if(((%pct >= 0.5 && %pct < 1) && (%obj.vdOverride == false || %obj.vdOverride == "")) && %obj.augType !$= "Auto Repair Bot")
    {
        %force = (%pct * 500) * getRandom(1);
        if(%force)
        {
            %va = getRandom(1) ? getRandom() * -1 : getRandom();
            %vb = getRandom(1) ? getRandom() * -1 : getRandom();
            %vc = getRandom(1) ? getRandom() * -1 : getRandom();
            %vec = %va SPC %vb SPC %vc;
            %nVec = vectorScale(%vec, %force);

            %seed = getRandom(100);
            if(%seed > 60 && %seed < 90)
                %obj.playThread(0, "maintainback");
            else if(%seed > 90)
                %obj.playThread(0, "maintainbot");
            else
                %obj.playThread(0, "activateback");

            %obj.applyImpulse(%obj.getTransform(), %nVec);
        }
        %obj.lastDmgPct = %pct;
        schedule(250, %obj, "vDmgApplyImpulse", %obj);

        if(%obj.tp_sndCnt >= 4)
        {
            %obj.tp_sndCnt = 0;
            %obj.play3D(EngineAlertSound);
        }
    }
    else
        %obj.stopThread(0);
}

function VehicleData::onDamage(%this,%obj)
{

   %damage = %obj.getDamageLevel();
   if (%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         if(%obj.respawnTime !$= "")
            %obj.marker.schedule = %obj.marker.data.schedule(%obj.respawnTime, "respawn", %obj.marker);
         %obj.setDamageState(Destroyed);
      }
   }
   else
   {
      if(%obj.getDamageState() !$= "Enabled")
         %obj.setDamageState(Enabled);

        %pct = %obj.getDamagePct();

        if(%pct >= 0.6 && !%obj.dmgApplyImp)
            vDmgApplyImpulse(%obj);
   }
}
