// We cancel schedules when player switches to another weapon -
// WeaponImage::onUnmount and DefaultGame::onClientKilled
datablock TargetProjectileData(GrappleBeam)
{
directDamage = 0.0;
hasDamageRadius = false;
indirectDamage = 0.0;
damageRadius = 0.0;
velInheritFactor = 1.0;
maxRifleRange = 250;
beamColor = "0.1 1.0 0.1";
startBeamWidth = 0.30;
pulseBeamWidth = 0.20;
beamFlareAngle = 3.0;
minFlareSize = 0.0;
maxFlareSize = 400.0;
pulseSpeed = 6.0;
pulseLength = 0.150;
textureName[0] = "special/nonlingradient";
textureName[1] = "special/flare";
textureName[2] = "special/pulse";
textureName[3] = "special/expFlare";
beacon = false;
};
datablock ItemData(GrapplingHook) : TargetingLaser
{
image = GrapplingHookImage;
pickUpName = "a grappling hook";
computeCRC = false;
};
datablock ShapeBaseImageData(GrapplingHookImage) : TargetingLaserImage
{
item = GrapplingHook;
projectile = GrappleBeam;
usesEnergy = true;
minEnergy = 5;
cutOffEnergy = 10;
stateName[3] = "Fire";
stateEnergyDrain[3] = 3;
stateFire[3] = true;
stateAllowImageChange[3] = false;
stateScript[3] = "onFire";
stateTransitionOnTriggerUp[3] = "ReelIn";
stateTransitionOnNoAmmo[3] = "ReelIn";
stateSound[3] = TargetingLaserPaintSound;
//stateTimeoutValue[3] = 2.0;
//stateTransitionOnTimeout[3] = "Deconstruction";
stateTimeoutValue[5] = 1.5;
stateName[6] = "ReelIn";
stateFire[6] = true;
stateSound[6] = TargetingLaserPaintSound;
stateAllowImageChange[6] = false;
stateScript[6] = "onReelIn";
stateTransitionOnTriggerDown[6] = "Deconstruction";
//stateTimeoutValue[6] = 2.0;
//stateTransitionOnTimeout[6] = "Deconstruction";
};
function GrapplingHookImage::onFire(%data, %obj, %slot)
{
//error("GrapplingHookImage::onFire(" SPC %data.getName() SPC %obj.client.nameBase SPC %slot SPC ")");
%p = Parent::onFire(%data, %obj, %slot);
if(isObject(%p))
{
%obj.grapplePos = %p.getTargetPoint();
$GrapplePoint[%obj.client] = %obj.grapplePos;
%dist = vectorDist(%obj.grapplePos , %obj.getPosition());
if(%dist > 250)
{
%p.delete();
%obj.lastProjectile = "";
%obj.grapplePos = "";
return;
}
$ropeLength[%obj.client] = %dist;
echo("**********" NL "**********" NL $ropeLength[%obj.client]);
%obj.grappleObject();
%p.schedule(300, "delete");
}
}
function Player::grappleObject(%obj)
{
if(isObject(%obj))
{
if(isEventPending(%obj.grappleSchedule))
cancel(%obj.grappleSchedule);
if(%obj.getState() !$= "Dead")
{
%pos = %obj.getWorldBoxCenter();
%dist = VectorLen(VectorSub(%pos, $GrapplePoint[%obj.client]));
%vel = %obj.getVelocity();
%rad = VectorSub($GrapplePoint[%obj.client], %pos);
%radx = getWord(%rad, 0); %velx = getWord(%vel, 0);
%rady = getWord(%rad, 1); %vely = getWord(%vel, 1);
%radz = getWord(%rad, 2); %velz = getWord(%vel, 2);
echo($ropeLength[%obj.client]);
if (VectorLen(VectorSub(VectorAdd(%pos, %vel), $GrapplePoint[%obj.client])) > $ropeLength[%obj.client]) {
%radVel = ((%radx * velx) + (%rady * %vely) + (%radz * %velz)) / $ropeLength[%obj.client];
%mass = %obj.getDataBlock().mass;
%force = VectorScale(VectorNormalize(%rad), %radVel);
%newVel = VectorSub(%vel, %force);
if (mSgn(%radz) == 1) {
%force = VectorScale("0 0" SPC %radz, 1 / %dist);
%newVel = VectorAdd(%newVel, %force);
}
%obj.SetVelocity(%newVel);
}
%obj.grappleSchedule = %obj.schedule(250, "grappleObject");
}
}
}
function GrapplingHookImage::onReelIn(%data, %obj, %slot)
{
if(isObject(%obj))
{
// if(isEventPending(%obj.grappleSchedule))
cancel(%obj.grappleSchedule);
%dist = vectorDist(%obj.grapplePos , %obj.getPosition());
if(%dist > 250)
{
%data.deconstruct(%obj, %slot);
return;
}
echo("**********" NL $ropeLength[%obj.client]);
%obj.reelIn();
}
}
$TractorPower = 0.25;
function Player::reelIn(%obj)
{
if(isObject(%obj))
{
if(isEventPending(%obj.reelSchedule))
cancel(%obj.reelSchedule);
if(%obj.getState() !$= "Dead")
{
echo($ropeLength[%obj.client]);
if ($ropeLength[%obj.client] > 2) $ropeLength[%obj.client] -= $TractorPower;
%pos = %obj.getWorldBoxCenter();
%dist = VectorLen(VectorSub(%pos, $GrapplePoint[%obj.client]));
%vel = %obj.getVelocity();
%rad = VectorSub($GrapplePoint[%obj.client], %pos);
%radx = getWord(%rad, 0); %velx = getWord(%vel, 0);
%rady = getWord(%rad, 1); %vely = getWord(%vel, 1);
%radz = getWord(%rad, 2); %velz = getWord(%vel, 2);
if (VectorLen(VectorSub(VectorAdd(%pos, %vel), $GrapplePoint[%obj.client])) > $ropeLength[%obj.client]) {
%radVel = ((%radx * velx) + (%rady * %vely) + (%radz * %velz)) / $ropeLength[%obj.client];
%mass = %obj.getDataBlock().mass;
%force = VectorScale(VectorNormalize(%rad), %radVel);
%newVel = VectorSub(%vel, %force);
if (mSgn(%radz) == 1) {
%force = VectorScale("0 0" SPC %radz, 1 / %dist);
%newVel = VectorAdd(%newVel, %force);
}
%newVel = VectorAdd(%newVel, VectorScale(%rad, $TractorPower));
%obj.SetVelocity(%newVel);
}
%obj.reelSchedule = %obj.schedule(250, "reelIn");
}
}
}
function GrapplingHookImage::deconstruct(%data, %obj, %slot)
{
if (isObject(%obj.lastProjectile))
{
%obj.lastProjectile.delete();
%obj.lastProjectile = "";
}
%obj.grapplePos = "";
if(isEventPending(%obj.grappleSchedule))
cancel(%obj.grappleSchedule);
if(isEventPending(%obj.reelSchedule))
cancel(%obj.reelSchedule);
}
function mSgn(%value) {
if (%value == 0) return "0";
else return %value / mAbs(%value);
}