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

607 lines
14 KiB
Ucode

//=============================================================================
// KFWeap_MinigunBase
//=============================================================================
// Minigun base
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
//=============================================================================
class KFWeap_MinigunBase extends KFWeapon
abstract
native
nativereplication;
/* The minigun is winded up and ready to fire */
var bool bWindUpReady;
/* The zoom is active, keeps track of the current status of the zoom */
var bool bZoomActive;
/* Time used to wind up the weapon (also acts as the cooldown) */
var float WindUpActivationTime;
/* Control variable to check the current state of the wind up */
var transient float WindUpControlTime;
/* Rotation speed of the barrel when fully warmed up*/
var float WindUpRotationSpeed;
/* Rotation info of the barrel, controls the rotation for the selected bone via c++ */
var CylinderRotationInfo CylinderRotInfo;
/* The weapon is winding up */
var repnotify bool bWindUpModeActive;
/* The system stores the status of the winding up in case some animation interrupts the process */
var repnotify bool bStoredWindUpMode;
/* The weapon is firing and the barrels should be rotating */
var repnotify bool bFiringModeActive;
/* Replicated status of the rotation of the barrels */
var bool bReplicatedFiringModeActive;
/* Replicated rotation speed of the barrel when fully warmed up */
var repnotify float ReplicatedWindUpControlTime;
/* Rotation speed used in the player controller when the weapon is winding up but no firing */
var float WindUpViewRotationSpeed;
/* Pawn movement speed used when the weapon is winding up but no firing */
var float WindUpPawnMovementSpeed;
/* Rotation speed used in the player controller when the weapon is firing */
var float FiringViewRotationSpeed;
/* Pawn movement speed used when the weapon is firing */
var float FiringPawnMovementSpeed;
simulated event ReplicatedEvent(name VarName)
{
switch (VarName)
{
case nameof(bWindUpModeActive):
bReplicatedFiringModeActive = bWindUpModeActive || bFiringModeActive;
NotifyRotationState();
break;
case nameof(bStoredWindUpMode):
NotifyRotationState();
break;
case nameof(bFiringModeActive):
bReplicatedFiringModeActive = bWindUpModeActive || bFiringModeActive;
NotifyRotationState();
break;
case nameof(ReplicatedWindUpControlTime):
if( Instigator == none || !Instigator.IsLocallyControlled() )
{
WindUpControlTime = ReplicatedWindUpControlTime;
}
break;
}
}
replication
{
if (bNetDirty && Role == ROLE_Authority)
bWindUpModeActive, bStoredWindUpMode, bFiringModeActive, ReplicatedWindUpControlTime;
}
cpptext
{
// replication is coming boys
INT* GetOptimizedRepList( BYTE* InDefault, FPropertyRetirement* Retire, INT* Ptr, UPackageMap* Map, UActorChannel* Channel );
// cylinder is incrementally rotated
virtual void TickSpecial( FLOAT DeltaSeconds );
};
/** Cache Anim Nodes from the tree
* @note: skipped on server because AttachComponent/AttachWeaponTo is not called
*/
simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
{
super.PostInitAnimTree( SkelComp );
PostInitAnimTreeMinigun( SkelComp );
}
simulated event PostInitAnimTreeMinigun( SkeletalMeshComponent SkelComp )
{
CylinderRotInfo.Control = SkelControlSingleBone( SkelComp.FindSkelControl('CylinderControl') );
if( CylinderRotInfo.Control != none )
{
CylinderRotInfo.Control.SetSkelControlActive( true );
}
}
/* updates the cylinder rotation in Tick Special */
native simulated function UpdateCylinderRotation( out CylinderRotationInfo RotInfo, float Degrees );
/* function called from C++ to access perk time modifier when winding up */
simulated event float GetPerkFireRateModifier()
{
local KFPerk_Commando Perk;
Perk = KFPerk_Commando(GetPerk());
if( WorldInfo.TimeDilation < 1 && Perk != none )
{
return Perk.GetZedTimeModifierForWindUp();
}
return 0;
}
simulated function Activate()
{
Local KFPlayerController KFPC;
Local KFPlayerInput KFPI;
super.Activate();
if (!WeaponContentLoaded || Instigator == none)
{
return;
}
KFPC = KFPlayerController(Instigator.Controller);
if(KFPC != none && KFPC.PlayerInput != none)
{
KFPI = KFPlayerInput(KFPC.PlayerInput);
if(KFPI != none && KFPI.bIronsightsActive)
{
SetIronSights(true);
}
}
}
simulated event vector GetMuzzleLoc()
{
local Rotator ViewRotation;
if( Instigator != none )
{
ViewRotation = Instigator.GetViewRotation();
// Add in the free-aim rotation
if ( KFPlayerController(Instigator.Controller) != None )
{
ViewRotation += KFPlayerController(Instigator.Controller).WeaponBufferRotation;
}
return Instigator.GetPawnViewLocation() + (FireOffset >> ViewRotation);
}
return Location;
}
simulated function BeginFire(Byte FireModeNum)
{
if(FireModeNum == DEFAULT_FIREMODE)
{
bFiringModeActive = true;
bForceNetUpdate = true;
}
Super.BeginFire(FireModeNum);
}
simulated function EndFire(byte FireModeNum)
{
if(FireModeNum == DEFAULT_FIREMODE)
{
bFiringModeActive = false;
bForceNetUpdate = true;
}
Super.EndFire(FireModeNum);
}
/** If TRUE, Instigator/Owner moves at walking speed when this weapon is equipped */
simulated function bool ShouldOwnerWalk()
{
return IsFiring() && IsInState('WeaponFiring');
}
/** Disable the rotation of the barrels when sprinting */
simulated function SetWeaponSprint(bool bNewSprintStatus)
{
if(bNewSprintStatus && bWindUpModeActive)
{
return;
}
Super.SetWeaponSprint(bNewSprintStatus);
}
simulated function bool AllowSprinting()
{
return true;
}
/** Force iron sights as the default configuration is set to false */
simulated function bool AllowIronSights()
{
return true;
}
/** Used in KFPlayerInput to change the behaviour of the iron sight */
simulated function bool IsUsingSights()
{
return bWindUpModeActive;
}
/**
* Network: LocalPlayer
* Changes the functionality of the Iron sight
*/
simulated function SetIronSights(bool bNewIronSights)
{
if ( !Instigator.IsLocallyControlled() )
{
return;
}
ServerSetIronSights(bNewIronSights);
bStoredWindUpMode = bNewIronSights;
if(GetStateName() == 'Reloading')
{
WindUp(false);
UpdateZoom();
return;
}
PlayIdleAnim();
WindUp(bNewIronSights);
UpdateZoom();
bForceNetUpdate = true;
}
reliable server function ServerSetIronSights(bool bNewIronSights)
{
bStoredWindUpMode = bNewIronSights;
if(GetStateName() == 'Reloading')
{
WindUp(false);
UpdateZoom();
return;
}
WindUp(bNewIronSights);
UpdateZoom();
}
simulated function WindUp(bool bWindUpActive)
{
bWindUpModeActive = bWindUpActive;
NotifyRotationState();
}
/** Updates the rotation in the 3rd person character */
simulated function NotifyRotationState()
{
local KFPawn KFPawn;
local KFWeapAttach_Minigun KFWeapAttach;
KFPawn = KFPawn(Instigator);
KFWeapAttach = KFWeapAttach_Minigun(KFPawn.WeaponAttachment);
if(KFWeapAttach != none)
{
KFWeapAttach.UpdateWindUp(bReplicatedFiringModeActive || bWindUpModeActive || IsFiring());
}
}
/** Updates the zoom status (active when firing or winding up) */
simulated function UpdateZoom()
{
local bool bNewZoomStatus;
if ( !Instigator.IsLocallyControlled() )
{
return;
}
bNewZoomStatus = bWindUpModeActive || IsFiring();
if(bZoomActive == bNewZoomStatus)
{
return;
}
bZoomActive = bNewZoomStatus;
PerformZoom(bZoomActive);
}
simulated event OnZoomInFinished(){ }
simulated event OnZoomOutFinished(){ }
simulated event Tick( float DeltaTime )
{
local KFPawn_Human OwnerHuman;
local KFPlayerController OwnerController;
local float NewMovementSpeedMod;
local float NewRotationSpeedLimit;
local bool bLimitFiring, bLimitWindingUp;
Super.Tick(DeltaTime);
// Replicate WindUp time to simulated clients
if ( WorldInfo.NetMode == NM_DedicatedServer || WorldInfo.NetMode == NM_ListenServer )
{
ReplicatedWindUpControlTime = WindUpControlTime;
}
OwnerHuman = KFPawn_Human(Instigator);
if ( OwnerHuman != None )
{
OwnerController = KFPlayerController(OwnerHuman.Controller);
if( OwnerController != none )
{
bLimitFiring = IsFiring() && IsInState('WeaponFiring');
bLimitWindingUp = IsFiring() || bWindUpModeActive;
if( Role == Role_Authority )
{
NewMovementSpeedMod = MovementSpeedMod;
if ( bLimitFiring )
{
NewMovementSpeedMod = FiringPawnMovementSpeed;
}
else if( bLimitWindingUp )
{
NewMovementSpeedMod = WindUpPawnMovementSpeed;
}
else
{
NewMovementSpeedMod = 1;
}
if( NewMovementSpeedMod != MovementSpeedMod )
{
MovementSpeedMod = NewMovementSpeedMod;
OwnerHuman.UpdateGroundSpeed();
}
}
NewRotationSpeedLimit = OwnerController.RotationSpeedLimit;
if ( bLimitFiring )
{
NewRotationSpeedLimit = FiringViewRotationSpeed;
}
else if( bLimitWindingUp )
{
NewRotationSpeedLimit = WindUpViewRotationSpeed;
}
else
{
NewRotationSpeedLimit = 2000.0f;
}
if( NewRotationSpeedLimit != OwnerController.RotationSpeedLimit )
{
OwnerController.RotationSpeedLimit = NewRotationSpeedLimit;
}
}
}
}
simulated function NotifyBeginState()
{
Super.NotifyBeginState();
NotifyRotationState();
}
simulated function NotifyEndState()
{
Super.NotifyEndState();
NotifyRotationState();
}
/*********************************************************************************************
* State WeaponWindingUp
* The weapon is in this state to wind up and prepare for firing
*********************************************************************************************/
simulated state WeaponWindingUp
{
ignores AllowSprinting;
simulated event bool IsFiring()
{
return true;
}
simulated function BeginState(Name PrevStateName)
{
local KFPerk InstigatorPerk;
local int IdleIndex;
NotifyBeginState();
InstigatorPerk = GetPerk();
if( InstigatorPerk != none )
{
SetZedTimeResist( InstigatorPerk.GetZedTimeModifierForWindUp() );
}
UpdateZoom();
if ( Instigator.IsLocallyControlled() )
{
if ( IdleAnims.Length > 0 )
{
IdleIndex = Rand(IdleAnims.Length);
PlayAnimation(IdleAnims[IdleIndex], 0.0, true, 0.2);
}
StartIdleFidgetTimer();
ToggleAdditiveBobAnim(!bUsingSights);
}
if( bWindUpReady )
{
GoToState('WeaponFiring');
}
}
simulated function EndState(Name NextStateName)
{
NotifyEndState();
}
simulated event Tick(float DeltaTime)
{
Global.Tick(DeltaTime);
// Stop the looping fire sound if we're in zed time and want to play single fire sounds
if( bPlayingLoopingFireSnd && ShouldForceSingleFireSound() )
{
StopLoopingFireSound(CurrentFireMode);
}
if(bWindUpReady)
{
GoToState('WeaponFiring');
}
else if(!bFiringModeActive)
{
HandleFinishedFiring();
}
}
}
/*********************************************************************************************
* State WeaponFiring
* The weapon is in this state while holding fire button
*********************************************************************************************/
simulated state WeaponFiring
{
simulated event BeginState(Name PreviousStateName)
{
local KFPerk InstigatorPerk;
Super.BeginState(PreviousStateName);
InstigatorPerk = GetPerk();
if( InstigatorPerk != none )
{
SetZedTimeResist( InstigatorPerk.GetZedTimeModifierForWindUp() );
}
}
simulated function EndState(Name NextStateName)
{
Super.EndState(NextStateName);
UpdateZoom();
}
}
/*********************************************************************************************
* State MeleeAttackBasic
* We are doing a melee attack
*********************************************************************************************/
simulated state MeleeAttackBasic
{
ignores AllowSprinting, AllowIronSights;
simulated function BeginState(Name PreviousStateName)
{
local KFPerk InstigatorPerk;
InstigatorPerk = GetPerk();
if( InstigatorPerk != none )
{
SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
}
TimeWeaponFiring(CurrentFireMode);
NotifyBeginState();
}
}
/*********************************************************************************************
* State Active
* The weapon idle state (not firing, not reloading, ...)
*********************************************************************************************/
simulated state Active
{
/** Initialize the weapon as being active and ready to go. */
simulated event BeginState(Name PreviousStateName)
{
local KFPerk InstigatorPerk;
WindUp(bStoredWindUpMode);
UpdateZoom();
Super.BeginState(PreviousStateName);
InstigatorPerk = GetPerk();
if( InstigatorPerk != none )
{
SetZedTimeResist( InstigatorPerk.GetZedTimeModifierForWindUp() );
}
}
}
/*********************************************************************************************
* State GrenadeFiring
* Handles firing grenades.
*********************************************************************************************/
simulated state GrenadeFiring
{
simulated event bool IsFiring()
{
return false;
}
}
/** Called on local player when reload starts and replicated to server */
simulated function InitializeReload()
{
WindUp(false);
bZoomActive = false;
Super.InitializeReload();
}
reliable server function ServerSendToReload(byte ClientReloadAmount)
{
Super.ServerSendToReload(ClientReloadAmount);
WindUp(false);
bZoomActive = false;
}
defaultproperties
{
// Wind Up variables
WindUpActivationTime=1.5
WindUpRotationSpeed=200
bHasIronSights=false
bKeepIronSightsOnJump=true
bSkipZoomInRotation=true
FireSightedAnims[0]=Shoot
FireLastSightedAnim=Shoot_Last
FireLoopSightedAnim=ShootLoop
FireLoopEndLastSightedAnim=ShootLoop_End_Last
IdleSightedAnims(0)=Idle
FireLoopStartSightedAnim=ShootLoop_Start
FireLoopEndSightedAnim=ShootLoop_End
bAlwaysRelevant=True
bOnlyRelevantToOwner=False
WindUpViewRotationSpeed=2000 // base rotation
WindUpPawnMovementSpeed=1 // base speed
FiringViewRotationSpeed=2000
FiringPawnMovementSpeed=0.75f
}