I love the smell of UnrealEd crashing in the morning. – tarquin
Legacy:Mod Ideas/LocalGravity
Moved from my Personal Projects page
Local Gravity[edit]
The Idea[edit]
The Idea is to allow mappers greater control of the gravity in the map, allowing people to walk on walls, around a planet, or in general whatever can make a level more fun.
The Progress[edit]
My progress thus far has been with editing the PlayerSpidering state of the Playercontroller, and here is most of my code thus far.
//============================================================================= // GravPlayer.uc //============================================================================= class GravPlayer extends xPlayer; var float MaxAcceleration, AccelerationDampening; function Possess(Pawn aPawn) { Super.Possess(aPawn); GoToState('PlayerSpidering'); } state PlayerSpidering { function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { local vector OldAccel; OldAccel = Pawn.Acceleration; if ( Pawn.Acceleration != NewAccel ) Pawn.Acceleration = NewAccel; if ( bPressedJump ) DoJump(bUpdating); } //Should put in the Pawn if possible, to eaise bot Implementation. function bool DoJump( bool bUpdating ) { if ( !Pawn.bIsCrouched && !Pawn.bWantsToCrouch && Pawn.Physics == PHYS_Spider ) { if ( Pawn.Role == ROLE_Authority ) { if ( (Level.Game != None) && (Level.Game.GameDifficulty > 2) ) MakeNoise(0.1 * Level.Game.GameDifficulty); if ( Pawn.bCountJumps && (Pawn.Inventory != None) ) Pawn.Inventory.OwnerEvent('Jumped'); } if ( Pawn.Physics == PHYS_Spider ) Pawn.Velocity += Pawn.JumpZ * Pawn.Floor; if ( (Pawn.Base != None) && !Pawn.Base.bWorldGeometry ) Pawn.Velocity.Z += Pawn.Base.Velocity.Z; Pawn.PhysicsVolume.Gravity = vect(0,0,0); Pawn.SetPhysics(PHYS_Falling); return true; } return false; } function UpdateRotation(float DeltaTime, float maxPitch) { local rotator ViewRotation; local vector MyFloor, CrossDir, FwdDir, OldFwdDir, OldX, RealFloor, PawnX, PawnZ; if ( bInterpolating || Pawn.bInterpolating ) { ViewShake(deltaTime); return; } TurnTarget = None; bRotateToDesired = false; bSetTurnRot = false; if ( (Pawn.Base == None) || (Pawn.Floor == vect(0,0,0)) ) { if(OldFloor == vect(0,0,0)) OldFloor = vect(0,0,1); MyFloor = OldFloor; } else MyFloor = Pawn.Floor; if ( MyFloor != OldFloor ) { // smoothly change floor RealFloor = MyFloor; MyFloor = Normal(6*DeltaTime * MyFloor + (1 - 6*DeltaTime) * OldFloor); if ( (RealFloor Dot MyFloor) > 0.999 ) MyFloor = RealFloor; else { // translate view direction CrossDir = Normal(RealFloor Cross OldFloor); FwdDir = CrossDir Cross MyFloor; OldFwdDir = CrossDir Cross OldFloor; ViewX = MyFloor * (OldFloor Dot ViewX) + CrossDir * (CrossDir Dot ViewX) + FwdDir * (OldFwdDir Dot ViewX); ViewX = Normal(ViewX); ViewZ = MyFloor * (OldFloor Dot ViewZ) + CrossDir * (CrossDir Dot ViewZ) + FwdDir * (OldFwdDir Dot ViewZ); ViewZ = Normal(ViewZ); OldFloor = MyFloor; ViewY = Normal(MyFloor Cross ViewX); } } //Moved here because it is already calculated here //Pawn.FaceRotation(OrthoRotation(ViewX,ViewY,ViewZ), deltaTime ); if ( (aTurn != 0) || (aLookUp != 0) ) { // adjust Yaw based on aTurn if ( aTurn != 0 ) ViewX = Normal(ViewX + ViewY * Sin(0.0031*DeltaTime*aTurn)); // adjust Pitch based on aLookUp if ( aLookUp != 0 ) { OldX = ViewX; ViewX = Normal(ViewX + ViewZ * Sin(0.0031*DeltaTime*aLookUp)); ViewZ = Normal(ViewX Cross ViewY); //bound max pitch //Redo this now /*if ( (ViewZ Dot MyFloor) < 0.1 ) { OldX = Normal(OldX - MyFloor * (MyFloor Dot OldX)); if ( (ViewX Dot MyFloor) > 0) ViewX = Normal(OldX + MyFloor); else ViewX = Normal(OldX - MyFloor); ViewZ = Normal(ViewX Cross ViewY); }*/ } // calculate new Y axis ViewY = Normal(MyFloor Cross ViewX); } ViewRotation = OrthoRotation(ViewX,ViewY,ViewZ); SetRotation(ViewRotation); ViewShake(deltaTime); ViewFlash(deltaTime); PawnX = Normal(ViewY Cross MyFloor); PawnZ = Normal(PawnX Cross ViewY); Pawn.FaceRotation(OrthoRotation(PawnX,ViewY,PawnZ), deltaTime ); //Pawn.FaceRotation(ViewRotation, deltaTime ); } function PlayerTick(float DeltaTime) { local Vector HitLocation, HitNormal, X, Y, Z; local Actor HitActor; Super.PlayerTick(DeltaTime); GetAxes(Pawn.Rotation, X, Y, Z); if(Pawn.Physics == PHYS_Falling) { if(VSize(Pawn.Acceleration) > MaxAcceleration) Pawn.Acceleration = Normal(Pawn.Acceleration) * MaxAcceleration; else Pawn.Acceleration *= AccelerationDampening; Pawn.Acceleration += Z * Pawn.PhysicsVolume.default.Gravity.Z; Pawn.Velocity += Pawn.Acceleration*DeltaTime; //Pawn.Acceleration = vect(0,0,0); //Change 70 to something less, static. HitActor = Trace(HitLocation, HitNormal, Pawn.Location+Normal(Pawn.Velocity)*100, Pawn.Location); if(HitActor != None && HitActor.bWorldGeometry) { Log("Here2"); Pawn.SetPhysics(PHYS_Spider); Pawn.SetBase(HitActor , HitNormal); } } } } defaultproperties { AccelerationDampening=0.1 MaxAcceleration=200 PawnClass=class'LocalGravity.GravPawn' }
ProcessMove is overridden to use a DoJump in this class, will probally get rid of this when I move that code back to the Pawn.
UpdateRotation is mostly the same as in PlayerController.uc, except for a bit of math, that being in the middle of the function, no real way I could reuse it without copying it.
Now, what I would like some suggestions on, are in my PlayerTick. the Trace that I am doing has a static number in there, I kinda need a better way, this will make you stick to soon when falling straight down, or not at all when falling too diagonal.
Ohh yes, and we want to be able to get it into our map. So, an Actor!
//============================================================================= // LocalGravActor.uc //============================================================================= class LocalGravActor extends Actor placeable; var() Class<PlayerController> PCClass< SEMI > var() string PlayerClassName; function PreBeginPlay() { Level.Game.PlayerControllerClass = PCClass< SEMI > Level.Game.DefaultPlayerClassName = PlayerClassName; } defaultproperties { PCClass=class'LocalGravity.GravPlayer' PlayerClassName="LocalGravity.GravPawn" bHidden=true }
To Do[edit]
The most pressing matters are finding a better way to see if we should be on something then
HitActor = Trace(HitLocation, HitNormal, Pawn.Location+Normal(Pawn.Velocity)*100, Pawn.Location); if(HitActor != None && HitActor.bWorldGeometry)
Then fix thirdperson camera, allow more flexibality when creating the level, and giving bots the same flexibility
Comments[edit]
Glacian: I am working on a similar mod, maybe we could combine forces....muwahaha! I fixed the bounded view angle problem by substituting in quaternion rotation, and I've coded up some modified gravity, doublejumping, and dodging code to work at any angle. I stuck only on the problem of getting the physics to allow the pawn to walk on the wall, and phys_spidering has some behaviors I don't like. If you (or anyone else) are interested, my email is focusgir (at) yahoo (dot) com.