468 lines
16 KiB
Ucode
468 lines
16 KiB
Ucode
//=============================================================================
|
|
// 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<string> OverheadTexts, out array<Color> 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
|
|
}
|