class GrapplingHook extends UTBeamWeapon;
var bool bCoolingoff;
var bool bHooked;
var vector HookLocation, Force;
var float GrappleLength, Omega, CForce;
var int Counter;
var float CoolDowntime;
replication
{
// Things the server tells the client
if (ROLE == ROLE_Authority)
HookLocation, GrappleLength, bHooked, bCoolingoff;
}
// Constantly updates what is going on
function UpdateGrappleStatus()
{
if (Owner == None) return;
if (bHooked)
{
if (Owner.Physics != PHYS_Falling)
{
GotoState('StopState');
return;
}
Counter++;
// Update angular velocity every 3rd tick; gives a less spiralled path
if (Counter == 3)
{
// Angular velocity
GrappleLength = VSize(HookLocation - Owner.Location);
// If the chain gets too long
if (GrappleLength > 2500)
{
GotoState('StopState');
return;
}
Omega = VSize(Owner.Velocity / GrappleLength) * 0.03;
Counter = 0;
}
// Centripetal force
CForce = 25 * GrappleLength * Omega ^ 2;
// Centripetal force is towards centre of circle
Force = Normal(HookLocation - Owner.Location);
Force *= CForce;
Owner.Velocity += 0.04 * Force;
// Clamp maximum velocity
if (VSize(Owner.Velocity) > 1300)
Owner.Velocity = Normal(Owner.Velocity) * 1300;
else if (VSize(Owner.Velocity) < -1300)
Owner.Velocity = - (Normal(Owner.Velocity) * 1300);
}
}
// What happens when we Fire
simulated function StartGrapple()
{
local vector HitLocation, HitNormal;
local Actor Other;
// Don't start grappling if we're already grappling
if (bHooked)
return;
// End trace to stop people grappling stupidly long distances
Other = Trace(HitLocation, HitNormal, Owner.Location + (2500 * Vector(GetAdjustedAim( Owner.Location ))), Owner.Location, TRUE,,, TRACEFLAG_Bullet);
if (Other == None)
return;
if (!Other.IsA('Pawn') && !Other.IsA('Projectile') && !Other.IsA('Decoration'))
{
bHooked = True;
HookLocation = HitLocation;
GrappleLength = VSize(HitLocation - Owner.Location);
//Kick player
//Owner.Velocity += vect(0,0,100) + VRand() * 64;
Owner.Velocity += Normal(HookLocation - Owner.Location) * 200;
SetTimer(0.01,True,'UpdateGrappleStatus');
}
}
function StopGrapple()
{
bHooked = False;
SetTimer(0.01,False,'UpdateGrappleStatus');
if (bCoolingOff == True)
{
//Do nothing and let it pass to CoolOff;
}
if (bCoolingOff == False)
{
Owner.Velocity += vect(0,0,700) + VRand() * 64;
}
GotoState('CoolOff');
}
// Fire to call Normal or Alt Fire
simulated function BeginFire(byte FireModeNum)
{
if (FireModeNum == 0)
{
GotoState('WeaponFiring');
}
Super.BeginFire(FireModeNum);
}
// What happens when we stop Firing
simulated function EndFire(Byte FireModeNum)
{
if (FireModeNum == 0)
{
GotoState('StopState');
}
Super.EndFire(FireModeNum);
}
simulated state WeaponFiring
{
Begin:
StartGrapple();
}
// Stop Grappling and Kill Everything
state StopState
{
Begin:
StopGrapple();
}
state CoolOff
{
Begin:
if (bHooked == True)
bCoolingoff = False;
else if ( bHooked == False)
bCoolingoff = True;
sleep(CoolDowntime);
bCoolingoff = False;
}
// Defaults
defaultproperties
{
Counter=0
InventoryGroup=1
Begin Object Name=FirstPersonMesh ObjName=FirstPersonMesh
FOV=70.000000
SkeletalMesh=SkeletalMesh'WP_GrablingGun.Mesh.SK_WP_ShockRifle_1P'
AnimSets(0)=AnimSet'WP_GrablingGun.Anim.K_WP_ShockRifle_1P_Base'
End Object
CoolDowntime=0.50000
AmmoCount=1
MaxAmmoCount=1
ShotCost(0)=0
Mesh=FirstPersonMesh
Begin Object Name=PickupMesh ObjName=PickupMesh
SkeletalMesh=SkeletalMesh'WP_GrablingGun.Mesh.SK_WP_ShockRifle_3P'
End Object
DroppedPickupMesh=PickupMesh
PickupFactoryMesh=PickupMesh
Name="Default__GrapplingHook"
ObjectArchetype=UTWeapon'UTGame.Default__UTWeapon'
AttachmentClass=class'grapplingattachment'
WeaponFireSnd[0]=SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_FireCue'
WeaponEquipSnd=SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_RaiseCue'
WeaponPutDo wnSnd=SoundCue'A_Weapon_ShockRifle.Cue.A_Weapon_SR_LowerCue'
PickupSound=SoundCue'A_Pickups.Weapons.Cue.A_Pickup_Weapons_Shock_Cue'
}