Įƒ*žE•@>sQ?kOœ:p§a߇œ#+;‘>•NoneWallJumpBootsClientMessageConsoleCommandCoreEngineFlipDodgeRDodgeLDodgeBkxWallJump01 kxWallJumpInitializeKeysFindClosestWallSetFinalMeshClientPlayAnim ROLLRIGHT ROLLLEFTMesh PlayerPawnPreBeginPlayCollisionHeight SpectatorGiveToMutateMaxDesireabilityPickupMessageModifyPlayer RespawnTime AmbientGlowDoJumpIcon ItemNamebAutoActivatebActivatablebDisplayableInvPickupViewMesh PickupSoundActivateSoundBotExpireMessageBotpackRechargeRate WallJumpUTWallProximity MaxJumps JumpHeightVelocityLimit JumpStyle nofJumps WallJumpByteProperty IntPropertyBoolPropertyFloatPropertyObjectPropertyNamePropertyClassPropertyStructProperty StrPropertyUnrealIStructVectorRotator FunctionObject TextBufferHitWallPackageClassRoleTextureSoundPlayerLodMeshPawnActorLevel Viewport InventoryPlayerReplicationInfo ZoneInfo GameInfo LevelInfoMutatorRight ReturnValueYaw ScriptTextiKeyNameYZXAPhysicsJumpZ Location PointRegion ZoneGravity DifficultyOther TweenTime SequenceP HitLocation HitNormalRateMutateString VelocityHasFlagbAdmin JumpSoundGameRegionZone WallNormalOwner TimeSecondsNetMode RotationSender DirectionIconsAnglePickupsI_BootsBootSndNewMeshTournamentPickupjbootInventoryClass JumpType bRestrictFC nofJumpKeysLastJumpTime keyBindingDeltaVBestHitLocationBestHitNormalClosestSoFarBestA forwardness rightnessDJ_InvMyMutateStringtempMaxJumpstempJumpTypetempJumpHeight"ƒ®2<'š:Ø,–:Ø,€’’’’’’’’’’6Fs³ć“®Xu6č„œŌXƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Yƒ> £Y“1ŚČ“1ŚČ‡Ž”“1ŚČ“1ŚČƒ> £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 )… ,$C-".$š™™?/$šB0"*$ @1"(]WallJumping is over!Ó"Ó#Ó]! You picked up the WallJumpBoots ]WallJumpBoots$šA$°$?%±&±æ°$`A @ €ƒ@€ƒ@1€ˆ €ƒ€†@ƒ%)@@††,€ƒ„&†¦(@*@+„†„†€@!@@#†-€†:€†/€0Žc† /* 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 float WallProximity; 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 RechargeRate; var() config bool bRestrictFC; var int nofJumps; var int nofJumpKeys; var float LastJumpTime; // 220 toolow, try 360, 520 works mostly. 640 worked // #define MaxWallDist 25.0 // almost touching // #define MaxWallDist 50.0 // reasonable distance 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("kxWallJump01.WallJumpBoots.PreBeginPlay() NO LOCAL PLAYERPAWN !!!"); return; } InitializeKeys(P); if ( nofJumpKeys == 0 ) { Log("kxWallJump01.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("kxWallJump01.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: } // 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; 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 in this case 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; default: P.Velocity.Z = P.JumpZ * JumpHeight; break; } // P.Velocity.Z = P.JumpZ * JumpHeight; // P.Velocity.X = 0; // P.Velocity.Y = 0; DeltaV = P.JumpZ * JumpHeight * 0.4 * 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); } // if ( nofJumps == MaxJumps ) { SetFinalMesh(P,DeltaV); // } } } 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; 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 = 64.0*sin(angle); Direction.Y = 64.0*cos(angle); Direction.Z = 0; A = Trace(HitLocation,HitNormal,P.Location+Direction,P.Location,false); if (A!=None && VSize(HitLocation-P.Location) < ClosestSoFar) { BestHitLocation = HitLocation; BestHitNormal = HitNormal; BestA = A; } } return BestA; } 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); } ”4>+’’’’’’’’’’’’’’’’’’ 31]ī”=$:eƒ> £Y—{#U懎”Žs³ć“ƒ> £YŽs³ć“ƒ> £YŽs³ć“ƒ> £YŽs³ć“ƒ> £YŽs³ć“ƒ> £Yƒ> £YŽs³ć“ƒ> £YŽs³ć“ˆžtČˆžtČˆžtČˆžtČs³ć“s³ć“ … 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("kxWallJump01.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); } @ø52¤6š:¢& /a0 ƒNFw.“·*NM*10”r*ēkxWallJump01.WallJumpBoots.PreBeginPlay() NO LOCAL PLAYERPAWN !!!  4š%ēkxWallJump01.WallJumpBoots.PreBeginPlay() Could NOT find any keys bound to JUMP/DOUBLEJUMP, WallJump will NOT work !!!4 6 P Ź%%Č–  ØKeynameS‚›~ ØKeybinding Jump’’’’6š~ ØKeybinding WallJump’’’’ ØKeybinding  .pØØSET INPUT  WallJump|ēpØØØØkxWallJump01.WallJumpBoots.InitializeKeys() Changed fromto WallJump|„¾¾›~ ØKeybinding WallJump’’’’„„ 72h~ –r.ƒ”* .ƒ”c‚‚±!?%³Æ£! —&&Ŗ‚‚-*w§¼*–“&Sš:Ŗ:$P– ’%ü±ŗ6‰ Š  * '&$°6‰ Š©  * ’’"+#‹r"*0You need to be near a wall to wall-jump! „£) Ż%6‰ Š«h &6‰ Š®6‰ Š««?|°6‰ Š«6‰ Š«h ±,ø6‰ Š«h 9,ø6‰ Š««? ŠŌā Š®į Š««?h ’’6‰ Š«hÕ««ĶĢĢ># Š× Š#a»$Ą?'–D€?@‚w *—: «%"b«ĶĢĢ=< «””š:Ŗ:$&£ Ā 8Ä”$$tI °«@ŪI@6Ÿ«€B»6ž«€B¼6‰a&× ™ ™(ō‚w*°įŲ ™$,-&%ø¬ŪI@A% $€„9ŲN“!Ūā ā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= ;.ųu!”a./0 ¬  ³¬ Q„ a/!,‚ a/! a/!' 1 a    ™±w*¹   ­='/śļŻ„§-ŗš:¢%'Ż|€, WallJumpUT,%|€,MaxJumpsJ, ņ›% 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ŻŻ|€, JumpHeightL, ݳ?,d ¬?,d+pJumpHeight is now U ­' DDE’’’’E’’’’LEž’’’A=ū’’’>E’’’’SE’’’’K6ś’’’\:ü’’’mEž’’’7Ež’’’6Ež’’’:Ež’’’E7ü’’’M6ų’’’`Ež’’’4Ež’’’@E’’’’QE’’’’TD)Ež’’’;E’’’’PE’’’’R:ü’’’a=ü’’’b7ę’’’s:ü’’’r:ķ’’’c6ś’’’[6ś’’’]7ł’’’q7ü’’’u3ł’’’w6ł’’’vEž’’’8Ež’’’B=ū’’’?7ų’’’P3ü’’’F:ü’’’x3ü’’’_3č’’’d@ģ’’’@ģ’’’Eė’’’ADė’’’}Jė’’’BHŃ’’’Ež’’’9Ež’’’5E’’’’NE’’’’O4Ś’’’W7ż’’’I@ü’’’6Ė’’’5é’’’o7ż’’’p7é’’’nD<DĆ’’’{GĀ’’’~‹8hW#®nd#Œ. R1¤;@ ^1‹;hj1–>Q w1‹>yC2‘1 P2–7Z \2‹=eh2‹7hu2;IB3Œ;N O3Œ;O [3‘- g3‹6hs3Œ9| @4‘D L4‘F X4–7H d4‘7Y p49z|4‹=PI5ŒG V58Ib5‹9ho5‹9^|59iI6;UV6‘>R c6Œ>T o6Œ/ {6Œ* G7‹8CS78t`7Œ9L m7‹9My79jF8–>l S8‘>S _8‘0 k8³E w88iC99JP99K]9¤<g j9Œ<k v9Œ<f B:²=CN:„X4o†\:”+cKĮ„3X4PHnĘŒ, ~Ž’økJ’ Iu“’2b ~™’K`¦‹9Vk©’Wx©’,O±’¬3M{±’­3c H“