I like the grapple. With some tweaking it will probably work really well. The grabber could probably use a bit of work. Fortunately (like I said), I wrote something similar for work:
//////////////////////////////
// Class: ToolMover
// Desc: A tool that can pick up, move and rotate the desired object
// Author: Luke 'Ambershee' Parkes-Haskell
//////////////////////////////
class ToolMover extends Tool;
var float WeaponImpulse;
var float HoldDistanceMin;
var float HoldDistanceMax;
var float ThrowImpulse;
var float ChangeHoldDistanceIncrement;
var RB_Handle PhysicsGrabber;
var float HoldDistance;
var Quat HoldOrientation;
var rotator NewRot;
simulated function StartFire( optional byte FireModeNum )
{
local vector CamLoc, StartShot, EndShot, X, Y, Z;
local vector HitLocation, HitNormal, Extent;
local actor HitActor;
local float HitDistance;
local Quat PawnQuat, ActorQuat;
local TraceHitInfo HitInfo;
local SkeletalMeshComponent SkelComp;
local rotator CamRot;
if (FireModeNum == 0)
{
Instigator.Controller.GetPlayerViewPoint(CamLoc, CamRot);
// Do ray check and grab actor
GetAxes( CamRot, X, Y, Z );
StartShot = CamLoc;
EndShot = StartShot + (10000.0 * X);
Extent = vect(0,0,0);
HitActor = Trace(HitLocation, HitNormal, EndShot, StartShot, True, Extent, HitInfo);
HitDistance = VSize(HitLocation - StartShot);
if( HitActor != None && HitActor != WorldInfo && HitDistance > HoldDistanceMin && HitDistance < HoldDistanceMax )
{
// If grabbing a bone of a skeletal mesh, dont constrain orientation.
PhysicsGrabber.GrabComponent(HitInfo.HitComponent, HitInfo.BoneName, HitLocation, PlayerController(Instigator.Controller).bRun==0);
// If we succesfully grabbed something, store some details.
if( PhysicsGrabber.GrabbedComponent != None )
{
HoldDistance = HitDistance;
PawnQuat = QuatFromRotator( CamRot );
if ( HitInfo.BoneName != '' )
{
SkelComp = SkeletalMeshComponent(HitInfo.HitComponent);
ActorQuat = SkelComp.GetBoneQuaternion(HitInfo.BoneName);
}
else
{
ActorQuat = QuatFromRotator( PhysicsGrabber.GrabbedComponent.Owner.Rotation );
}
HoldOrientation = QuatProduct ( QuatInvert ( PawnQuat ), ActorQuat );
}
}
}
else
{
if ( PhysicsGrabber.GrabbedComponent != None )
{
PhysicsGrabber.ReleaseComponent();
bMode = false;
}
}
}
simulated function StopFire( optional byte FireModeNum )
{
//We used to do something. Left in in case we later want to do something.
}
exec function WeaponModeToggle()
{
if(bMode)
{
//Cheesy hack to regrab object and retain rotation after toggling out of rotation mode.
StopFire(1);
StartFire(0);
bMode = false;
}
else
{
if ( PhysicsGrabber.GrabbedComponent != None )
{
StopFire(1);
StartFire(0);
bMode = true;
}
}
}
event Tick(float DeltaTime)
{
local vector CamLoc, NewHandlePos, X, Y, Z;
local rotator CamRot;
super.Tick(DeltaTime);
if ( PhysicsGrabber.GrabbedComponent == None )
{
return;
}
PhysicsGrabber.GrabbedComponent.WakeRigidBody( PhysicsGrabber.GrabbedBoneName );
Instigator.Controller.GetPlayerViewPoint(CamLoc, CamRot);
GetAxes( CamRot, X, Y, Z );
// Update handle position on grabbed actor.
NewHandlePos = CamLoc + (HoldDistance * X);
PhysicsGrabber.SetLocation( NewHandlePos );
if (bMode == false)
{
PhysicsGrabber.SetOrientation ( QuatProduct ( QuatFromRotator ( CamRot ) , HoldOrientation ) );
}
}
simulated function bool DoOverrideNextWeapon()
{
HoldDistance -= ChangeHoldDistanceIncrement;
return true;
}
simulated function bool DoOverridePrevWeapon()
{
HoldDistance += ChangeHoldDistanceIncrement;
return true;
}
simulated function RotateObject(Rotator ObjectRot)
{
if (PhysicsGrabber.GrabbedComponent != None)
{
NewRot += PhysicsGrabber.GrabbedComponent.Rotation + ObjectRot;
PhysicsGrabber.SetOrientation( QuatFromRotator (NewRot) );
}
}
function DrawToolInfo(Canvas Canvas)
{
Canvas.DrawText("Move Tool in", FALSE, 1, 1);
Canvas.SetPos(400,50);
if (bMode)
{
Canvas.DrawText("Rotate Mode", FALSE, 1, 1);
}
else
{
Canvas.DrawText("Move Mode", FALSE, 1, 1);
}
}
DefaultProperties
{
HoldDistanceMin=150.0
HoldDistanceMax=750.0
WeaponImpulse=600.0
ThrowImpulse=800.0
ChangeHoldDistanceIncrement=50.0
Begin Object Class=RB_Handle Name=RB_Handle0
End Object
PhysicsGrabber=RB_Handle0
Components.Add(RB_Handle0)
InventoryGroup = 1;
bMode = false;
}
Note that the class it extends is very similar to the UTWeapon class, save that it is considerably more simple and doesn't contain any UT specific logic. The exec WeaponModeToggle was bound to a key to allow for switching between tool modes of movement and rotation. Notably, we don't need the rotation part anyway, just the normal grabber. I reckon this code will port almost directly across into UT.