Įƒ*žE1@ˆ½źĆFč‚r4B®” ö®X1NoneFallDamageHandlerTriggerbInitiallyActivebCollideActors PostTouchCoreEngineSystemTouchObject FunctionStructPropertyVector TextBufferStructClassObjectPropertyPawnActor Keypoint BoolPropertyFloatProperty ScriptText IntPropertyACollisionHeightPackageJumpZ Location PointRegion ZoneInfo ZoneGravityOtherP TraceStart HitLocation HitNormalEventInstigator VelocityRegionZone PendingTouchZMaxFallDamage MinVelocity DistanceLeft TimeToImpactGravity  „€ƒ†ƒ€ƒ † †€„€ƒ]U//============================================================================= // // Object: FallDamageHandler // Author: Joe 'Ironblayde' Farrell // E-mail: jdfarrell@ironblayde.com // //============================================================================= // This actor "catches" players and either eliminates or reduces the falling // damage they might otherwise incur. It differs from using a Kicker for the // same purpose in two important ways: // // 1. This actor only takes action if the player's velocity along the // z-axis is above a certain threshhold, so it won't activate when you // don't want it to. // // 2. This actor reduces the player's velocity by a certain amount rather // than nullifying it completely, so you can allow players to take a // limited amount of damage if you prefer that to throwing out the // damage entirely. // // To use it, simply place a FallDamageTrigger where you want to catch players // and set its MaxFallDamage property to the maximum fall damage you want a // player to take from landing in the area. The default value of zero will // negate falling damage entirely. Use the trigger's CollisionHeight and // CollisionRadius settings to define the area you want the trigger to affect. // A few notes and cautions: // // 1. Sometimes a player falling onto one of these triggers will take // slightly less damage than the maximum. I'm not sure why this is, but // my guess is that it relates to the fact that the number of times the // game world updates per second is only finite, whereas the math I // used to compute the player's expected impact velocity assumes a // continuously accelerating body. I'm not sure how to fix this, or // even whether people will think it needs fixing. But I'd love to hear // any ideas. // // 2. The actor should be placed close to the ground, since the velocity // correction is done the moment the player touches the trigger. The // closer to the ground this is done, the less likely it is that the // velocity change will be noticeable. Placing the trigger in midair // far above the ground will have strange results. // // 3. Disclaimer: I know a fair amount about programming but very little // about UnrealScript! So there may be mistakes or inefficiencies // lurking within, and if you find any, I'd appreciate it if you'd let // me know. Thanks, and enjoy. //============================================================================= class FallDamageHandler expands Keypoint; var() int MaxFallDamage; // maximum falling damage a player will incur var() bool bInitiallyActive; // is this actor initially active? // -Trigger()- // Toggles the actor's activity state. function Trigger(Actor Other, Pawn EventInstigator) { bInitiallyActive = !bInitiallyActive; } // -Touch()- // Sets up PostTouch(), which does all the work. function Touch(Actor Other) { // Set up touch if the actor is active. if (bInitiallyActive) { PendingTouch = Other.PendingTouch; Other.PendingTouch = self; } } // -PostTouch()- // Handles the messy details of velocity adjustment. simulated function PostTouch(Actor Other) { local Actor A; local Pawn P; local vector HitNormal, HitLocation, TraceStart; local float MinVelocity, DistanceLeft, TimeToImpact, Gravity; // Check whether the touching actor is a pawn. P = Pawn(Other); if (P != None) { // See if the pawn may be about to take falling damage. if (P.Velocity.Z <= -(P.JumpZ + 600)) { // Determine the minimum velocity required to stay within the // desired range of falling damage. MinVelocity = -(P.JumpZ + 700 + MaxFallDamage / 0.15); if (MinVelocity < -(P.JumpZ + 1650)) MinVelocity = -(P.JumpZ + 1650); // Trace to the ground to find out how much farther the player // has to fall. TraceStart = Other.Location; TraceStart.z -= Other.CollisionHeight; A = Other.Trace(HitLocation, HitNormal, Other.Location + vect(0, 0, -65536), TraceStart, false); if (A != None) { DistanceLeft = TraceStart.z - HitLocation.z; // Compute the increase in velocity the player will experience // before impact, assuming zone gravity is the only accelerating // force, and apply this to our value for MinVelocity. Gravity = Region.Zone.ZoneGravity.z; if (Gravity != 0) { TimeToImpact = (-MinVelocity - sqrt(MinVelocity * MinVelocity + 2.0 * Gravity * DistanceLeft)) / -Gravity; MinVelocity -= (Gravity * TimeToImpact); } } // Update player velocity if necessary. if (P.Velocity.Z < MinVelocity) P.Velocity.Z = MinVelocity; } } } // These lines were in the code for testing purposes; I've left them here in case I // need them again in the future, or if people want to display some information for // their own testing. // -------------------------------------------------------------------------------- // BroadcastMessage("MinVelocity = " $ MinVelocity $ " UU"); // BroadcastMessage("Distance remaining to ground = " $ DistanceLeft $ " UU"); // BroadcastMessage("Zone gravity = " $ Gravity $ " UU/s²"); // BroadcastMessage("Time to impact = " $ TimeToImpact $ " s"); // BroadcastMessage("New MinVelocity = " $ MinVelocity $ " UU"); ’’’’’’’’@ ’’’’’’’’’’<ž“hžD„žtČ„žtČ„žtČ„žtČ„žtČƒœŌXƒœŌXƒœŌXƒœŌX1ŚČ„žtČ„žtČƒœŌXƒœŌX…ÓӜRŪ ü.„św*ś²6‡ Ž©®Š?X©®®Š?¼¬? š™>ø°©®Š?r©®Š?r ‘¹6‡–0a × ‘#€Ē(Äw* Æ6‡6‡ 6‡6•’ ›Äµ?% ¬Æ©Į®«««@ ©¹« ś°6‡ Ž6‡ Ž ˜ 9~ -- ™ A5 /--‹‹‹ ’’’’’’’’ž’’’ ū’’’ ś’’’+ž’’’ž’’’ü’’’ż’’’*ž’’’ ž’’’  ż’’’'’’’’’’’’ ż’’’ ż’’’(ž’’’ż’’’ģ’’’)ż’’’ž’’’ ż’’’ ż’’’ ž’’’ š’’’  ż’’’ž’’’‰- M ˆ" Y ˆ! f ‰0 s Œ#   L ˆ X ˆ! e ‰/ r ‰. ~ Œ$ JŒ% Wš, dˆ& pˆ! }“4hUJYrdœXKh˜$cm™ 6Gn