1
0
KF2-Dev-Scripts/KFGameContent/Classes/KFDT_Slashing_EvisceratorProj.uc
2020-12-13 18:01:13 +03:00

190 lines
6.2 KiB
Ucode

//=============================================================================
// KFDT_Slashing_EvisceratorProj
//=============================================================================
// Damage type for projectiles fired from the Eviscerator
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// John "Ramm-Jaeger" Gibson
//=============================================================================
class KFDT_Slashing_EvisceratorProj extends KFDT_Slashing
abstract
hidedropdown;
`define COSINE_0_DEGREES 1
`define COSINE_20_DEGREES 0.94
`define COSINE_70_DEGREES 0.34
`define COSINE_90_DEGREES 0
/** Allows the damage type to customize exactly which hit zones it can dismember */
static simulated function bool CanDismemberHitZone( name InHitZoneName )
{
return true;
}
/** @return The slast type from the HitFxInfo. This returns a 8-way slash info. */
static simulated function EPawnOctant GetLastSlashDirection(KFPawn_Monster InPawn, vector HitDirection)
{
local vector SlashPlaneNormal;
local rotator InstigatorRotation;
local vector InstigatorFaceDir, InstigatorRightDir;
local float UpDotSlash, RightDotSlash, UpThresholdValue;
if( InPawn != none )
{
HitDirection = Normal(HitDirection);
InstigatorRotation = InPawn.GetBaseAimRotation();
InstigatorFaceDir = GetRotatorAxis(InstigatorRotation, 0);
InstigatorRightDir = GetRotatorAxis(InstigatorRotation, 1);
// Cross the face direction of the instigator with the hit direction to find
// the normal to the "slashing" plane
SlashPlaneNormal = Normal(InstigatorFaceDir Cross HitDirection);
// Dot the slash plane normal with the world up direction to figure out
// the quadrant for the normal of the slash plane
UpDotSlash = vect(0,0,1) Dot SlashPlaneNormal;
UpThresholdValue = Abs(UpDotSlash);
// Dot the slash plane normal with the instigator right to figure out
// the direction of the slash
RightDotSlash = InstigatorRightDir Dot SlashPlaneNormal;
// Threshhold against the preset values to find out the type of slash. The sign (+ or -) of the
// dot products are used to further classify the direction of the slash
if( UpThresholdValue <= `COSINE_0_DEGREES && UpThresholdValue >= `COSINE_20_DEGREES )
{
if( UpDotSlash > 0 )
return DIR_Right;
else
return DIR_Left;
}
else if( UpThresholdValue <= `COSINE_20_DEGREES && UpThresholdValue >= `COSINE_70_DEGREES )
{
if( UpDotSlash < 0 && RightDotSlash > 0 )
return DIR_ForwardLeft;
else if( UpDotSlash > 0 && RightDotSlash > 0 )
return DIR_ForwardRight;
else if( UpDotSlash > 0 && RightDotSlash < 0 )
return DIR_BackwardRight;
else if( UpDotSlash < 0 && RightDotSlash < 0 )
return DIR_BackwardLeft;
}
else if( UpThresholdValue <= `COSINE_70_DEGREES && UpThresholdValue >= `COSINE_90_DEGREES )
{
if( RightDotSlash > 0 )
return DIR_Forward;
else
return DIR_Backward;
}
}
return DIR_None;
}
/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */
static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName)
{
local EPawnOctant SlashDir;
local KFCharacterInfo_Monster MonsterInfo;
MonsterInfo = InPawn.GetCharacterMonsterInfo();
if ( MonsterInfo == none )
{
return;
}
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
if( SlashDir == DIR_Forward || SlashDir == DIR_Backward )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Randomly pick the left or right shoulder bone and split the guy in half vertically
OutBoneName = Rand(2) == 0
? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName
: MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
else if( SlashDir == DIR_Left || SlashDir == DIR_Right )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach')
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit )
{
// Split the guy in half horizontally
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName;
}
}
}
else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
// ... and choose one of the shoulder constraints at random
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
}
else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
}
}
}
defaultproperties
{
EffectGroup=FXG_Sawblade
KDamageImpulse=1000
KDeathUpKick=800
KDeathVel=135
// Instigator damage can happen on owning client when projectile hits before Instigator is replicated and
// (Other != Instigator) == FALSE. This problem is specific to the eviscerator projectile since it's a
// replicated CSHD weapon, but it might make sense to have bNoInstigatorDamage=true on more weapons.
bNoInstigatorDamage=true
StunPower=0
StumblePower=100
GunHitPower=0
MeleeHitPower=100
WeaponDef=class'KFWeapDef_Eviscerator'
ModifierPerkList(0)=class'KFPerk_Berserker'
}