script ROPE_HOLD (int ropeTID, int length, int strength)
{
int myX; int myY; int myZ;
int ropeX; int ropeY; int ropeZ;
int velX; int velY; int velZ;
int normX; int normY; int normZ;
int pullX; int pullY; int pullZ;
int rPullX; int rPullY; int rPullZ;
int mag; int mode;
strength = (strength << 16) / 100;
strength = FixedMul(strength, strength);
if (length == -1)
{
myX = GetActorX(0); myY = GetActorY(0); myZ = GetActorZ(0);
ropeX = GetActorX(ropeTID); ropeY = GetActorY(ropeTID); ropeZ = GetActorZ(ropeTID);
velX = myX - ropeX; velY = myY - ropeY; velZ = myZ - ropeZ;
length = magnitudeThree(velX >> 16, velY >> 16, velZ >> 16);
}
int playerTID = ActivatorTID();
if ((playerTID != 0) || (ThingCount(0, playerTID) != 1))
{
playerTID = unusedTID(5000, -1);
Thing_ChangeTID(0, playerTID);
}
while (ThingCount(0, ropeTID) == 1)
{
myX = GetActorX(0); myY = GetActorY(0); myZ = GetActorZ(0);
ropeX = GetActorX(ropeTID); ropeY = GetActorY(ropeTID); ropeZ = GetActorZ(ropeTID);
velX = myX - ropeX; velY = myY - ropeY; velZ = myZ - ropeZ;
// this is where precision goes down the drain
mag = magnitudeThree(velX >> 16, velY >> 16, velZ >> 16);
normX = velX / mag; normY = velY / mag; normZ = velZ / mag;
if (mag > length)
{
rPullX = ropeX + (normX * length);
rPullY = ropeY + (normY * length);
rPullZ = ropeZ + (normZ * length);
pullX = -(velX - (normX * length));
pullY = -(velY - (normY * length));
pullZ = -(velZ - (normZ * length));
pullX = FixedMul(pullX, strength);
pullY = FixedMul(pullY, strength);
pullZ = FixedMul(pullZ, strength);
SetActorPosition(0, rPullX, rPullY, rPullZ, 0);
SetActorVelocity(0, pullX, pullY, pullZ, 1, 0);
}
ACS_ExecuteAlways(ROPE_DRAWLINE, 0, ropeTID, playerTID, 24);
Delay(1);
}
if (ThingCount(0, ropeTID) > 1)
{
Log(s:"Error: more than one object with tid ", d:ropeTID, s:" (is used for rope)");
}
}