Advertisement
dnnkeeper

UDK FeignDeath test

Nov 17th, 2012
491
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class UEX_TestPawn extends UDKPawn;
  2.  
  3. /** when we entered feign death; used to increase FeignDeathBodyAtRestSpeed over time so we get up in a reasonable amount of time */
  4. var float FeignDeathStartTime;
  5. /** When feign death recovery started.  Used to pull feign death camera into body during recovery */
  6. var float FeignDeathRecoveryStartTime;
  7. /** anim node used for feign death recovery animations */
  8. var AnimNodeBlend FeignDeathBlend;
  9.  
  10. var float FeignDeathBodyAtRestSpeed; /** when a body in feign death's velocity is less than this, it is considered to be at rest (allowing the player to get up) */
  11.  
  12. var name    HeadBone;
  13.  
  14. /** Set when pawn died on listen server, but was hidden rather than ragdolling (for replication purposes) */
  15. var bool bHideOnListenServer;
  16. /** bones to set fixed when doing the physics take hit effects */
  17. var array<name> TakeHitPhysicsFixedBones;
  18.  
  19. /** Array of bodies that should not have joint drive applied. */
  20. var array<name> NoDriveBodies;
  21.  
  22. /** Slot node used for playing full body anims. */
  23. var AnimNodeSlot FullBodyAnimSlot;
  24.  
  25. /** Slot node used for playing animations only on the top half. */
  26. var AnimNodeSlot TopHalfAnimSlot;
  27.  
  28. var(DeathAnim)  float   DeathHipLinSpring;
  29. var(DeathAnim)  float   DeathHipLinDamp;
  30. var(DeathAnim)  float   DeathHipAngSpring;
  31. var(DeathAnim)  float   DeathHipAngDamp;
  32.  
  33. var float RagdollLifespan;
  34.  
  35. /** World time that we started the death animation */
  36. var             float   StartDeathAnimTime;
  37. /** Time that we took damage of type DeathAnimDamageType. */
  38. var             float   TimeLastTookDeathAnimDamage;
  39. /** count of failed unfeign attempts - kill pawn if too many */
  40. var int UnfeignFailedCount;
  41.  
  42. /** true when feign death activation forced (e.g. knocked off hoverboard) */
  43. var bool bForcedFeignDeath;
  44.  
  45.  
  46. simulated event ReplicatedEvent(name VarName)
  47. {
  48.     if (VarName == 'bFeigningDeath')
  49.     {
  50.         `Log(self@"REPLICATED"@VarName@bFeigningDeath);
  51.         PlayFeignDeath();
  52.     }
  53.     else
  54.     {
  55.         Super.ReplicatedEvent(VarName);
  56.     }
  57. }
  58.  
  59. reliable server function ServerFeignDeath()
  60. {
  61.     if (Role == ROLE_Authority && !WorldInfo.Game.IsInState('MatchOver') && DrivenVehicle == None && Controller != None && !bFeigningDeath)
  62.     {
  63.         bFeigningDeath = true;
  64.         PlayFeignDeath();
  65.     }
  66. }
  67.  
  68. exec simulated function FeignDeath()
  69. {
  70.     ServerFeignDeath();
  71. }
  72.  
  73.  
  74. simulated function PlayFeignDeath(optional bool Permanent)
  75. {
  76.     if (bFeigningDeath){
  77.         PlayPhys(Permanent);
  78.     }
  79.     else
  80.         PlayGetUp();
  81. }
  82.  
  83.  
  84. simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
  85. {
  86.     if (SkelComp == Mesh)
  87.     {
  88.         FeignDeathBlend = AnimNodeBlend(Mesh.FindAnimNode('FeignDeathBlend'));     
  89.     }
  90.    
  91.     `Log(self@"SkelComp="@SkelComp@"Mesh="@Mesh@"FeignDeathBlend="@FeignDeathBlend);
  92.     if (Role == Role_Authority && Controller == None)
  93.     {
  94.        
  95.         bFeigningDeath=TRUE;
  96.        
  97.         SetTimer(1.0, false, 'PlayFeignDeath');
  98.     }
  99. }
  100.  
  101. simulated function PlayPhys(optional bool Permanent)
  102. {              
  103.         `Log(Self@"PlayPhys");
  104.        
  105.         StartFallImpactTime = WorldInfo.TimeSeconds;
  106.         bCanPlayFallingImpacts=true;
  107.         GotoState('FeigningDeath');
  108.  
  109.         // if we had some other rigid body thing going on, cancel it
  110.         if (Physics == PHYS_RigidBody)
  111.         {
  112.             //@note: Falling instead of None so Velocity/Acceleration don't get cleared
  113.             setPhysics(PHYS_Falling);
  114.         }
  115.  
  116.         // Ensure we are always updating kinematic
  117.         Mesh.MinDistFactorForKinematicUpdate = 0.0;
  118.  
  119.         SetPawnRBChannels(TRUE);
  120.         Mesh.ForceSkelUpdate();
  121.  
  122.         // Move into post so that we are hitting physics from last frame, rather than animated from this
  123.         Mesh.SetTickGroup(TG_PostAsyncWork);
  124.  
  125.         bBlendOutTakeHitPhysics = false;
  126.  
  127.         PreRagdollCollisionComponent = CollisionComponent;
  128.         CollisionComponent = Mesh;
  129.  
  130.         // Turn collision on for skelmeshcomp and off for cylinder
  131.         CylinderComponent.SetActorCollision(false, false);
  132.         Mesh.SetActorCollision(true, true);
  133.         Mesh.SetTraceBlocking(true, true);
  134.  
  135.         SetPhysics(PHYS_RigidBody);
  136.         Mesh.PhysicsWeight = 1.0;
  137.  
  138.         // If we had stopped updating kinematic bodies on this character due to distance from camera, force an update of bones now.
  139.         if( Mesh.bNotUpdatingKinematicDueToDistance )
  140.         {
  141.             Mesh.UpdateRBBonesFromSpaceBases(TRUE, TRUE);
  142.         }
  143.  
  144.         Mesh.PhysicsAssetInstance.SetAllBodiesFixed(FALSE);
  145.         Mesh.bUpdateKinematicBonesFromAnimation=FALSE;
  146.  
  147.         // Set all kinematic bodies to the current root velocity, since they may not have been updated during normal animation
  148.         // and therefore have zero derived velocity (this happens in 1st person camera mode).
  149.         Mesh.SetRBLinearVelocity(Velocity, false);
  150.  
  151.         FeignDeathStartTime = WorldInfo.TimeSeconds;
  152.         // reset mesh translation since adjustment code isn't executed on the server
  153.         // but the ragdoll code uses the translation so we need them to match up for the
  154.         // most accurate simulation
  155.         Mesh.SetTranslation(vect(0,0,1) * BaseTranslationOffset);
  156.         // we'll use the rigid body collision to check for falling damage
  157.         Mesh.ScriptRigidBodyCollisionThreshold = MaxFallSpeed;
  158.         Mesh.SetNotifyRigidBodyCollision(true);
  159.         Mesh.WakeRigidBody();
  160.  
  161.         if (Role == ROLE_Authority)
  162.         {
  163.             SetTimer(0.15, true, 'FeignDeathDelayTimer');
  164.         }
  165. }
  166.  
  167. state FeigningDeath
  168. {
  169.     ignores FaceRotation,  SetMovementPhysics;
  170.  
  171.     exec simulated function FeignDeath()
  172.     {
  173.         if (bFeigningDeath)
  174.         {
  175.             Global.FeignDeath();
  176.         }
  177.     }
  178.  
  179.     reliable server function ServerFeignDeath()
  180.     {
  181.         if (Role == ROLE_Authority && !WorldInfo.GRI.bMatchIsOver && !IsTimerActive('FeignDeathDelayTimer') && bFeigningDeath)
  182.         {
  183.             bFeigningDeath = false;
  184.             PlayFeignDeath();
  185.         }
  186.     }
  187.  
  188.     event bool EncroachingOn(Actor Other)
  189.     {
  190.  
  191.         // don't abort moves in ragdoll
  192.         return false;
  193.     }
  194.  
  195.     simulated function bool CanThrowWeapon()
  196.     {
  197.         return false;
  198.     }
  199.  
  200.     simulated function Tick(float DeltaTime)
  201.     {
  202.         local rotator NewRotation;
  203.  
  204.         if (bPlayingFeignDeathRecovery && PlayerController(Controller) != None)
  205.         {
  206.             // interpolate Controller yaw to our yaw so that we don't get our rotation snapped around when we get out of feign death
  207.             NewRotation = Controller.Rotation;
  208.             NewRotation.Yaw = RInterpTo(NewRotation, Rotation, DeltaTime, 2.0).Yaw;
  209.             Controller.SetRotation(NewRotation);
  210.  
  211.         }
  212.     }
  213.  
  214.  
  215.  
  216.     simulated event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
  217.     {
  218.         if (Physics != PHYS_RigidBody && !bPlayingFeignDeathRecovery)
  219.         {
  220.             // blend out of feign death animation
  221.             if (FeignDeathBlend != None)
  222.             {
  223.                 FeignDeathBlend.SetBlendTarget(0.0, 0.5);
  224.             }
  225.             GotoState('Auto');
  226.         }
  227.     }
  228.  
  229.     simulated event BeginState(name PreviousStateName)
  230.     {
  231.     }
  232.  
  233.     simulated function EndState(name NextStateName)
  234.     {
  235.    
  236.         local Actor A;
  237.  
  238.         if (NextStateName != 'Dying')
  239.         {
  240.             bNoWeaponFiring = default.bNoWeaponFiring;
  241.             bCanPickupInventory = default.bCanPickupInventory;
  242.  
  243.    
  244.             Global.SetMovementPhysics();
  245.  
  246.             bForcedFeignDeath = false;
  247.             bPlayingFeignDeathRecovery = false;
  248.  
  249.         }
  250.     }
  251. }
  252.  
  253. // prevents player from getting out of feign death until the body has come to rest
  254. function FeignDeathDelayTimer()
  255. {
  256.     if (Role != Role_Authority)
  257.         return;
  258.     //WorldInfo.Game.Broadcast(self,self@" FeignDeathDelayTimer ");
  259.     if ( /*Controller != none && */
  260.         (WorldInfo.TimeSeconds - FeignDeathStartTime > 1.0) &&
  261.         (PhysicsVolume.bWaterVolume || (VSize(Velocity) < 4.0 * FeignDeathBodyAtRestSpeed * (WorldInfo.TimeSeconds - FeignDeathStartTime))) )
  262.     {
  263.         // clear timer, so we can come out of feign death
  264.         //ClearTimer('FeignDeathDelayTimer');
  265.         // automatically get up if we were forced into it
  266.             ClearTimer('FeignDeathDelayTimer');
  267.             PlayGetUp();
  268.  
  269.     }
  270. }
  271.  
  272. simulated function PlayGetUp()
  273. {
  274.     local vector FeignLocation, HitLocation, HitNormal, TraceEnd, Impulse;
  275.     local rotator NewRotation;
  276.     //local UTWeapon UTWeap;
  277.     local Vehicle V;
  278.     local Controller Killer;
  279.     local float UnFeignZAdjust;
  280.    
  281.     `Log(self@"PlayGetUp"@PreRagdollCollisionComponent);
  282.     bFeigningDeath=FALSE;
  283.         // fit cylinder collision into location, crouching if necessary
  284.         FeignLocation = Location;
  285.         CollisionComponent = PreRagdollCollisionComponent;
  286.         TraceEnd = Location + vect(0,0,1) * GetCollisionHeight();
  287.         if (Trace(HitLocation, HitNormal, TraceEnd, Location, true, GetCollisionExtent()) == None )
  288.         {
  289.             HitLocation = TraceEnd;
  290.         }
  291.         if ( !SetFeignEndLocation(HitLocation, FeignLocation) )
  292.         {
  293.             CollisionComponent = Mesh;
  294.             SetLocation(FeignLocation);
  295.             bFeigningDeath = true;
  296.             Impulse = VRand();
  297.             Impulse.Z = 0.5;
  298.             Mesh.AddImpulse(800.0*Impulse, Location);
  299.             UnfeignFailedCount++;
  300.             if ( UnFeignfailedCount > 4 )
  301.             {
  302.                 Suicide();
  303.             }
  304.             return;
  305.         }
  306.  
  307.         // Calculate how far we just moved the actor up.
  308.         UnFeignZAdjust = Location.Z - FeignLocation.Z;
  309.         // If its positive, move back down by that amount until it hits the floor
  310.         if(UnFeignZAdjust > 0.0)
  311.         {
  312.             moveSmooth(vect(0,0,-1) * UnFeignZAdjust);
  313.         }
  314.  
  315.         UnfeignFailedCount = 0;
  316.  
  317.         CollisionComponent = Mesh;
  318.  
  319.         bPlayingFeignDeathRecovery = true;
  320.         FeignDeathRecoveryStartTime = WorldInfo.TimeSeconds;
  321.  
  322.         // don't need collision events anymore
  323.         Mesh.SetNotifyRigidBodyCollision(false);
  324.         // don't allow player to move while animation is in progress
  325.         SetPhysics(PHYS_None);
  326.  
  327.    
  328.         `Log(self@"FeignDeathBlend="@FeignDeathBlend);
  329.         // find getup animation, and freeze it at the first frame
  330.         if ( (FeignDeathBlend != None) && !bIsCrouched )
  331.         {
  332.             // physics weight interpolated to 0 in C++, then StartFeignDeathRecoveryAnim() is called
  333.             Mesh.PhysicsWeight = 1.0;
  334.             FeignDeathBlend.SetBlendTarget(1.0, 0.0);
  335.             StartFeignDeathRecoveryAnim();
  336.             // force rotation to match the body's direction so the blend to the getup animation looks more natural
  337.             NewRotation = Rotation;
  338.             NewRotation.Yaw = rotator(Mesh.GetBoneAxis('b_Hips', AXIS_X)).Yaw;
  339.             // flip it around if the head is facing upwards, since the animation for that makes the character
  340.             // end up facing in the opposite direction that its body is pointing on the ground
  341.             // FIXME: generalize this somehow (stick it in the AnimNode, I guess...)
  342.             if (Mesh.GetBoneAxis(HeadBone, AXIS_Y).Z < 0.0)
  343.             {
  344.                 NewRotation.Yaw += 32768;
  345.             }
  346.             SetRotation(NewRotation);
  347.         }
  348.         else
  349.         {
  350.             // failed to find recovery node, so just pop out of ragdoll
  351.             RestorePreRagdollCollisionComponent();
  352.             Mesh.PhysicsWeight = 0.f;
  353.             Mesh.PhysicsAssetInstance.SetAllBodiesFixed(TRUE);
  354.             Mesh.bUpdateKinematicBonesFromAnimation=TRUE;
  355.             Mesh.MinDistFactorForKinematicUpdate = default.Mesh.MinDistFactorForKinematicUpdate;
  356.             SetPawnRBChannels(FALSE);
  357.  
  358.             if (Physics == PHYS_RigidBody)
  359.             {
  360.                 setPhysics(PHYS_Falling);
  361.             }
  362.  
  363.             GotoState('Auto');
  364.         }
  365. }
  366.  
  367.  
  368. //Установки, чтоб не проваливаться сквозь геометрию
  369. simulated function SetPawnRBChannels(bool bRagdollMode)
  370. {
  371.     if(bRagdollMode)
  372.     {
  373.         Mesh.SetRBChannel(RBCC_Pawn);
  374.         Mesh.SetRBCollidesWithChannel(RBCC_Default,TRUE);
  375.         Mesh.SetRBCollidesWithChannel(RBCC_Pawn,false);
  376.         Mesh.SetRBCollidesWithChannel(RBCC_Vehicle,TRUE);
  377.         Mesh.SetRBCollidesWithChannel(RBCC_Untitled3,FALSE);
  378.         Mesh.SetRBCollidesWithChannel(RBCC_BlockingVolume,TRUE);
  379.     }
  380.     else
  381.     {
  382.         Mesh.SetRBChannel(RBCC_Untitled3);
  383.         Mesh.SetRBCollidesWithChannel(RBCC_Default,FALSE);
  384.         Mesh.SetRBCollidesWithChannel(RBCC_Pawn,FALSE);
  385.         Mesh.SetRBCollidesWithChannel(RBCC_Vehicle,FALSE);
  386.         Mesh.SetRBCollidesWithChannel(RBCC_Untitled3,TRUE);
  387.         Mesh.SetRBCollidesWithChannel(RBCC_BlockingVolume,FALSE);
  388.     }
  389. }
  390.  
  391.  
  392. simulated function bool SetFeignEndLocation(vector HitLocation, vector FeignLocation)
  393. {
  394.     local vector NewDest;
  395.  
  396.     if ( SetLocation(HitLocation) && CheckValidLocation(FeignLocation) )
  397.     {
  398.         return true;
  399.     }
  400.  
  401.     // try crouching
  402.     ForceCrouch();
  403.     if ( SetLocation(HitLocation) && CheckValidLocation(FeignLocation) )
  404.     {
  405.         return true;
  406.     }
  407.  
  408.     newdest = HitLocation + GetCollisionRadius() * vect(1,1,0);
  409.     if ( SetLocation(newdest) && CheckValidLocation(FeignLocation) )
  410.         return true;
  411.     newdest = HitLocation + GetCollisionRadius() * vect(1,-1,0);
  412.     if ( SetLocation(newdest) && CheckValidLocation(FeignLocation) )
  413.         return true;
  414.     newdest = HitLocation + GetCollisionRadius() * vect(-1,1,0);
  415.     if ( SetLocation(newdest) && CheckValidLocation(FeignLocation) )
  416.         return true;
  417.     newdest = HitLocation + GetCollisionRadius() * vect(-1,-1,0);
  418.     if ( SetLocation(newdest) && CheckValidLocation(FeignLocation) )
  419.         return true;
  420.  
  421.     return false;
  422. }
  423.  
  424. /**
  425.   * Make sure location pawn ended up at out of feign death is valid (not through a wall)
  426.   */
  427. simulated function bool CheckValidLocation(vector FeignLocation)
  428. {
  429.     local vector HitLocation, HitNormal, DestFinalZ;
  430.  
  431.     // try trace down to dest
  432.     if (Trace(HitLocation, HitNormal, Location, FeignLocation, false, vect(10,10,10),, TRACEFLAG_Bullet) == None)
  433.     {
  434.         return true;
  435.     }
  436.  
  437.     // try trace straight up, then sideways to final location
  438.     DestFinalZ = FeignLocation;
  439.     FeignLocation.Z = Location.Z;
  440.     if ( Trace(HitLocation, HitNormal, DestFinalZ, FeignLocation, false, vect(10,10,10)) == None &&
  441.         Trace(HitLocation, HitNormal, Location, DestFinalZ, false, vect(10,10,10),, TRACEFLAG_Bullet) == None )
  442.     {
  443.         return true;
  444.     }
  445.     return false;
  446. }
  447.  
  448.  
  449. /** called when bPlayingFeignDeathRecovery and interpolating our Mesh's PhysicsWeight to 0 has completed
  450.  *  starts the recovery anim playing
  451.  */
  452. simulated event StartFeignDeathRecoveryAnim()
  453. {
  454.         // we're done with the ragdoll, so get rid of it
  455.     RestorePreRagdollCollisionComponent();
  456.     Mesh.PhysicsWeight = 0.f;
  457.     Mesh.MinDistFactorForKinematicUpdate = default.Mesh.MinDistFactorForKinematicUpdate;
  458.     Mesh.PhysicsAssetInstance.SetAllBodiesFixed(TRUE);
  459.     Mesh.PhysicsAssetInstance.SetFullAnimWeightBonesFixed(FALSE, Mesh);
  460.     SetPawnRBChannels(FALSE);
  461.     Mesh.bUpdateKinematicBonesFromAnimation=TRUE;
  462.  
  463.     // Turn collision on for cylinder and off for skelmeshcomp
  464.     CylinderComponent.SetActorCollision(true, true);
  465.     Mesh.SetActorCollision(false, false);
  466.     Mesh.SetTraceBlocking(false, false);
  467.  
  468.     Mesh.SetTickGroup(TG_PreAsyncWork);
  469.  
  470.     if (Physics == PHYS_RigidBody)
  471.     {
  472.         setPhysics(PHYS_Falling);
  473.     }
  474.  
  475.  
  476.     if (FeignDeathBlend != None && FeignDeathBlend.Children[1].Anim != None)
  477.     {
  478.         FeignDeathBlend.Children[1].Anim.PlayAnim(false, 1.1);
  479.     }
  480.     else
  481.     {
  482.         // failed to find recovery node, so just pop out of ragdoll
  483.         bNoWeaponFiring = default.bNoWeaponFiring;
  484.         GotoState('Auto');
  485.     }
  486.    
  487. }
  488.  
  489. defaultproperties
  490. {
  491.     Begin Object Class=SkeletalMeshComponent Name=PawnMesh
  492.         SkeletalMesh = SkeletalMesh'CH_IronGuard_Male.Mesh.SK_CH_IronGuard_MaleA'
  493.         AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'       
  494.         AnimSets(0) = AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
  495.         PhysicsAsset = PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
  496.         bHasPhysicsAssetInstance=TRUE
  497.        
  498.         bCacheAnimSequenceNodes=false
  499.         AlwaysLoadOnClient=TRUE
  500.         AlwaysLoadOnServer=TRUE
  501.         bOwnerNoSee=false
  502.         CastShadow=true
  503.  
  504.        
  505.         bUpdateSkelWhenNotRendered=true
  506.         bIgnoreControllersWhenNotRendered=false
  507.         bUpdateKinematicBonesFromAnimation=TRUE
  508.         bCastDynamicShadow=TRUE
  509.  
  510.         BlockNonZeroExtent=true
  511.         BlockZeroExtent=true
  512.         BlockActors=true
  513.         CollideActors=true
  514.         BlockRigidBody=true
  515.         AlwaysCheckCollision=true
  516.         //bIgnoreEncroachers=true
  517.         RBChannel=RBCC_Pawn
  518.         RBCollideWithChannels=(Pawn=TRUE, Default=TRUE,GameplayPhysics=TRUE,EffectPhysics=TRUE,Cloth=FALSE)
  519.            
  520.         bOverrideAttachmentOwnerVisibility=TRUE
  521.         bAcceptsDynamicDecals=TRUE
  522.  
  523.         TickGroup=TG_PreAsyncWork
  524.         MinDistFactorForKinematicUpdate=0.2
  525.        
  526.         bChartDistanceFactor=TRUE
  527.        
  528.         //bSkipAllUpdateWhenPhysicsAsleep=TRUE
  529.        
  530.         RBDominanceGroup=20
  531.        
  532.         Scale=1
  533.         //MotionBlurScale=0.0
  534.         bAllowAmbientOcclusion=TRUE
  535.         // Nice lighting for hair
  536.         bUseOnePassLightingOnTranslucency=TRUE
  537.         bPerBoneMotionBlur=TRUE
  538.        
  539.     End Object
  540.    
  541.     Mesh=PawnMesh
  542.     Components.Add(PawnMesh)
  543.    
  544.     HeadBone=b_Head
  545.     FeignDeathBodyAtRestSpeed=12.0
  546.    
  547.     AlwaysRelevantDistanceSquared=+1960000.0
  548.     bPhysRigidBodyOutOfWorldCheck=TRUE
  549.     bRunPhysicsWithNoController=true
  550. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement