5
\$\begingroup\$

I'm working on a game in which the player runs around a level themed as a pinball machine. There are flippers that react to the presence of pinballs by flipping (as one would expect pinball flippers to do). The problem that I'm having is that if the player is in the path of the flipper as it rotates, the player is instantly killed. The desired behavior is that the player is damaged and pushed away from the moving flipper.

I've tried all sorts of things to make this stop happening. Currently, in the flipper, I have the following code to handle the collision:

event Bump(Actor other, PrimitiveComponent otherComp, Object.Vector hitNormal)
{
    local vector pushVelocity;

    if(/*If Flipper is moving and is bump()ing the Player*/)
    {
        pushVelocity = hitNormal * CalcLinearVelocity(vsize(location - other.location));
        player.TakeDamage(playerDamage, none, player.Location, pushVelocity * 2.1f, class'DamageType', , self);
    }
}

By using all sorts of logging, I can determine that the code in question is being called when the flipper hits the player and the player is being killed on the first frame this collision occurs--logging within the if() block only appears once. And yes, playerDamage is a value low enough that it would take many hits to kill the player.

Does anyone have any insight as to why the player is immediately dying instead of being damaged and pushed away? Or what sorts of things I should try to get my intended behavior?

\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

It took a while but I eventually found a fix for it. Some debugging eventually revealed the player was being telefragged. Intercepting EncroachedBy() in our player's Pawn class with a no-op has stopped the issue:

event EncroachedBy(Actor Other)
{
    //NOP!
}

I'm not sure if this is just putting a band-aid on a severed limb here but it's working now.

Thanks for the suggestions above!

\$\endgroup\$
2
\$\begingroup\$

There's a chance this is the same problem I saw working on a UT3 mod a long time ago. If your pawn is at risk of interpenetrating the world geometry, the pawn is killed via the event FellOutOfWorld. This happens quite frequently if your pawn is forced to ragdoll and subsequently gets pushed around.

I believe the interpenetration=kill hack was originally implemented in native code in UT3, and I couldn't tell you if it has since been moved out into UnrealScript in subsequent updates to the UDK sources.

My workaround, taken from my pawn class, ended up looking like this (again, this is against UT3 code):

/** If someone falls out of the world while ragdolled, they have 
    this many seconds to stand up before they're killed. */
var float OOWGracePeriod;

/*
 * Extremely common scenario:
 *   1) Pawn is ragdolled and has a substantial vertical impulse applied.
 *   2) Pawn very briefly "leaves world" upon ragdoll impacting ceiling.
 *   3a) Pawn would recover immediately; however, they were killed for falling out of the world.
 *   OR
 *   3b) Pawn's ragdoll collision geometry interpenetrates world geometry and gets stuck.
 *
 * In the event of 3a (99% of the time), we don't want the pawn to die.
 * In the event of 3b ( 1% of the time), we don't have much choice but to euthanize them.
 *
 * Therefore, give them a grace period in which to recover.
 */

simulated event FellOutOfWorld( class dmgType )
{
    if ( ! bForcedFeignDeath )
        Super.FellOutOfWorld(dmgType);
    else if ( ! IsTimerActive('KillIfStillForcedRagdoll') )
        SetTimer( OOWGracePeriod, false, 'KillIfStillForcedRagdoll' );
}

function KillIfStillForcedRagdoll()
{
    if ( bForcedFeignDeath )
        Super.FellOutOfWorld( class'KillZDamageType' );
}

function FeignDeathDelayTimer()
{
    Super.FeignDeathDelayTimer();

    if ( ! bFeigningDeath )
        ClearTimer( 'KillIfStillForcedRagdoll' );
}

EDIT: Almost forgot there was a second part to this.

/*
 * Another extremely common scenario: Ragdolled pawn gets crushed upon impacting wall.
 * Therefore, don't let crush damage from the world affect us while we're force-ragdolled.
 */

event TakeDamage( int Damage, Controller EventInstigator, Vector HitLocation, Vector Momentum, class dmgType, optional TraceHitInfo HitInfo, optional Actor DamageCauser )
{
    if ( bForcedFeignDeath && dmgType == class'DmgType_Crushed' && DamageCauser == None )
            return;

    Super.TakeDamage( Damage, EventInstigator, HitLocation, Momentum, dmgType, HitInfo, DamageCauser );
}

Yes, it was an egregious hack. But there was no way around those when working with UT3, because of how much stuff is implemented in native code. I can't imagine it's that much better with UDK.

\$\endgroup\$
3
  • \$\begingroup\$ Your TakeDamage() is in the player Pawn itself, correct? Essentially intercepting any damage calls before moving up the hierarchy? I'll have to give some of that logic a try. \$\endgroup\$ Commented Apr 7, 2011 at 19:04
  • \$\begingroup\$ Yes, both of those excerpts were from the pawn class. \$\endgroup\$
    – Zach
    Commented Apr 7, 2011 at 20:02
  • \$\begingroup\$ Seems (due to logging) that the Pawn is never out of world nor is it damaged outside of the one frame it's hit by the flipper before dying. Any other ideas? \$\endgroup\$ Commented Apr 11, 2011 at 19:01
1
\$\begingroup\$

Are you moving the player to the boundaries of the flipper when the collision occurs? I guess you don't do that and therefore:

  • the player collides with the flipper, ...
  • takes damage, changes direction (because of the collision),...
  • but since the player wasn't moved out of the collision area, it hits the flipper again and takes damage...
  • maybe the direction is reversed here once more and therefore you're in some sort of "collision-loop" where the player takes damage with every update.
\$\endgroup\$
1
  • \$\begingroup\$ Any function I've used to try to relocate the Pawn hasn't seemed to prevent this from happening. Also, as I mention in my question, the Pawn is only taking damage on one frame and it isn't enough to kill him. \$\endgroup\$ Commented Apr 11, 2011 at 19:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .