Įƒ*žE˜@@ŒW@zUģó{šg߇œ#+;‘@˜NoneWallJumpBootsClientMessageConsoleCommandCoreEngineFlipDodgeRDodgeLDodgeBkxWallJump03 kxWallJumpInitializeKeysFindClosestWallSetFinalMeshClientPlayAnim ROLLRIGHT ROLLLEFTMesh PlayerPawnPreBeginPlayCollisionHeight SpectatorGiveToMutateMaxDesireabilityPickupMessageModifyPlayer RespawnTime AmbientGlowDoJumpIcon ItemNamebAutoActivatebActivatablebDisplayableInvPickupViewMesh PickupSoundActivateSoundBotExpireMessageBotpackRechargeRate WallJumpUT MaxJumps JumpHeightVelocityLimit JumpStyle MaxWallDistNormalBouncebKillInwardVelocity nofJumps WallJumpByteProperty IntPropertyBoolPropertyFloatPropertyObjectPropertyNamePropertyClassPropertyStructProperty StrPropertyUnrealIStructVectorRotator FunctionObject TextBufferHitWallPackageClassRoleTextureSoundPlayerLodMeshPawnActorLevel Viewport InventoryPlayerReplicationInfo ZoneInfo GameInfo LevelInfoMutatorRight ReturnValueYaw ScriptTextiKeyNameYZXAPhysicsJumpZ Location PointRegion ZoneGravity DifficultyOther TweenTime SequenceP HitLocation HitNormalRateMutateString VelocityHasFlagbAdmin JumpSoundGameRegionZone WallNormalOwner TimeSeconds DodgeDirNetMode RotationSender DirectionIconsAnglePickupsI_BootsBootSndNewMeshTournamentPickupjbootInventoryClass JumpType bRestrictFC nofJumpKeysLastJumpTime keyBindingDeltaVBestHitLocationBestHitNormalClosestSoFarBestA forwardness rightnessDJ_InvMyMutateStringtempMaxJumpstempJumpTypetempJumpHeight&ƒÆ5>$=š:©,–:©,€’’’’’’’’’’6Nę8mÆXu6脜ŌXƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Y“1ŚČ“1ŚČˆŽ”“1ŚČ“1ŚČƒ> £Yƒ> £Yƒ> £Yƒ> £YˆŽ”ƒ> £Y˜{#Uæƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £YˆŽ”ƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £YˆŽ”ˆŽ”™©Ł«ƒ> £YˆŽ”™©Ł«ƒ> £Yƒ> £YˆŽ”ƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £YˆŽ”ƒ> £Y )… ,"-$ĶĢŒ?.$ÜB/"0$€B1$ū–!?2Ó*$ @3"(]WallJumping is over!Ó"Ó#Ó]! You picked up the WallJumpBoots ]WallJumpBoots$šA$±$?%²&²Ą±$`A$@ €ƒ"@€ƒ@4€‰ €ƒ€†!@ƒ††'†*@@/€ƒ††+@„§)@-@.„ „€@#@,@%@@†0€†<€†2€3ŽQ™ /* WARNING! This file was auto-generated by jpp. You probably want to be editing ./WallJumpBoots.uc.jpp instead. */ //================================================================================ // WallJumpBoots. //================================================================================ // vim: ft=uc // TODO: If we have normal jump boots, our in-air doublejumps also jump with their strength. I think this is wrong - we should ideally prevent the jump boots from being used in-air, but keep their charge. // TODO: Refuse doublejump during dodge (could make it an admin option). // DONE: I think we can remove GRAPPLEGUN_JUMPOFF_FIX. The grapple jump-off is unreliable with or without DJBoots. I doubt DJBoots are intercepting the jump call, since they work by adding a keybind! // #define GRAPPLEGUN_JUMPOFF_FIX class WallJumpBoots extends TournamentPickup config(kxWallJump); var() config int MaxJumps; var() config float JumpHeight; var() config float VelocityLimit; // Defines the size of the apex var() config int JumpType; // This is the restriction on jumping var() config int JumpStyle; // This is the type of jump that the player performs var() config float MaxWallDist; var() config float NormalBounce; var() config bool bKillInwardVelocity; var() config float RechargeRate; // This allows your boots to recharge slowly without walking if you don't use them for some time, for example, when using the grappling hook. var() config bool bRestrictFC; var int nofJumps; var int nofJumpKeys; var float LastJumpTime; replication { reliable if ( Role == 4 ) ClientPlayAnim; reliable if ( Role < 4 ) WallJump; } simulated function PreBeginPlay () { local PlayerPawn P; if ( Level.NetMode == 1 ) { return; } foreach AllActors(Class'PlayerPawn',P) { if ( Viewport(P.Player) != None ) { break; } else { P = None; } } if ( P == None ) { Log("kxWallJump03.WallJumpBoots.PreBeginPlay() NO LOCAL PLAYERPAWN !!!"); return; } InitializeKeys(P); if ( nofJumpKeys == 0 ) { Log("kxWallJump03.WallJumpBoots.PreBeginPlay() Could NOT find any keys bound to JUMP/DOUBLEJUMP, WallJump will NOT work !!!"); } else { } } simulated function InitializeKeys (PlayerPawn P) { local string KeyName; local string keyBinding; local int i; nofJumpKeys = 0; for (i=0;i<256;i++) { // TODO: This looks ballbag - check and test. Why aren' we using GET INPUT? Match on Jump single-word. KeyName = P.ConsoleCommand("Keyname" @ string(i)); if ( (InStr(P.ConsoleCommand("Keybinding" @ KeyName),"Jump") != -1) && (InStr(P.ConsoleCommand("Keybinding" @ KeyName),"WallJump") == -1) ) { keyBinding = P.ConsoleCommand("Keybinding" @ KeyName); P.ConsoleCommand("SET INPUT " @ KeyName @ " WallJump|" $ keyBinding); Log("kxWallJump03.WallJumpBoots.InitializeKeys() Changed" @ KeyName @ "from" @ keyBinding @ "to WallJump|" $ keyBinding); nofJumpKeys++; } else { if ( InStr(P.ConsoleCommand("Keybinding" @ KeyName),"WallJump") != -1 ) { nofJumpKeys++; } } } } exec function WallJump () { local PlayerPawn P; local Actor HitWall; local vector HitLocation,WallNormal,DeltaV; if ( PlayerPawn(Owner) == None ) { return; } P = PlayerPawn(Owner); if (RechargeRate>0 && (Level.TimeSeconds-LastJumpTime)>=RechargeRate && nofJumps>1) { nofJumps = 1; } if (bRestrictFC && P.PlayerReplicationInfo.HasFlag != None && nofJumps VelocityLimit) { // Not at apex return; } break; case 1: // Only allow jump when going upwards, or at the apex (not falling too fast) if (P.Velocity.Z < -VelocityLimit) { // Falling fast return; } break; default: } // Repeated jump after dodge takes player too far! (Certainly if velocity is additional.) if (p.DodgeDir == DODGE_Active) { // p.ClientMessage("Disallowed WallJump because you are mid-dodge."); return; } HitWall = FindClosestWall(p,HitLocation,WallNormal); if (HitWall == None) { p.ClientMessage("You need to be near a wall to wall-jump!"); return; } // OK we will do a jump nofJumps++; LastJumpTime = Level.TimeSeconds; DeltaV = P.JumpZ * JumpHeight * NormalBounce * WallNormal; switch (JumpStyle) { case 0: // Set standard upward velocity P.Velocity.Z = P.JumpZ * JumpHeight; break; case 1: // Moderated additional //// If we are already goin up fast, give us only half a jump extra P.Velocity.Z = P.Velocity.Z + 0.5 * P.JumpZ * JumpHeight; //// If we are not going up at jump speed, make us go up at jump speed! if (P.Velocity.Z < P.JumpZ * JumpHeight) { P.Velocity.Z = P.JumpZ * JumpHeight; } break; case 2: //// Add extra jump to current upward velocity. This can take you very high if tapped quickly, so for this JumpStyle, JumpType=on-apex is recommended. P.Velocity.Z += P.JumpZ * JumpHeight; break; case 3: //// Let the player choose whether to go for height or distance on the secondary jumps: //// Add extra jump to current velocity (half up, half "with" our sideways velocity) P.Velocity.Z += P.JumpZ * JumpHeight * 0.5; P.Velocity = Normal(P.Velocity) * (VSize(P.Velocity) + P.JumpZ * JumpHeight * 0.5); break; case 4: // "Fixed" / "sticky" / "standard" // Always standard (TODO: should only be applied if greater than existing Z or horizontal velocity): P.Velocity.X = 0; P.Velocity.Y = 0; P.Velocity.Z = P.JumpZ * JumpHeight; break; default: P.Velocity.Z = P.JumpZ * JumpHeight; break; } // We do this before any adjustments to DeltaV SetFinalMesh(P,DeltaV); // P.Velocity.Z = P.JumpZ * JumpHeight; // P.Velocity.X = 0; // P.Velocity.Y = 0; // IMO we should cancel the component of velocity parallel to the normal. // Or, "kill inward velocity" // Kill any inward velocity if (bKillInwardVelocity) { if (P.Velocity Dot -WallNormal > 0) { DeltaV = DeltaV + WallNormal * (P.Velocity Dot -WallNormal); } } P.Velocity = P.Velocity + DeltaV; P.PlaySound(P.JumpSound,SLOT_Interface,1.5,True,1200.0,1.0); if ( (Level.Game != None) && (Level.Game.Difficulty > 0) ) { P.MakeNoise(0.1 * Level.Game.Difficulty); } } } else if (p.Physics == PHYS_Walking) { // Do a normal jump off the ground: P.DoJump(); nofJumps = 1; LastJumpTime = Level.TimeSeconds; } } function Actor FindClosestWall(PlayerPawn P, out vector BestHitLocation, out vector BestHitNormal) { local float ClosestSoFar,angle; local Actor BestA,A; local vector HitLocation,HitNormal; local vector Direction; ClosestSoFar = 1000000.00; // #define distance VSize(P.Location - HitLocation) //// But actually the closest distance to this polygon is: //// assuming that the polygon does actually reach this far. for (angle=0;angle<2.0*PI;angle+=PI/8.0) { // Direction = vect( MaxWallDist*sin(angle), MaxWallDist*cos(angle), 0.0 ); // Direction = vector( rotator(angle,0,0) ); Direction.X = MaxWallDist*1.5*sin(angle); Direction.Y = MaxWallDist*1.5*cos(angle); Direction.Z = 0; A = Trace(HitLocation,HitNormal,P.Location+Direction,P.Location,false); // Do not allow WallJump off essentially flat surfaces (the jump they produce is unrealistically high) if (HitNormal.Z > 0.8) continue; if (A!=None && ((P.Location - HitLocation) Dot HitNormal) < ClosestSoFar) { BestHitLocation = HitLocation; BestHitNormal = HitNormal; BestA = A; ClosestSoFar = ((P.Location - HitLocation) Dot HitNormal); } } if (ClosestSoFar <= MaxWallDist) return BestA; else return None; } simulated function SetFinalMesh(PlayerPawn P, Vector DeltaV) { local name newMesh; local float forwardness,rightness; local Rotator right; newMesh = ''; forwardness = Normal(DeltaV) Dot Normal(Vector(P.Rotation)); right = P.Rotation; right.Yaw += 16384; rightness = Normal(DeltaV) Dot Normal(Vector(right)); // if ( sqrt(forwardness*forwardness+rightness*rightness)<0.2 && P.HasAnim('Flip')) { // newMesh = 'Flip'; if ( sqrt(DeltaV.X*DeltaV.X+DeltaV.Y*DeltaV.Y)<4.0) { // && P.HasAnim('Flip')) { //// Do not change mesh. // newMesh = 'Flip'; // TODO: should really *set* them on flat jump anim, since they may have started jumping sideways but then flattened to straight upward velocity. } else if ( rightness > Abs(forwardness) && P.HasAnim('ROLLRIGHT') ) { newMesh = 'ROLLRIGHT'; } else if ( rightness > Abs(forwardness) && P.HasAnim('DodgeL') ) { newMesh = 'DodgeL'; } else if ( rightness < (-Abs(forwardness)) && P.HasAnim('ROLLLEFT') ) { newMesh = 'ROLLLEFT'; } else if ( rightness < (-Abs(forwardness)) && P.HasAnim('DodgeR') ) { newMesh = 'DodgeR'; } else if ( forwardness < (-Abs(rightness)) && P.HasAnim('DodgeB') ) { newMesh = 'DodgeB'; } else if ( P.HasAnim('Flip') ) { // forwardness>Abs(rightness) newMesh = 'Flip'; } if (newMesh != '' && P.HasAnim(newMesh)) { P.PlayAnim(newMesh,1.352 * FMax(0.34999999,Region.Zone.ZoneGravity.Z / Region.Zone.Default.ZoneGravity.Z),0.06); if ( Level.NetMode != 0 ) { ClientPlayAnim(newMesh,1.352 * FMax(0.34999999,Region.Zone.ZoneGravity.Z / Region.Zone.Default.ZoneGravity.Z),0.06); } } } simulated function ClientPlayAnim (name Sequence, optional float Rate, optional float TweenTime) { Owner.PlayAnim(Sequence,Rate,TweenTime); } ”7@+’’’’’’’’’’’’’’’’’’ 6ć靔=$:eƒ> £Y˜{#U戎”Žę8mƒ> £YŽę8mƒ> £YŽę8mƒ> £YŽę8mƒ> £YŽę8mƒ> £Yƒ> £YŽę8mƒ> £YŽę8m‰žtȉžtȉžtȉžtČę8mę8m … EH//================================================================================ // WallJumpUT. //================================================================================ class WallJumpUT extends Mutator config (kxWallJump); // var config bool bRestrictFC; // var config int MaxJumps; // var config int JumpType; // var config float JumpHeight; // var config float RechargeRate; function ModifyPlayer (Pawn Other) { local Class InventoryClass; local WallJumpBoots DJ_Inv; Super.ModifyPlayer(Other); // 0x00000014 : 0x0000 if ( Other.IsA('Spectator') || (!Other.IsA('PlayerPawn') && !Other.IsA('Bot')) ) // 0x00000019 : 0x000B { return; // 0x0000003A : 0x0037 } // InventoryClass = Class(DynamicLoadObject("kxWallJump03.WallJumpBoots",Class'Class')); // 0x0000003C : 0x0039 // InventoryClass = Class(DynamicLoadObject(String(class'WallJumpBoots'),Class'Class')); // 0x0000003C : 0x0039 InventoryClass = class'WallJumpBoots'; DJ_Inv = Spawn(Class'WallJumpBoots',Other,,Other.Location); // 0x00000066 : 0x006E if ( DJ_Inv != None ) { DJ_Inv.RespawnTime = 0.0; // 0x00000082 : 0x009B DJ_Inv.GiveTo(Other); // 0x00000091 : 0x00AF // DJ_Inv.MaxJumps = MaxJumps; // 0x0000009C : 0x00C3 // DJ_Inv.JumpType = JumpType; // 0x000000A7 : 0x00D7 // DJ_Inv.JumpHeight = JumpHeight; // 0x000000B2 : 0x00EB // DJ_Inv.RechargeRate = RechargeRate; // 0x000000B2 : 0x00EB // TODO parts missing! } } function Mutate (string MutateString, PlayerPawn Sender) { local string MyMutateString; local int tempMaxJumps; local int tempJumpType; local float tempJumpHeight; // TODO: SaveConfig()? Nah, for that let admin do "admin set" :P if ( Sender.PlayerReplicationInfo.bAdmin || (Level.NetMode == 0) ) // 0x00000014 : 0x0000 { MyMutateString = MutateString; // 0x0000003B : 0x0034 if ( Left(MyMutateString,12) ~= "WallJumpUT" ) // 0x00000040 : 0x003F { MyMutateString = Mid(MyMutateString,13); // 0x00000059 : 0x005B if ( Left(MyMutateString,8) ~= "MaxJumps" ) // 0x00000062 : 0x006A { tempMaxJumps = int(Mid(MyMutateString,9)); // 0x00000077 : 0x0082 if ( tempMaxJumps != 0 ) // 0x00000081 : 0x0092 { class'WallJumpBoots'.default.MaxJumps = tempMaxJumps; // 0x00000089 : 0x009D Sender.ClientMessage("Maximum number of jumps is now: " $ string(class'WallJumpBoots'.default.MaxJumps)); // 0x0000008E : 0x00A8 } else { // 0x000000BA : 0x00DD Sender.ClientMessage("MaxJumps should be 1 or higher."); // 0x000000BD : 0x00E0 } } else { // 0x000000E3 : 0x010C if ( Left(MyMutateString,8) ~= "JumpType" ) // 0x000000E6 : 0x010F { tempJumpType = int(Mid(MyMutateString,9)); // 0x000000FB : 0x0127 switch (tempJumpType) // 0x00000105 : 0x0137 { case 0: // 0x00000109 : 0x013E class'WallJumpBoots'.default.JumpType = 0; // 0x0000010D : 0x0142 Sender.ClientMessage("Jumptype is now \"At apex\""); // 0x00000111 : 0x0149 break; // 0x00000131 : 0x016F case 1: // 0x00000134 : 0x0172 class'WallJumpBoots'.default.JumpType = 1; // 0x00000138 : 0x0176 Sender.ClientMessage("Jumptype is now \"Going up and apex\""); // 0x0000013C : 0x017D break; // 0x00000166 : 0x01AD case 2: // 0x00000169 : 0x01B0 class'WallJumpBoots'.default.JumpType = 2; // 0x0000016E : 0x01B5 Sender.ClientMessage("Jumptype is now \"Always\""); // 0x00000173 : 0x01BD break; // 0x00000192 : 0x01E2 default: // 0x00000195 : 0x01E5 Sender.ClientMessage("Jumptype should be 0, 1 or 2."); // 0x00000198 : 0x01E8 break; // 0x000001BC : 0x0212 } } else { // 0x000001BF : 0x0215 if ( Left(MyMutateString,10) ~= "JumpHeight" ) // 0x000001C2 : 0x0218 { tempJumpHeight = float(Mid(MyMutateString,11)); // 0x000001D9 : 0x0232 if ( tempJumpHeight >= 100 ) // 0x000001E4 : 0x0242 { class'WallJumpBoots'.default.JumpHeight = tempJumpHeight / 100; // 0x000001EF : 0x024F Sender.ClientMessage("JumpHeight is now "$ class'WallJumpBoots'.default.JumpHeight); // 0x00000198 : 0x01E8 // TODO // File ended here! } } } } } } Super.Mutate(MutateString,Sender); } ¹/Ū6š:¢& /a0 ƒNFw.“·*NM*10”r*ēkxWallJump03.WallJumpBoots.PreBeginPlay() NO LOCAL PLAYERPAWN !!!  4š%ēkxWallJump03.WallJumpBoots.PreBeginPlay() Could NOT find any keys bound to JUMP/DOUBLEJUMP, WallJump will NOT work !!!4 8 M? Ź%%Č–  ØKeynameS‚›~ ØKeybinding Jump’’’’6š~ ØKeybinding WallJump’’’’ ØKeybinding  .pØØSET INPUT  WallJump|ēpØØØØkxWallJump03.WallJumpBoots.InitializeKeys() Changed fromto WallJump|„¾¾›~ ØKeybinding WallJump’’’’„„ 94eµ dr.ƒ”* .ƒ”c‚‚±%?%³Æ£% —&&Ŗ‚‚--wؽ*–“&!š:«:$– ’%ü±ŗ6Š ‡$ * '&$°6Š ‡©$ * ’’Cš:ø:$ &.¤r&*0You need to be near a wall to wall-jump! „£Õ««+* %6Š ‡« Į&6Š ‡®6Š ‡««?¾°6Š ‡«6Š ‡« ó,ø6Š ‡« {,ø6Š ‡««? ‡Ōā ‡®į ‡««? Ž,6› ‡6š ‡6Š ‡« ’’6Š ‡«o-,o±Ū ‡Ó?%×ŌŪ ‡Ó ‡× ‡#a¼$Ą?'–D€?‚w *—: ¬%"b«ĶĢĢ=< ¬bbš:«:$&£ Ā :Ļnr$tIV°«@ŪI@6›««Ą?»6š««Ą?¼6Š a× – –(Ź±6ŠĶĢL?@@‚w *$°ŪŲ –/0' ŪŲ –ø¬ŪI@An²'p* €„;ķü“!Ūā ā9 Ŗ! Ŗ”6¶!@Ūā ā9!¤°Į®«6› 6› «6š 6š €@ŅŁ‚±ŗa!!Ņ‚±ŗa!!ŅE‚°©ŗa!!Ņ|‚°©ŗa!!Ņ³‚°©ŗa! ! ŅŅa!!²‚’!aMa«V­?õ33³>¬6Š6ž Ÿ6Š6ž ŸĀu=²›:¢%«V­?õ33³>¬6Š6ž Ÿ6Š6ž ŸĀu= =1#&”a123 Ā­  ³­ Q„ a/!,‚ a/! a/!' 4 a    –±w*ŗ   ®?(/śļŻ„Ø-»š:¢%(Ż|€, WallJumpUT,%|€,MaxJumps"J, ņ›"% "9pMaximum number of jumps is now: S "'MaxJumps should be 1 or higher.ŻY|€,JumpType)J, ) •% %!Jumptype is now "At apex"V ą& &+Jumptype is now "Going up and apex"V ", , Jumptype is now "Always"V ’’%Jumptype should be 0, 1 or 2.VŻŻ|€, JumpHeight#L, Ż³#?,d ¬#?,d+pJumpHeight is now U ®( FFG’’’’G’’’’NGž’’’C?ū’’’@<ü’’’oG’’’’UG’’’’M8ś’’’^Gž’’’8Gž’’’9Gž’’’<Gž’’’G8÷’’’b9ü’’’OGž’’’6Gž’’’BG’’’’SG’’’’VF)<ü’’’cGž’’’=G’’’’RG’’’’T8ś’’’]8ś’’’_?ü’’’d9ä’’’u<ü’’’t<ķ’’’e9ų’’’s9ü’’’w5ų’’’z8ų’’’xGž’’’:Gž’’’7Gž’’’D?ū’’’A9÷’’’R5ü’’’H<ü’’’{5ü’’’a5ē’’’fBģ’’’Bģ’’’Gė’’’DFė’’’@Lė’’’EJŠ’’’BGž’’’;G’’’’PG’’’’Q6Ł’’’Y9ż’’’K5ü’’’yBü’’’8Ė’’’7č’’’q9ż’’’r9č’’’pF>FĀ’’’~IĮ’’’AŒ:jN$Æ@[$‹- [3¤=C g3Œ=js3—@T @4Œ@|L4‘3 Y4—9\ e4Œ?gq4Œ9j~4=LK5‹=Q X5‹=R d5‘, p5Œ8j|5:vI6:LV6‹; c6;lo6‘G |6‘I H7—9K T7‘9[ `7Œ;jl7‹;O y7;kE8;}R8Œ?S_8‹0 l8‹J x8Œ;`D9=WQ9‘@U ^9‹@W j9‹. v9‹* B:Œ:EN:Œ;P[:—@n h:‘@V t:‘/ @;‹1 L;„2 X;„H d;:kp;;M};;NJ<¤>i W<‹>m c<‹>h o<³?F{<¦Z4]™I=”+dfÖ¦6Z4PHJÜ’¹kZ¤’ IE©’4eNÆ’Gs½Œ;XzĮ’WGĀ’,^É’­6MJŹ’®6c WĢ