//============================================================================= // KFPawn_ZedCrawler //============================================================================= // Crawler //============================================================================= // Killing Floor 2 // Copyright (C) 2016 Tripwire Interactive LLC //============================================================================= class KFPawn_ZedCrawler extends KFPawn_Monster; var protected Actor LastBumpLevelActor; var protected float LastBumpLevelTime; /** Template used by special crawlers when exploding during death */ var protected const KFGameExplosion DeathExplosionTemplate; /** How much of an impulse to apply to crawler if gore settings prevent dismemberment */ var protected const float LowGoreExplosionImpulse; event PossessedBy( Controller C, bool bVehicleTransition ) { local KFAIController_ZedCrawler CrawlerController; super.PossessedBy( C, bVehicleTransition ); LastBumpLevelActor = none; CrawlerController = KFAIController_ZedCrawler( MyKFAIC ); if( CrawlerController != none ) { CrawlerController.OriginalMeshTranslation = Mesh.Translation; } } // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm //simulated event BaseChange() //{ // Super.BaseChange(); // // if( Base != None && Pawn(Base) == none ) // Added pawn check 3/18 // { // if (Role == ROLE_Authority) // { // ReplicatedFloor = Floor; // } // else // { // Floor = ReplicatedFloor; // } // } //} /** * SpecialMoveTo() - Called by NavigationPoint SuggestMovePreparation event, * provides option for pawn to do something special (but not necessarily a real * KFSpecialMove) for this reachspec. * * @param Start Starting node * @param End Ending node * @param Next Which node is currently next (need to check if Start != End) */ // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm //function bool SpecialMoveTo( NavigationPoint Start, NavigationPoint End, Actor Next ) //{ // local ReachSpec CurrentPath; // local vector EndLocation; // local AICommand ActiveCommand; //// local int i; // //local KFDebugLines KFDL; // // if( Start == End ) // { // return false; // } // // CurrentPath = Start.GetReachSpecTo( End ); // if( CurrentPath == none ) // { // `AILog_Ext( GetFuncName()$"() WARNING - Can't find ReachSpec from start "$Start$" to End "$End$" (Next: "$Next$")", 'Crawler', MyKFAIC ); // } // EndLocation = CurrentPath.End.Actor.Location; // `AILog_Ext( GetFuncName()$" CurrentPath: "$CurrentPath$" Start: "$Start$" End: "$End$" Next: "$Next$" Phys: "$GetPhysicsName()$" Velocity: "$VSize(Velocity)$" Dist From Start "$VSize(Start.Location - Location)$" Dist From End: "$VSize(End.Location - Location), 'Crawler', MyKFAIC ); // `AILog_Ext( GetFuncName()$" MoveGoal: "$MyKFAIC.MoveGoal$" Dist from: "$VSize(MyKFAIC.MoveGoal.Location - Location), 'Crawler', MyKFAIC ); // // if( CurrentPath.BlockedBy != none ) // { // `log( "CurrentPath "$CurrentPath$" blockedBy was "$CurrentPath.BlockedBy ); // } // // if( WallToFloorReachSpec(CurrentPath) != none && WallToFloorReachSpec(CurrentPath).bJumpDownTo ) // && !End.IsA('KFWallPathNode') ) // { // MyKFAIC.AIActionStatus = "Falling from wall using "$CurrentPath$" ("$Start$")"; // SetPhysics( PHYS_Falling ); // return false; // } // // JC: Temp // if( !NavigationPoint(CurrentPath.End.Actor).bWallNode && CurrentPath.Start.bWallNode ) // { // if( (Location.Z - EndLocation.Z > 0.f) && ((Location.Z - EndLocation.Z) <= KFWallPathNode(CurrentPath.End.Actor).MaxDropFromWallDistance) ) // { // if( VSize2D(EndLocation - Location) <= KFWallPathNode(CurrentPath.End.Actor).Max2DDistToFloorNodes ) // { // MyKFAIC.AIActionStatus = "Falling from wall using "$CurrentPath$" ("$Start$")"; // SetPhysics( PHYS_Falling ); // return false; // } // } // } // // if( KFPathnode( End ) != none ) // { // if( CurrentPath != none && CurrentPath.IsA( 'WallToFloorReachSpec' ) && Physics == PHYS_Spider ) // { // if( WallToFloorReachSpec(CurrentPath).bJumpDownTo ) // { // SetPhysics( PHYS_Falling ); // } // } // } // // if( CurrentPath != None && Physics == PHYS_Walking && End.IsA('KFWallPathNode') ) // { // if( KFWallPathNode(End).bMustJumpTo ) // { // ActiveCommand = AICommand( MyKFAIC.GetActiveCommand() ); // if( WallReachSpec(CurrentPath) != none && (ActiveCommand == none || !ActiveCommand.IsA('AICommand_Crawler_LeapToWall')) ) // { // return SpecialMoveTo_Leap( Start, End, KFPathnode(Start).JumpTime ); // } // else if( (ActiveCommand == none || !ActiveCommand.IsA('AICommand_Crawler_LeapToWall')) ) // { // return SpecialMoveTo_Leap( Start, End ); // } // } // else if( !CurrentPath.Start.IsA('KFDoorMarker') && !Next.IsA('KFDoorMarker') ) // { // //KFDL = class'KFDebugLines'.static.GetDebugLines(); // //if( KFDL != none ) // //{ // // KFDL.AddDebugSphere( Start.Location, 24, 8, 0, 255, 0, true, 200, name, 1 ); // // KFDL.AddDebugSphere( End.Location, 24, 8, 255, 0, 0, true, 200, name, 2 ); // // KFDL.AddDebugSphere( Next.Location, 18, 6, 255, 255, 0, true, 200, name, 3 ); // //} // `AILog_Ext( GetFuncName()$" Setting PHYS to PHYS_SPIDER DIST: "$VSize(End.Location-Location), 'Crawler', MyKFAIC ); // SetPhysics(PHYS_Spider); // // MyKFAIC.ForcePauseAndRepath(); 2.5.2014 // // MyKFAIC.PauseAndShowMsg( "SpecialMoveTo Setting PHYS to Spider Start: "$Start$" End: "$End ); // return false; // } // return true; // } // return false; //} function bool SpecialMoveTo_Leap( NavigationPoint Start, NavigationPoint End, optional float JumpTime=0.45f ) { class'AICommand_Crawler_LeapToWall'.static.LeapToWall( KFAIController_ZedCrawler(MyKFAIC), Start, End, JumpTime ); return TRUE; } /** * BumpLevel() - Event called by KFPawn_Monster NotifyBumpLevel() when bumping * geometry (this includes when landing on the ground). * * @param HitLocation World location where the level was bumped * @param HitNormal The normal generated at collision * @param Wall The actor, if any, that's considered to be the wall */ event SpiderBumpLevel( vector HitLocation, vector HitNormal, optional actor Wall ) { local AICommand ActiveCommand; if( MyKFAIC != none ) { if( LastBumpLevelTime == 0.f || `TimeSince(LastBumpLevelTime) > 0.1f ) { LastBumpLevelTime = WorldInfo.TimeSeconds; ActiveCommand = AICommand( MyKFAIC.GetActiveCommand() ); if( Physics != PHYS_Falling || (ActiveCommand != none && AICommand_Crawler_LeapToWall(ActiveCommand) != none) ) { if( Wall != none && LastBumpLevelActor != Wall ) { `AILog_Ext( "(Pawn) "$GetFuncName()$" Wall: "$Wall$" HitNormal: "$HitNormal, 'Crawler', MyKFAIC ); LastBumpLevelActor = Wall; MyKFAIC.NotifyHitWall( HitNormal, Wall ); } } else { `AILog_Ext( "(Pawn) [PHYS_FALLING] "$GetFuncName()$" Wall: "$Wall$" HitNormal: "$HitNormal, 'Crawler', MyKFAIC ); } } } } // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm //simulated event RootMotionProcessed(SkeletalMeshComponent SkelComp) //{ // if( Mesh.RootMotionVelocity != vect(0,0,0) ) // { // //MyKFAIC.LastCrawlerX = Mesh.RootMotionVelocity; // //MyKFAIC.SetFocalPoint( Location + normal(Mesh.RootMotionVelocity) * 512.f ); // KFAIController_ZedCrawler(MyKFAIC).LastRMVelocity = Mesh.RootMotionVelocity; // } //} /********************************************************************************************* * Debugging ********************************************************************************************* */ /** Render some Fleshpound specific debug text over his head */ /** * GetOverheadDebugText() - Called by KFAIController if rendering debug text is enabled. * Gives Pawn a chance to include some debug text of its own. * * @param ModifyTextColor Optionally override the default text color */ simulated function GetOverheadDebugText( KFHUDBase HUD, out array OverheadTexts, out array OverheadColors ) { local string DebugText; Super.GetOverheadDebugText(HUD, OverheadTexts, OverheadColors); if( MyKFAIC != none ) { DebugText = DebugText$"\nPhys:"$GetPhysicsName()$" Floor:"$Floor$" Rot:"$Rotation$" Desired:"$DesiredRotation; if( Base != none ) { DebugText = DebugText$"\nBase:"$Base; } } OverheadTexts[OverheadTexts.Length] = DebugText; } /** * DrawDebugRotation() - Draw Pawn's rotation information in front */ simulated function DrawDebugRotation() { local vector vExtent, StartLoc; if ( Mesh!=none ) { // draw cylinder around them vExtent = vect( 0,0,1 ) * GetCollisionHeight(); DrawDebugCylinder(Location-vExtent, Location+vExtent, GetCollisionRadius(), 10, 100, 100, 0); // Draw Pawn's rotation coordinate in front/top of their cylinder, so it's more visible - red being exactly yaw StartLoc = Location+vExtent*GetCollisionRadius(); DrawDebugCoordinateSystem(StartLoc, Rotation, 75); if ( ReachedDesiredRotation()==false ) { // if pawn is rotating, please draw desired rotation with yellow DrawDebugLine(Location, Location+Vector(DesiredRotation)*750, 0, 100, 255); } } } simulated function Tick( float DeltaTime ) { Super.Tick( DeltaTime ); if( bDebugCrawlerPhysics ) { DrawDebugRotation(); } } /** Returns (hardcoded) dialog event ID for when players spots this zed type */ function int GetSpotterDialogID() { local int EmergeType; if( IsDoingSpecialMove(SM_Emerge) ) { EmergeType = SpecialMoveFlags & 0x0f; switch( EmergeType ) { case EMERGE_Floor: return 142;//SPOTZ_EmergeFloor case EMERGE_Wall248UU: case EMERGE_WallHigh: return 140;//SPOTZ_EmergeVent case EMERGE_Ceiling: return 141;//SPOTZ_EmergeCeiling default: return 125;//SPOTZ_Generic }; } if( Floor.Z > 0.7 ) { // floor return 125;//SPOTZ_Generic } else if( Floor.Z < -0.7 ) { // ceiling return 139;//SPOTZ_Ceiling } else { // wall? return 138;//SPOTZ_Wall } return 125;//SPOTZ_Generic } /** Added knockdown when jumped on */ defaultproperties { LocalizationKey=KFPawn_ZedCrawler // Third person body component Begin Object Name=KFPawnSkeletalMeshComponent Translation=(Z=-40) // based on CollisionHeight bPerBoneMotionBlur=false End Object Begin Object Name=CollisionCylinder // Use collision cube to make it easier when we orient the crawler to the // wall. Otherwise, we would need to dynamically adjust Mesh Translation CollisionHeight=40.0 CollisionRadius=+47.0 End Object // --------------------------------------------- // Stats XPValues(0)=8 XPValues(1)=10 XPValues(2)=10 XPValues(3)=10 bIsCrawlerClass=true // --------------------------------------------- // Content MonsterArchPath="ZED_ARCH.ZED_Crawler_Archetype" PawnAnimInfo=KFPawnAnimInfo'ZED_Crawler_ANIM.Crawler_AnimGroup' DifficultySettings=class'KFDifficulty_Crawler' // --------------------------------------------- // Gameplay Begin Object Name=MeleeHelper_0 BaseDamage=7.f MaxHitRange=180.f MomentumTransfer=25000.f MyDamageType=class'KFDT_Slashing_ZedWeak' End Object Health=55 DoshValue=10 Mass=50.f bKnockdownWhenJumpedOn=true // Penetration PenetrationResistance=0.5 DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Submachinegun', DamageScale=(1.5))) //2.25 DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_AssaultRifle', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Shotgun', DamageScale=(1.0))) //0.75 //0.8 DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Handgun', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Rifle', DamageScale=(1.0))) //0.45 DamageTypeModifiers.Add((DamageType=class'KFDT_Slashing', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Bludgeon', DamageScale=(0.9))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire', DamageScale=(0.9))) //0.6 DamageTypeModifiers.Add((DamageType=class'KFDT_Microwave', DamageScale=(0.2))) DamageTypeModifiers.Add((DamageType=class'KFDT_Explosive', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing', DamageScale=(1.0))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic', DamageScale=(1.0))) // --------------------------------------------- // Movement / Physics // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm ReachedGoalThresh_Walking=0.f//=30.f //ReachedGoalThresh_Spider=30.f RotationRate=(Pitch=90000,Yaw=45000,Roll=90000) GroundSpeed=400.f //280 SprintSpeed=500.f bCrawler=false//true - // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm bCanClimbCeilings=false//true - // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm MaxFallSpeed=6000 JumpZ=750 bUseQuadrupedFloorConform=true // --------------------------------------------- // AI / Navigation ElitePawnClass.Add(class'KFPawn_ZedCrawlerKing') ControllerClass=class'KFAIController_ZedCrawler' bDebugCrawlerPhysics=false bDisableTurnInPlace=true bBlocksNavigation=true //ExtraCostForPath=2000 DamageRecoveryTimeHeavy=0.75f DamageRecoveryTimeMedium=1.0f KnockdownImpulseScale=1.0f // --------------------------------------------- // Special Moves Begin Object Name=SpecialMoveHandler_0 SpecialMoveClasses(SM_Emerge)=class'KFSM_Emerge_Crawler' SpecialMoveClasses(SM_Evade)=class'KFSM_Evade' SpecialMoveClasses(SM_Evade_Fear)=class'KFSM_Evade_Fear' End Object // for reference: Vulnerability=(default, head, legs, arms, special) IncapSettings(AF_Stun)= (Vulnerability=(2.0, 2.0, 1.0, 1.0, 1.0), Cooldown=5.0, Duration=2.5) IncapSettings(AF_Knockdown)=(Vulnerability=(2.f), Cooldown=1.0) IncapSettings(AF_Stumble)= (Vulnerability=(2.f), Cooldown=0.2) IncapSettings(AF_GunHit)= (Vulnerability=(2.5), Cooldown=0.2) IncapSettings(AF_MeleeHit)= (Vulnerability=(2.0), Cooldown=0.0) IncapSettings(AF_Poison)= (Vulnerability=(10.0), Cooldown=7.5, Duration=5.5) IncapSettings(AF_Microwave)=(Vulnerability=(0.5), Cooldown=7.5, Duration=3.0) IncapSettings(AF_FirePanic)=(Vulnerability=(3), Cooldown=7.0, Duration=5) IncapSettings(AF_EMP)= (Vulnerability=(2.5), Cooldown=5.0, Duration=5.0) IncapSettings(AF_Freeze)= (Vulnerability=(2.5), Cooldown=1.5, Duration=4.5) IncapSettings(AF_Snare)= (Vulnerability=(10.0, 10.0, 10.0, 10.0), Cooldown=5.5, Duration=4.0) IncapSettings(AF_Bleed)= (Vulnerability=(2.0)) ParryResistance=1 // Used for special crawler gas AOE attack "explosion" template Begin Object Class=KFGameExplosion Name=ExploTemplate0 Damage=4 DamageRadius=450 //600 DamageFalloffExponent=0.f DamageDelay=0.f MyDamageType=class'KFDT_Toxic_PlayerCrawlerSuicide' // Damage Effects KnockDownStrength=0 KnockDownRadius=0 FractureMeshRadius=0 FracturePartVel=0 ExplosionEffects=KFImpactEffectInfo'ZED_Crawler_ARCH.ToxicGasAoE_Explosion' ExplosionSound=AkEvent'WW_WEP_EXP_Dynamite.Play_WEP_EXP_Dynamite_Explosion' MomentumTransferScale=100 // Dynamic Light ExploLight=none // Camera Shake CamShake=CameraShake'FX_CameraShake_Arch.Grenades.Default_Grenade' CamShakeInnerRadius=450 CamShakeOuterRadius=900 CamShakeFalloff=1.f bOrientCameraShakeTowardsEpicenter=true End Object DeathExplosionTemplate=ExploTemplate0 LowGoreExplosionImpulse=5000.f `if(`notdefined(ShippingPC)) DebugRadarTexture=Texture2D'UI_ZEDRadar_TEX.MapIcon_Crawler'; `endif // --------------------------------------------- // Spawning MinSpawnSquadSizeType=EST_Crawler }