deathpax

swJumpPad.uc

May 12th, 2020
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.39 KB | None | 0 0
  1. // ============================================================================
  2. //  swJumpPad.
  3. //
  4. //  Ported to unreal by Death Pax, adjusted to work with ScriptedPawns
  5. //
  6. //  Improved JumpPad/Kicker Actor that calculates jump force automatically.
  7. //  Does not require additional Trigger/LiftExit/LiftCenter actors.
  8. //  Familiar placing procedure - just like Teleporters.
  9. //  Path links visible in UnrealEd.
  10. //  Bot support.
  11. //  Can be disabled/enabled with Triggers.
  12. //  Support for on-jump special effects.
  13. //  Allows jump angle and destination randomisation.
  14. //  Supports custom vertical gravity, ie: LowGrav mutator.
  15. //
  16. // ============================================================================
  17. //  Copyright 2005 Roman Switch` Dzieciol, neai o2.pl
  18. //  http://wiki.beyondunreal.com/wiki/Switch
  19. // ============================================================================
  20. //  One-way JumpPad Tutorial:
  21. //  - swJumpPads are placed like Teleporters:
  22. //  - TWO swJumpPad actors are required: Source and Destination.
  23. //  - In Source swJumpPad set "URL" to some name.
  24. //  - In Destination swJumpPad set "Tag" to that name.
  25. //  - Adjust JumpAngle if neccessary.
  26. //  - Congratulations, you have set up a one-way botbot-friendly JumpPad.
  27. //
  28. // ============================================================================
  29. //  Tips:
  30. //
  31. //  - JumpAngle will be limited to 1-89 degrees.
  32. //
  33. //  - If the JumpAngle is too low, a theoretically valid one will be calculated
  34. //    ingame and warning message will be broadcasted every time someone jumps.
  35. //
  36. //  - For testing precision, doublejump into JumpPad from distance, this way
  37. //    you won't accidentially disrupt your jump with movement keys.
  38. //
  39. //  - Ignore other Teleporter properties other than URL, it's not a teleporter.
  40. //
  41. //  - If you want to change jump parameters, change them in the Source JumpPad,
  42. //    not the Destination one.
  43. //
  44. //  - bTraceGround requires that there are no holes under the center of
  45. //    Destination JumpPad. If there is one, ie if the JumpPad is placed on edge
  46. //    of a cliff, players will be launched at the ground level in the hole, ie
  47. //    bottom of the cliff. To fix this move Destination JumpPad away from the
  48. //    edge or disable bTraceGround.
  49. //    
  50. // ============================================================================
  51. //  Angle random modes:
  52. //  
  53. //  AM_Random  
  54. //      Uses random value from range ( JumpAngle, JumpAngle+AngleRand )
  55. //      
  56. //  AM_Extremes
  57. //      Uses JumpAngle then JumpAngle+AngleRand then repeat. Lets suppose that
  58. //      two players walk into JumpPad one after another. Player who jumped
  59. //      first may arrive at target location *later* than player who jumped
  60. //      second if the jump angle of second player was significatly flatter.
  61. //      
  62. //  AM_Owned        
  63. //      Team==TeamNumber uses JumpAngle, other teams use JumpAngle+AngleRand
  64. //
  65. // ============================================================================
  66. //  bLogParams acronyms:
  67. //  
  68. //  A   = Angle
  69. //  IV  = Impact velocity in Z plane
  70. //  IS  = Impact velocity in XY plane
  71. //  IH  = Impact height
  72. //  T   = Time in ms
  73. //  P   = Peak height
  74. //  V   = Jump velocity
  75. //  G   = Gravity
  76. //  U   = URL
  77. //  PN  = Player Name
  78. //  N   = Source JumpPad name
  79. //  D   = Destination JumpPad name
  80. //
  81. // ============================================================================
  82. class swJumpPad expands Teleporter;
  83.  
  84.  
  85. enum EAngleMode
  86. {
  87.     AM_Random,      
  88.     AM_Extremes,    
  89.     AM_Owned        
  90. };
  91.  
  92.  
  93. // ============================================================================
  94. // Source JumpPad Properties
  95. // ============================================================================
  96.  
  97. var(JumpPad) float          JumpAngle;          // Jump angle
  98.  
  99. var(JumpPad) byte           TeamNumber;         // Team number
  100. var(JumpPad) bool           bTeamOnly;          // Other teams can't use it
  101.  
  102. var(JumpPad) float          TargetZOffset;      // Target location height offset
  103. var(JumpPad) vector         TargetRand;         // Target location random range
  104. var(JumpPad) bool           bTraceGround;       // Find ground below JumpPad and use it as target location
  105.  
  106. var(JumpPad) float          AngleRand;          // Jump angle random range
  107. var(JumpPad) EAngleMode     AngleRandMode;      // Jump angle random range mode
  108.  
  109. var(JumpPad) bool           bDisabled;          // Disable, triggering JumpPad toggles this
  110.  
  111. var(JumpPadFX) class<Actor> JumpEffect;         // Spawn this actor at JumpPad when someone jumps
  112. var(JumpPadFX) class<Actor> JumpPlayerEffect;   // Spawn this actor at jumping player
  113. var(JumpPadFX) name         JumpEvent;          // Trigger this event when someone jumps
  114. var(JumpPadFX) sound        JumpSound;          // Play this sound when someone jumps
  115. var(JumpPadFX) bool         bClientSideEffects; // Spawn effects only on clients
  116.  
  117. var(JumpPadDebug) float     JumpWait;           // Disable JumpPad for JumpWait seconds after jump
  118. var(JumpPadDebug) bool      bLogParams;         // Display jump parameters in log and ingame
  119.  
  120. var Pawn Pending;
  121.  
  122. // ============================================================================
  123. // Internal
  124. // ============================================================================
  125.  
  126. var Actor JumpTarget;
  127. var Actor JumpActor;
  128. var bool bSwitchAngle;
  129. var float MinAngleCurve;
  130. var float MinAngleFinder;
  131. var float MinAngle;
  132. var float MaxAngle;
  133.  
  134. Const RadianToDegree    = 57.2957795131;
  135. Const DegreeToRadian    = 0.01745329252;
  136. Const RadianToURot      = 10430.3783505;
  137. Const URotToRadian      = 0.000095873799;
  138. Const DegreeToURot      = 182.04444444;
  139. Const URotToDegree      = 0.00549316;
  140.  
  141. simulated function PostBeginPlay()
  142. {
  143.     Super(NavigationPoint).PostBeginPlay();
  144.     if( URL == "" )
  145.         ExtraCost = 0;
  146. }
  147.  
  148. simulated function bool Accept( actor Incoming)
  149. {
  150.     return false;
  151. }
  152.  
  153. simulated function Trigger( Actor Other, Pawn EventInstigator )
  154. {
  155.     local int i;
  156.  
  157.     bEnabled = !bEnabled;
  158.     if( bEnabled ) // launch any pawns already in my radius
  159.         for( i=0; i<4; i++)
  160.             if( Touching[i] != None )
  161.                 Touch(Touching[i]);
  162. }
  163.  
  164. simulated function ShowMessage( coerce string s, optional Actor A, optional bool bID )
  165. {
  166.     if( bID )
  167.         s = s $ GetIdentifier(A);
  168.    
  169.     if( Role == ROLE_Authority )
  170.         BroadcastMessage( s, true );
  171.    
  172.     Log( s, name );
  173. }
  174.  
  175. simulated function float GetAngle( Actor Other )
  176. {
  177.     switch( AngleRandMode )
  178.     {
  179.         case AM_Random:
  180.             return RandRange( JumpAngle, JumpAngle+AngleRand );
  181.            
  182.         case AM_Extremes:
  183.             bSwitchAngle = !bSwitchAngle;
  184.             return JumpAngle + AngleRand*float(bSwitchAngle);
  185.            
  186.         case AM_Owned:
  187.             if( Pawn(Other) != None && Pawn(Other).PlayerReplicationInfo.Team != TeamNumber )
  188.                     return JumpAngle+AngleRand;
  189.             else    return JumpAngle;
  190.     }  
  191. }
  192.  
  193. simulated function string GetIdentifier( Actor A )
  194. {
  195.     local string S;
  196.     local Pawn P;
  197.  
  198.     S = S @ "U=[" $URL$ "]";
  199.  
  200.     P = Pawn(A);
  201.     if( P != None )
  202.     {
  203.         S = S @ "PN=[";
  204.         if( P.PlayerReplicationInfo != None
  205.         &&  P.PlayerReplicationInfo.PlayerName != "" )
  206.                 S = S $P.PlayerReplicationInfo.PlayerName;
  207.         else    S = S $P.Name;  
  208.         S = S $ "]";
  209.     }
  210.     S = S @ "N=[" $Name$ "]";
  211.     S = S @ "D=[" $JumpTarget.GetPropertyText("Name")$ "]";
  212.  
  213.     return S;
  214. }
  215.  
  216. simulated function vector TraceGround( vector Origin )
  217. {
  218.     local Actor A;
  219.     local vector HL,HN;
  220.    
  221.     A = Trace( HL, HN, Origin+vect(0,0,-32768), Origin, false );
  222.     if( A != None )
  223.     {
  224.         return HL;
  225.     }
  226.        
  227.     ShowMessage( "ERROR: Ground level not found below destination",, true );
  228.     return JumpTarget.Location + vect(0,0,-1)*JumpTarget.CollisionHeight;
  229. }
  230.  
  231. simulated function vector CalcVelocity( Pawn Other )
  232. {
  233.     local vector vel;
  234.     local vector origin;
  235.     local vector targetloc, targetdelta, targetrange;
  236.     local rotator jumpdir, targetdir;
  237.     local float targetdist, targetz;
  238.     local float grav;
  239.     local float angler, angled, pitch, angledmin, minalpha, angledtry;
  240.     local float tanr, sinr, cosr;
  241.     local float speed, speedxy, speedz;
  242.     local float peak;
  243.     local float time;
  244.     local float impactheight, impactspeedz;
  245.     local vector impactspeedxy;
  246.     local ScriptedPawn SP;
  247.     local Bots B;
  248.    
  249.    
  250.     // Player location
  251.     origin = Other.Location + vect(0,0,-1)*Other.CollisionHeight;
  252.    
  253.     // Target Location
  254.     if( bTraceGround )
  255.     {
  256.         targetloc = TraceGround(JumpTarget.Location);
  257.     }
  258.     else
  259.     {
  260.         targetloc = JumpTarget.Location + vect(0,0,-1)*JumpTarget.CollisionHeight;
  261.     }
  262.     targetloc += VRand()*TargetRand;
  263.     targetloc.Z += TargetZOffset;
  264.    
  265.     // Target vars
  266.     targetdelta = targetloc - origin;
  267.     targetrange = targetdelta * vect(1,1,0);
  268.     targetdist = VSize(targetrange);
  269.     targetz = targetdelta.Z;
  270.     targetdir = rotator(targetdelta);
  271.    
  272.     // Get gravity
  273.     grav = -Region.Zone.ZoneGravity.Z;
  274.    
  275.     // Get Angle
  276.     //JumpAngle=10;
  277.     angled = FClamp(GetAngle(Other),MinAngle,MaxAngle);
  278.  
  279.     // Check minimum angle
  280.     angledmin = FClamp(int(targetdir.Pitch * URotToDegree)+1,MinAngle,MaxAngle);
  281.     if( angledmin > angled )
  282.     {
  283.         minalpha = (1-(1-(angledmin / MaxAngle))**MinAngleCurve);
  284.         angledtry = FClamp(angledmin+(MaxAngle-angledmin)*MinAngleFinder*minalpha,MinAngle,MaxAngle);
  285.         ShowMessage( "WARNING: Minimum theoretical jump angle is" @int(angledmin)$ ". JumpAngle=" $int(angled)$ ". Trying angle=" $int(angledtry), Other, true );
  286.         angled = angledtry;
  287.     }
  288.  
  289.     // Convert angle
  290.     angler = angled * DegreeToRadian; // radians
  291.     pitch = angled * DegreeToURot; // ru
  292.    
  293.     // Target direction
  294.     jumpdir = targetdir;
  295.     jumpdir.Pitch = pitch;
  296.    
  297.     // Speed
  298.     tanr = tan(angler);
  299.     speed = targetdist * Sqrt( (grav*((tanr*tanr) + 1)) / (2*(targetdist*tanr-targetz)) );
  300.     if( speed == 0 )
  301.     {
  302.         ShowMessage( "ERROR: Could not calculate JumpSpeed", Other, true );
  303.         speed = Other.JumpZ;
  304.     }
  305.    
  306.     // Velocity
  307.     vel = speed * vector(jumpdir);
  308.  
  309.     // Velocity components
  310.     speedxy = VSize(vel*vect(1,1,0));
  311.     speedz = vel.Z;
  312.        
  313.     // Flight time
  314.     time = (speedz / grav) + sqrt((speedz*speedz)/(grav*grav)-(2*targetz)/grav);
  315.        
  316.    
  317.     if( bLogParams )
  318.     {
  319.         sinr = sin(angler);
  320.         cosr = cos(angler);
  321.        
  322.         peak = ( (speed*speed*sinr*sinr) / (2*grav));
  323.        
  324.         impactheight = peak - targetz;
  325.         impactspeedxy = Normal(targetrange) * speedxy;
  326.         impactspeedz = ( speedz ) - ( grav * time );
  327.        
  328.         ShowMessage(
  329.          "A=" $int(angled)
  330.         @"IV=" $int(impactspeedz)
  331.         @"IS=" $int(VSize(impactspeedxy))
  332.         @"IH=" $int(impactheight)
  333.         @"T=" $int(time*1000)
  334.         @"P=" $int(peak)
  335.         @"V=" $int(speed)
  336.         @"G=" $int(grav)
  337.         , Other, true );
  338.     }
  339.  
  340.     // AI hints
  341.     SP = ScriptedPawn(Other);
  342.     if( SP != None )
  343.     {
  344.         SP.Focus = JumpTarget.Location;
  345.         SP.MoveTarget = JumpTarget;
  346.         SP.MoveTimer = time-0.1;
  347.         SP.Destination = JumpTarget.Location;
  348.     }
  349.     B = Bots(Other);
  350.     if( B != None )
  351.     {
  352.         B.Focus = JumpTarget.Location;
  353.         B.MoveTarget = JumpTarget;
  354.         B.MoveTimer = time-0.1;
  355.         B.Destination = JumpTarget.Location;
  356.     }
  357.     // Update player's physics
  358.     if( Other.Physics == PHYS_Walking )
  359.     {
  360.         Other.SetPhysics(PHYS_Falling);
  361.     }        
  362.     Other.Velocity = vel;    
  363.     Other.Acceleration = vect(0,0,0);  
  364.    
  365.     // AI hints
  366.     if( SP != None )
  367.     {
  368.         SP.bJumpOffPawn = true;
  369.         SP.SetFall();
  370.         SP.DesiredRotation = rotator(targetrange);
  371.     }        
  372.     if( B != None )
  373.     {
  374.         B.bJumpOffPawn = true;
  375.         B.SetFall();
  376.         B.DesiredRotation = rotator(targetrange);
  377.     }    
  378.     return vel;
  379. }
  380.  
  381. simulated event Touch( Actor Other )
  382. {
  383.     // Accept only pawns
  384.     if( !bEnabled || Pawn(Other) == None || Other.Physics == PHYS_None  )
  385.         return;
  386.  
  387.     // Setup PostTouch
  388.     //PendingTouch = Other.PendingTouch;
  389.     //Other.PendingTouch = self;
  390.     Pending=Pawn(Other);
  391.     SetTimer(0.01, false);
  392. }
  393. simulated function Timer()
  394. {
  395.     PostTouch(Pending);
  396. }
  397. simulated function PostTouch( Actor Other )
  398. {
  399.     local Pawn P;
  400.     local Actor A;
  401.  
  402.     // Accept only pawns
  403.     P = Pawn(Other);
  404.     if( !bEnabled || P == None || P.Physics == PHYS_None )
  405.         return;
  406.  
  407.     if( Role == ROLE_Authority )
  408.     {
  409.         // Find JumpTarget
  410.         foreach AllActors( class 'Actor', A )
  411.             if( string(A.tag) ~= URL && A != Self )
  412.                 JumpTarget = A;
  413.                
  414.         if( JumpTarget == None )
  415.         {
  416.             if( URL != "" )
  417.                 ShowMessage( "ERROR: Could not find destination", Other, true );
  418.             return;
  419.         }          
  420.            
  421.         // If team only, enforce it
  422.         if( bTeamOnly && P.PlayerReplicationInfo.Team != TeamNumber )
  423.             return;
  424.        
  425.         // Do not launch again a launched player.
  426.         if( Other != JumpActor || Level.TimeSeconds-JumpWait > default.JumpWait )
  427.         {
  428.             JumpActor = Other;
  429.             JumpWait = Level.TimeSeconds;  
  430.         }
  431.         else return;  
  432.        
  433.         // Launch player
  434.         CalcVelocity( P );
  435.                
  436.         // Broadcast event
  437.         Instigator = P;
  438.         if( JumpEvent != '' )
  439.             foreach AllActors( class'Actor', A, JumpEvent )
  440.                 A.Trigger( self, Instigator );
  441.            
  442.         // Play Sounds
  443.         JumpSounds(P);
  444.     }
  445.    
  446.     // Show effects
  447.     JumpEffects(P);
  448. }
  449.  
  450. simulated function JumpEffects( Pawn Other )
  451. {
  452.     if((bClientSideEffects && Level.NetMode != NM_DedicatedServer)
  453.     ||(!bClientSideEffects && Role == ROLE_Authority))
  454.     {
  455.         // Spawn JumpPad effect
  456.         if( JumpEffect != None )
  457.             Spawn( JumpEffect, self,, Location, rotator(Other.Velocity) );  
  458.            
  459.         // Spawn Player effect
  460.         if( JumpPlayerEffect != None )
  461.             Spawn( JumpPlayerEffect, Other,, Other.Location, rotator(Other.Velocity) );
  462.     }
  463. }
  464.  
  465. function JumpSounds( Pawn Other )
  466. {
  467.     // Make noise
  468.     if( JumpSound != None )
  469.     {
  470.         PlaySound(JumpSound);    
  471.         MakeNoise(1.0);
  472.     }
  473. }
  474.  
  475. /* SpecialHandling is called by the navigation code when the next path has been found.  
  476. It gives that path an opportunity to modify the result based on any special considerations
  477. */
  478.  
  479. function Actor SpecialHandling( Pawn Other )
  480. {
  481.     //ShowMessage( "FOUND!",, true );
  482.     return self;
  483. }
  484.  
  485.    
  486. // ============================================================================
  487. //  Copyright 2005 Roman Switch` Dzieciol, neai o2.pl
  488. //  http://wiki.beyondunreal.com/wiki/Switch
  489. // ============================================================================
  490. defaultproperties
  491. {
  492.     JumpAngle=45.00
  493.     bTraceGround=True
  494.     JumpEvent=JumpPad
  495.     JumpSound=Sound'UnrealI.Pickups.BootJmp'
  496.     JumpWait=1.00
  497.     MinAngleCurve=3.00
  498.     MinAngleFinder=0.75
  499.     MinAngle=1.00
  500.     MaxAngle=89.00
  501.     ExtraCost=400
  502.     bStatic=False
  503.     bDirectional=False
  504.     CollisionRadius=64.00
  505.     CollisionHeight=24.00
  506. }
Add Comment
Please, Sign In to add comment