Volumes are a painful way to do gravity wells. Things are much easier if you can get someone to make a class that does it right.
For those interested in UT2003/2004 gravity wells, I've got some code that works quite nicely. I snatched most of it from the vortex weapon in ChaosUT and tweaked it to work as a placeable, persistent actor. I tweaked the acceleration formula to be simpler so that you can make acceleration constant and then falloff linearly past a certain point, rather than the square root one (which was probably more realistic but gave less control.)
Code:
//=============================================================================
// Gravity Well
//=============================================================================
//Chunks of code shamelessly stolen from ChaosUT's VortexProj, edited by Bumber
class GravityWell extends Actor
placeable;
var(GravityWell) float Gravity, MinRange, MaxRange;
var(GravityWell) bool bIgnoreProjectiles, bIgnoreOcclusion, bHelpStuckPawns;
simulated function Tick(float DeltaTime)
{
local Actor thisActor;
local Pawn thisPawn;
local vector dir, ActorLocation;
local float dist, DeltaV;
ForEach CollidingActors(class'Actor', thisActor, MaxRange, Location)
{
if (!IsMovable(thisActor) || !IsVisible(thisActor))
continue;
if (!bIgnoreOcclusion && !FastTrace(thisActor.Location, Location))
continue;
thisPawn = Pawn(thisActor);
if (thisActor.Physics == PHYS_Karma)
thisActor.KGetCOMPosition(ActorLocation);
else
ActorLocation = thisActor.Location;
dir = Normal(Location - ActorLocation);
dist = VSize(Location - ActorLocation);
if (dist <= MinRange)
DeltaV = Gravity * DeltaTime;
else
DeltaV = Gravity * DeltaTime * (1 - (dist - MinRange) / (MaxRange - MinRange));
if (thisActor.Physics == PHYS_Karma || thisActor.Physics == PHYS_KarmaRagdoll)
{
if (!thisActor.KIsAwake())
thisActor.KWake();
thisActor.KAddImpulse(dir * DeltaV * thisActor.Mass * thisActor.KGetMass(), ActorLocation, 'bip01 Spine');
}
else if (thisPawn != None)
{
if (bHelpStuckPawns && dist < 64)
dir = 10 * Normal(thisPawn.Velocity);
thisPawn.AddVelocity(dir * DeltaV);
}
else
{
if (thisActor.Physics == PHYS_None || thisActor.Physics == PHYS_Rotating)
{
if (thisActor.IsA('GameObject') && thisActor.IsInState('Home'))
thisActor.GotoState('Dropped');
thisActor.SetPhysics(PHYS_Falling);
thisActor.Velocity = vect(0,0,1) * 80;
}
if (thisActor.Physics == PHYS_Projectile)
{
if (!bIgnoreProjectiles)
{
thisActor.SetRotation(thisActor.Rotation - rotator(thisActor.Velocity));
thisActor.Velocity += dir * DeltaV;
thisActor.SetRotation(thisActor.Rotation + rotator(thisActor.Velocity));
}
}
else
thisActor.Velocity += dir * DeltaV;
}
}
}
//=============================================================================
// IsVisible
//=============================================================================
simulated function bool IsVisible(Actor Other)
{
return !Other.bHidden && (Other.DrawType == DT_Mesh || Other.DrawType == DT_StaticMesh
|| Other.DrawType == DT_Sprite || Other.DrawType == DT_SpriteAnimOnce
|| Other.DrawType == DT_RopeSprite || Other.DrawType == DT_VerticalSprite);
}
//=============================================================================
// IsMovable
//=============================================================================
simulated function bool IsMovable(Actor Other)
{
if (Other.bStatic || Other.bNoDelete)
return false;
if (Other.IsA('GameObject') && (Other.Physics == PHYS_None || Other.Physics == PHYS_Rotating))
return Other.IsInState('Dropped') || Other.IsInState('Home');
if (Other.IsA('UnrealPawn') && (Other.Physics == PHYS_Walking
|| Other.Physics == PHYS_Falling || Other.Physics == PHYS_Swimming
|| Other.Physics == PHYS_Flying || Other.Physics == PHYS_Spider
|| Other.Physics == PHYS_Ladder || Other.Physics == PHYS_KarmaRagDoll))
return true;
if (Other.IsA('Pickup') && Pickup(Other).bDropped)
return true;
return Other.Physics == PHYS_Projectile || Other.Physics == PHYS_Falling || Other.Physics == PHYS_Karma;
}
//=============================================================================
// DefaultProperties
//=============================================================================
defaultproperties
{
bHidden=true;
bIgnoreProjectiles=false;
bIgnoreOcclusion=true;
bHelpStuckPawns=false;
Gravity=950;
MinRange=512;
MaxRange=1024;
}
I've now added options for occlusion (in case you want solid objects to block gravity) and for disabling the effect of gravity on projectiles. I've also added an option to help pawns not get stuck in the dead center of the gravity well for strong gravities.
It would be great if someone could add functionality for spider physics (like in the Apoc Matrix Moves mutator or the electromagnet powerup of the RPG mutator) so we could make actual round planets you could walk on, but it's beyond my skill for the moment.
Bookmarks