mirror of
https://github.com/mostlikely4r/construction-mod.git
synced 2026-01-19 19:24:44 +00:00
239 lines
6.2 KiB
C#
239 lines
6.2 KiB
C#
// 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);
|
|
}
|
|
}
|