upload
This commit is contained in:
@ -24,4 +24,7 @@ defaultproperties
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Commando'
|
||||
|
||||
bCanZedTime=false
|
||||
bCanEnrage=false
|
||||
}
|
||||
|
30
KFGameContent/Classes/KFDT_Ballistic_HRG_Warthog.uc
Normal file
30
KFGameContent/Classes/KFDT_Ballistic_HRG_Warthog.uc
Normal file
@ -0,0 +1,30 @@
|
||||
//=============================================================================
|
||||
// KFDT_Ballistic_HRG_Warthog
|
||||
//=============================================================================
|
||||
// Class Description
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Ballistic_HRG_Warthog extends KFDT_Ballistic_Shell
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
KDamageImpulse=2000
|
||||
KDeathUpKick=750
|
||||
KDeathVel=350
|
||||
|
||||
KnockdownPower=125
|
||||
StumblePower=340
|
||||
GunHitPower=275
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_Warthog'
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
bCanZedTime=false
|
||||
}
|
53
KFGameContent/Classes/KFDT_Ballistic_Shotgun_S12.uc
Normal file
53
KFGameContent/Classes/KFDT_Ballistic_Shotgun_S12.uc
Normal file
@ -0,0 +1,53 @@
|
||||
//=============================================================================
|
||||
// KFDT_Ballistic_Shotgun_S12
|
||||
//=============================================================================
|
||||
// Damage type class for the S12 shotgun
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Ballistic_Shotgun_S12 extends KFDT_Ballistic_Shotgun
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
/** Allows the damage type to customize exactly which hit zones it can dismember */
|
||||
static simulated function bool CanDismemberHitZone( name InHitZoneName )
|
||||
{
|
||||
if( super.CanDismemberHitZone( InHitZoneName ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ( InHitZoneName )
|
||||
{
|
||||
case 'lupperarm':
|
||||
case 'rupperarm':
|
||||
case 'chest':
|
||||
case 'heart':
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
BloodSpread=0.4
|
||||
BloodScale=0.6
|
||||
|
||||
|
||||
KDamageImpulse=900
|
||||
KDeathUpKick=-500
|
||||
KDeathVel=350
|
||||
//KDamageImpulse=350
|
||||
//KDeathUpKick=120
|
||||
//KDeathVel=10
|
||||
|
||||
StumblePower=5
|
||||
GunHitPower=0
|
||||
|
||||
ModifierPerkList(0)=class'KFPerk_Support'
|
||||
|
||||
WeaponDef=class'KFWeapDef_Shotgun_S12'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_Warthog.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_HRG_Warthog.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_HRG_Warthog
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_HRG_Warthog extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_HRG_Warthog'
|
||||
}
|
16
KFGameContent/Classes/KFDT_Bludgeon_Shotgun_S12.uc
Normal file
16
KFGameContent/Classes/KFDT_Bludgeon_Shotgun_S12.uc
Normal file
@ -0,0 +1,16 @@
|
||||
//=============================================================================
|
||||
// KFDT_Bludgeon_Shotgun_S12
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Bludgeon_Shotgun_S12 extends KFDT_Bludgeon_RifleButt
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
//defaults
|
||||
WeaponDef=class'KFWeapDef_Shotgun_S12'
|
||||
}
|
@ -24,7 +24,9 @@ defaultproperties
|
||||
KnockdownPower = 100
|
||||
StumblePower = 300
|
||||
|
||||
|
||||
WeaponDef=class'KFWeapDef_AutoTurret'
|
||||
ModifierPerkList(0)=class'KFPerk_Commando'
|
||||
|
||||
bCanZedTime=false
|
||||
bCanEnrage=false
|
||||
}
|
||||
|
32
KFGameContent/Classes/KFDT_Explosive_HRG_Warthog.uc
Normal file
32
KFGameContent/Classes/KFDT_Explosive_HRG_Warthog.uc
Normal file
@ -0,0 +1,32 @@
|
||||
//=============================================================================
|
||||
// KFDT_Explosive_HRG_Warthog
|
||||
//=============================================================================
|
||||
// Explosive damage type for HRG Warthog explosion
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Explosive_HRG_Warthog extends KFDT_Explosive
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldSpawnPersistentBlood = true
|
||||
|
||||
// physics impact
|
||||
RadialDamageImpulse = 2000
|
||||
GibImpulseScale = 0.15
|
||||
KDeathUpKick = 1000
|
||||
KDeathVel = 300
|
||||
|
||||
KnockdownPower = 50
|
||||
StumblePower = 150
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_Warthog'
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
bCanZedTime=false
|
||||
bCanEnrage=false
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
//=============================================================================
|
||||
// KFDT_Explosive_HRG_Warthog_HighExplosive
|
||||
//=============================================================================
|
||||
// Explosive damage type for HRG Warthog Projectile Explosion
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Explosive_HRG_Warthog_HighExplosive extends KFDT_Explosive
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldSpawnPersistentBlood = true
|
||||
|
||||
// physics impact
|
||||
RadialDamageImpulse = 2000
|
||||
GibImpulseScale = 0.15
|
||||
KDeathUpKick = 1000
|
||||
KDeathVel = 300
|
||||
|
||||
KnockdownPower = 50
|
||||
StumblePower = 150
|
||||
|
||||
WeaponDef=class'KFWeapDef_HRG_Warthog'
|
||||
ModifierPerkList(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
bCanZedTime=false
|
||||
bCanEnrage=false
|
||||
}
|
39
KFGameContent/Classes/KFDT_Explosive_Shotgun_S12.uc
Normal file
39
KFGameContent/Classes/KFDT_Explosive_Shotgun_S12.uc
Normal file
@ -0,0 +1,39 @@
|
||||
//=============================================================================
|
||||
// KFDT_Explosive_Shotgun_S12
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFDT_Explosive_Shotgun_S12 extends KFDT_EMP
|
||||
abstract
|
||||
hidedropdown;
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bShouldSpawnPersistentBlood=true
|
||||
|
||||
// physics impact
|
||||
RadialDamageImpulse=3000 //5000 //20000
|
||||
GibImpulseScale=0.15
|
||||
KDeathUpKick=1000
|
||||
KDeathVel=300
|
||||
|
||||
// unreal physics momentum
|
||||
bExtraMomentumZ=True
|
||||
|
||||
bCanGib=true
|
||||
|
||||
KnockdownPower=100
|
||||
StunPower=25
|
||||
StumblePower=200
|
||||
EMPPower=100
|
||||
|
||||
//Perk
|
||||
ModifierPerkList(0)=class'KFPerk_Support'
|
||||
|
||||
WeaponDef=class'KFWeapDef_Shotgun_S12'
|
||||
|
||||
bCanApplyRadialCalculationtoAffliction=false
|
||||
}
|
36
KFGameContent/Classes/KFExplosion_HRG_Warthog.uc
Normal file
36
KFGameContent/Classes/KFExplosion_HRG_Warthog.uc
Normal file
@ -0,0 +1,36 @@
|
||||
//=============================================================================
|
||||
// KFExplosion_HRG_Warthog
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFExplosion_HRG_Warthog extends KFExplosionActor;
|
||||
|
||||
var private int HealingValue;
|
||||
|
||||
// Disable Knockdown for friendlies
|
||||
protected function bool KnockdownPawn(BaseAiPawn Victim, float DistFromExplosion)
|
||||
{
|
||||
if (Victim.GetTeamNum() != Instigator.GetTeamNum())
|
||||
{
|
||||
return Super.KnockdownPawn(Victim, DistFromExplosion);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable Stumble for friendlies
|
||||
protected function bool StumblePawn(BaseAiPawn Victim, float DistFromExplosion)
|
||||
{
|
||||
if (Victim.GetTeamNum() != Instigator.GetTeamNum())
|
||||
{
|
||||
return Super.StumblePawn(Victim, DistFromExplosion);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
}
|
@ -882,12 +882,33 @@ function StartWave()
|
||||
WaveNum++;
|
||||
MyKFGRI.WaveNum = WaveNum;
|
||||
|
||||
if (IsMapObjectiveEnabled())
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
MyKFGRI.ClearPreviousObjective();
|
||||
if (MyKFGRI.StartNextObjective())
|
||||
if (WaveNum == 1) // Only on first wave..
|
||||
{
|
||||
WaveBuffer = ObjectiveSpawnDelay;
|
||||
MyKFGRI.ChooseNextObjective(WaveNum);
|
||||
}
|
||||
|
||||
MyKFGRI.ClearPreviousObjective();
|
||||
|
||||
if (WaveNum != WaveMax)
|
||||
{
|
||||
if (MyKFGRI.StartNextObjective())
|
||||
{
|
||||
WaveBuffer = ObjectiveSpawnDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsMapObjectiveEnabled())
|
||||
{
|
||||
MyKFGRI.ClearPreviousObjective();
|
||||
|
||||
if (MyKFGRI.StartNextObjective())
|
||||
{
|
||||
WaveBuffer = ObjectiveSpawnDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,32 @@ var array<PerkRoulette_PlayerMessageDelegate> PerkRoulette_PlayersDelegateData;
|
||||
|
||||
var array<KFPlayerController_WeeklySurvival> PerkRoulette_PlayersDelegateInventory;
|
||||
|
||||
struct ContaminationModeData
|
||||
{
|
||||
var() float FirstWaveInitialTimer;
|
||||
var() float WaveInitialTimer;
|
||||
var() float WaveCurrentTimer;
|
||||
var() float GraceTimer; // We store on each Player the GraceCurrentTimer
|
||||
var() float DamageTimer;
|
||||
var() float DamageCurrentTimer;
|
||||
var() bool ObjectiveHidden;
|
||||
var() bool CanUpdate;
|
||||
|
||||
structdefaultproperties
|
||||
{
|
||||
FirstWaveInitialTimer = 45.f
|
||||
WaveInitialTimer = 30.f
|
||||
WaveCurrentTimer = 0.f
|
||||
GraceTimer = 5.f
|
||||
DamageTimer = 1.f
|
||||
DamageCurrentTimer = 0.f
|
||||
ObjectiveHidden = false
|
||||
CanUpdate = false
|
||||
}
|
||||
};
|
||||
|
||||
var ContaminationModeData ContaminationMode;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Statics
|
||||
static event class<GameInfo> SetGameType(string MapName, string Options, string Portal)
|
||||
@ -538,6 +564,18 @@ function Tick(float DeltaTime)
|
||||
// This deals with players joining at any time (lobby, or in wave)
|
||||
ChooseRandomPerks(false);
|
||||
}
|
||||
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
if (ContaminationMode.CanUpdate)
|
||||
{
|
||||
UpdateContaminationMode(DeltaTime);
|
||||
}
|
||||
else if (WaveNum < (WaveMax - 1))
|
||||
{
|
||||
UpdateContaminationModeTrader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function TickZedTime( float DeltaTime )
|
||||
@ -576,6 +614,11 @@ function WaveEnded(EWaveEndCondition WinCondition)
|
||||
ChooseRandomPerks(true);
|
||||
}
|
||||
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
ContaminationMode.CanUpdate = false;
|
||||
}
|
||||
|
||||
super.WaveEnded(WinCondition);
|
||||
|
||||
if (OutbreakEvent.ActiveEvent.bPermanentZedTime && ZedTimeRemaining > ZedTimeBlendOutTime)
|
||||
@ -614,6 +657,19 @@ function GrantExtraDoshOnWaveWon()
|
||||
KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).AddDosh(ExtraDosh, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
ExtraDosh = MyKFGRI.ContaminationModeExtraDosh();
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
if (KFPC.IsInState('Spectating') == false
|
||||
&& KFPC.PlayerReplicationInfo.bOnlySpectator == false)
|
||||
{
|
||||
KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).AddDosh(ExtraDosh, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ClearZedTimePCTimers()
|
||||
@ -687,6 +743,22 @@ function StartWave()
|
||||
{
|
||||
OverridePickupList();
|
||||
}
|
||||
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
if (WaveNum == 1)
|
||||
{
|
||||
ContaminationMode.WaveCurrentTimer = ContaminationMode.FirstWaveInitialTimer;
|
||||
}
|
||||
else
|
||||
{
|
||||
ContaminationMode.WaveCurrentTimer = ContaminationMode.WaveInitialTimer;
|
||||
}
|
||||
|
||||
ContaminationMode.DamageCurrentTimer = ContaminationMode.DamageTimer;
|
||||
ContaminationMode.ObjectiveHidden = false;
|
||||
ContaminationMode.CanUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
function bool OverridePickupList()
|
||||
@ -1187,6 +1259,14 @@ function NotifyKilled(Controller Killer, Controller Killed, Pawn KilledPawn, cla
|
||||
PerkRoulette_PlayersDelegateInventory.AddItem(KFPC_WS_Killed);
|
||||
}
|
||||
}
|
||||
|
||||
if (MyKFGRI.IsContaminationMode())
|
||||
{
|
||||
if (KFPC_WS_Killed != none)
|
||||
{
|
||||
KFPC_WS_Killed.HideContaminationMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function GunGameLevelGrantWeapon(KFPlayerController_WeeklySurvival KFPC_WS, class<KFWeaponDefinition> ToGrantWeaponDefinition)
|
||||
@ -1827,6 +1907,189 @@ function BroadcastCustomDelegate()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Weekly 19: Contamination Mode
|
||||
*/
|
||||
|
||||
function UpdatePlayersState(KFMapObjective_DoshHold Area
|
||||
, out array<KFPlayerController_WeeklySurvival> ValidPlayers
|
||||
, out array<KFPlayerController_WeeklySurvival> PlayersInsideArea
|
||||
, out array<KFPlayerController_WeeklySurvival> PlayersOutsideArea)
|
||||
{
|
||||
local KFPlayerController_WeeklySurvival KFPC_WS;
|
||||
local int i;
|
||||
|
||||
// Get available players
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
|
||||
{
|
||||
if (KFPC_WS.Pawn.IsAliveAndWell() == false
|
||||
|| KFPC_WS.PlayerReplicationInfo.bOnlySpectator
|
||||
|| KFPC_WS.IsInState('Spectating'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ValidPlayers.AddItem(KFPC_WS);
|
||||
}
|
||||
|
||||
// Update who's in and who's out
|
||||
for (i = 0 ; i < ValidPlayers.Length ; ++i)
|
||||
{
|
||||
// If is inside..
|
||||
if (Area.TouchingHumans.Find(KFPawn_Human(ValidPlayers[i].Pawn)) != INDEX_NONE)
|
||||
{
|
||||
PlayersInsideArea.AddItem(ValidPlayers[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayersOutsideArea.AddItem(ValidPlayers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateContaminationModeTrader()
|
||||
{
|
||||
local KFMapObjective_DoshHold Area;
|
||||
local array<KFPlayerController_WeeklySurvival> ValidPlayers, PlayersInsideArea, PlayersOutsideArea;
|
||||
local int i;
|
||||
|
||||
Area = KFMapObjective_DoshHold(MyKFGRI.NextObjective);
|
||||
|
||||
if (Area != none)
|
||||
{
|
||||
UpdatePlayersState(Area, ValidPlayers, PlayersInsideArea, PlayersOutsideArea);
|
||||
|
||||
for (i = 0 ; i < PlayersInsideArea.Length ; ++i)
|
||||
{
|
||||
PlayersInsideArea[i].ShowContaminationMode();
|
||||
|
||||
PlayersInsideArea[i].UpdateContaminationModeWidget(true);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < PlayersOutsideArea.Length ; ++i)
|
||||
{
|
||||
PlayersOutsideArea[i].ShowContaminationMode();
|
||||
|
||||
PlayersOutsideArea[i].ContaminationModePlayerIsInside = false;
|
||||
PlayersOutsideArea[i].UpdateContaminationModeWidget_Timer(ContaminationMode.WaveInitialTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateContaminationMode(float DeltaTime)
|
||||
{
|
||||
local KFMapObjective_DoshHold Area;
|
||||
local array<KFPlayerController_WeeklySurvival> ValidPlayers, PlayersInsideArea, PlayersOutsideArea;
|
||||
local KFPlayerController_WeeklySurvival KFPC_WS;
|
||||
local int i;
|
||||
local bool CheckPlayersInArea, CanApplyDamage;
|
||||
|
||||
CheckPlayersInArea = false;
|
||||
|
||||
// Update wave timer..
|
||||
if (ContaminationMode.WaveCurrentTimer > 0.f)
|
||||
{
|
||||
ContaminationMode.WaveCurrentTimer -= DeltaTime;
|
||||
}
|
||||
|
||||
if (MyKFGRI.CurrentObjective != none)
|
||||
{
|
||||
foreach WorldInfo.AllActors(class'KFMapObjective_DoshHold', Area)
|
||||
{
|
||||
if (Area.IsActive())
|
||||
{
|
||||
CheckPlayersInArea = true;
|
||||
|
||||
UpdatePlayersState(Area, ValidPlayers, PlayersInsideArea, PlayersOutsideArea);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a valid area an objective..
|
||||
if (CheckPlayersInArea && WaveNum != WaveMax)
|
||||
{
|
||||
// Trigger logic depending on state of game
|
||||
|
||||
if (ContaminationMode.WaveCurrentTimer > 0.f)
|
||||
{
|
||||
// If we are still on safe time to reach area, we can only notify Player if you are inside or outside, no Grace Timer, and No Damage applied
|
||||
|
||||
for (i = 0 ; i < PlayersInsideArea.Length ; ++i)
|
||||
{
|
||||
PlayersInsideArea[i].UpdateContaminationModeWidget(true);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < PlayersOutsideArea.Length ; ++i)
|
||||
{
|
||||
PlayersOutsideArea[i].ContaminationModePlayerIsInside = false;
|
||||
PlayersOutsideArea[i].UpdateContaminationModeWidget_Timer(ContaminationMode.WaveCurrentTimer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If Time finished, we must Damage Players that are outside (use Grace Timer)
|
||||
|
||||
if (ContaminationMode.DamageCurrentTimer > 0.f)
|
||||
{
|
||||
ContaminationMode.DamageCurrentTimer -= DeltaTime;
|
||||
}
|
||||
|
||||
CanApplyDamage = ContaminationMode.DamageCurrentTimer <= 0.f;
|
||||
|
||||
// Reset damage tick
|
||||
if (CanApplyDamage)
|
||||
{
|
||||
ContaminationMode.DamageCurrentTimer = ContaminationMode.DamageTimer;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < PlayersInsideArea.Length ; ++i)
|
||||
{
|
||||
PlayersInsideArea[i].ContaminationModeGraceCurrentTimer = ContaminationMode.GraceTimer;
|
||||
|
||||
PlayersInsideArea[i].UpdateContaminationModeWidget(true);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < PlayersOutsideArea.Length ; ++i)
|
||||
{
|
||||
if (PlayersOutsideArea[i].ContaminationModeGraceCurrentTimer > 0.f)
|
||||
{
|
||||
PlayersOutsideArea[i].ContaminationModeGraceCurrentTimer -= DeltaTime;
|
||||
}
|
||||
|
||||
PlayersOutsideArea[i].UpdateContaminationModeWidget(false);
|
||||
|
||||
if (CanApplyDamage && PlayersOutsideArea[i].ContaminationModeGraceCurrentTimer <= 0.f)
|
||||
{
|
||||
PlayersOutsideArea[i].Pawn.TakeDamage(class'KFDT_WeeklyContamination'.static.GetDamage(), none, vect(0,0,0), vect(0,0,0), class'KFDT_WeeklyContamination');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide UIs if no more objective
|
||||
|
||||
if (ContaminationMode.ObjectiveHidden == false)
|
||||
{
|
||||
ContaminationMode.ObjectiveHidden = true;
|
||||
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
|
||||
{
|
||||
if (KFPC_WS.Pawn.IsAliveAndWell() == false
|
||||
|| KFPC_WS.PlayerReplicationInfo.bOnlySpectator
|
||||
|| KFPC_WS.IsInState('Spectating'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
KFPC_WS.HideContaminationMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
defaultproperties
|
||||
|
@ -62,6 +62,25 @@ simulated function NotifyWaveStart()
|
||||
super.NotifyWaveStart();
|
||||
}
|
||||
|
||||
function ChooseNextObjective(int NextWaveNum)
|
||||
{
|
||||
local KFMapInfo KFMI;
|
||||
|
||||
if (IsContaminationMode() == false)
|
||||
{
|
||||
super.ChooseNextObjective(NextWaveNum);
|
||||
}
|
||||
|
||||
KFMI = KFMapInfo(WorldInfo.GetMapInfo());
|
||||
|
||||
if (KFMI != none && NextWaveNum != WaveMax)
|
||||
{
|
||||
bForceNextObjective = true; // this overrides the objective chance, so it just chooses randomnly between all them
|
||||
|
||||
ChooseNextRandomObjective(KFMI, NextWaveNum, false);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultProperties
|
||||
{
|
||||
bIsWeeklyMode=True
|
||||
|
@ -95,7 +95,7 @@ simulated function AddToOwnerArray()
|
||||
}
|
||||
}
|
||||
|
||||
simulated function TakeRadiusDamage(Controller InstigatedBy, float BaseDamage, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HurtOrigin, bool bFullDamage, Actor DamageCauser, optional float DamageFalloffExponent = 1.f)
|
||||
simulated function TakeRadiusDamage(Controller InstigatedBy, float BaseDamage, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HurtOrigin, bool bFullDamage, Actor DamageCauser, optional float DamageFalloffExponent = 1.f, optional bool bAdjustRadiusDamage=true)
|
||||
{
|
||||
if (!bIgnoreRadiusDamage || AcceptedDamageTypes.Find(DamageType) != INDEX_NONE)
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ var() float RemindPlayersTime;
|
||||
var transient float PrevWaveProgress;
|
||||
var transient bool bRemindPlayers;
|
||||
|
||||
var Texture2D ContaminationIcon;
|
||||
|
||||
simulated event ReplicatedEvent(name VarName)
|
||||
{
|
||||
@ -125,11 +126,95 @@ event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vecto
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool ShouldDrawIcon()
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
if (WorldInfo != None && WorldInfo.Game != none && WorldInfo.Game.GameReplicationInfo != none)
|
||||
{
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI != none && KFGRI.IsContaminationMode())
|
||||
{
|
||||
return KFGRI.AIRemaining > KFGRI.ContaminationModeZedsToFinish();
|
||||
}
|
||||
}
|
||||
|
||||
return Super.ShouldDrawIcon();
|
||||
}
|
||||
|
||||
simulated function GrantReward(KFPlayerReplicationInfo KFPRI, KFPlayerController KFPC)
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
Super.GrantReward(KFPRI, KFPC);
|
||||
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFGRI.IsContaminationMode() == false)
|
||||
{
|
||||
if (KFPRI == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFPRI.bOnlySpectator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFPC != none)
|
||||
{
|
||||
// Summer 2023 objective
|
||||
KFPC.ClientOnTryCompleteObjective(3, SEI_Summer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function NotifyZedKilled(Controller Killer, Pawn KilledPawn, bool bIsBoss)
|
||||
{
|
||||
local int i;
|
||||
local KFGameInfo KFGI;
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
local KFPlayerController KFPC;
|
||||
local KFPlayerReplicationInfo KFPRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI != none && KFGRI.IsContaminationMode())
|
||||
{
|
||||
if (ROLE == Role_Authority)
|
||||
{
|
||||
if (bActive)
|
||||
{
|
||||
if (KFGRI.AIRemaining <= KFGRI.ContaminationModeZedsToFinish())
|
||||
{
|
||||
DeactivateObjective();
|
||||
|
||||
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
|
||||
{
|
||||
if (KFPC != none)
|
||||
{
|
||||
KFPRI = KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo);
|
||||
|
||||
if (KFPRI != none && KFPRI.bOnlySpectator == false)
|
||||
{
|
||||
// Summer 2023 objective
|
||||
KFPC.ClientOnTryCompleteObjective(3, SEI_Summer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ROLE == Role_Authority)
|
||||
{
|
||||
@ -144,7 +229,6 @@ function NotifyZedKilled(Controller Killer, Pawn KilledPawn, bool bIsBoss)
|
||||
{
|
||||
if (RewardPerZed == 0)
|
||||
{
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
RewardPerZed = GetMaxDoshReward() / (PctOfWaveZedsKilledForMaxReward * KFGRI.WaveTotalAICount);
|
||||
}
|
||||
CurrentRewardAmount = FMin(CurrentRewardAmount + RewardPerZed, float(GetMaxDoshReward()));
|
||||
@ -237,6 +321,16 @@ function StartPenaltyCheck()
|
||||
|
||||
function ActivationVO()
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI != none && KFGRI.IsContaminationMode())
|
||||
{
|
||||
PlaySoundBase(AkEvent'WW_VOX_NPC_Trader.Play_Trader_DEFA_Area', false, WorldInfo.NetMode == NM_DedicatedServer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ActivationSoundEventOverride != none)
|
||||
{
|
||||
PlaySoundBase(ActivationSoundEventOverride, false, WorldInfo.NetMode == NM_DedicatedServer);
|
||||
@ -373,6 +467,15 @@ simulated function DeactivateObjective()
|
||||
|
||||
function PlayDeactivationDialog()
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI != none && KFGRI.IsContaminationMode())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentRewardAmount <= 0)
|
||||
{
|
||||
if (FailureSoundEventOverride != none)
|
||||
@ -499,6 +602,23 @@ simulated function bool ShouldShowObjectiveHUD()
|
||||
return !IsComplete();
|
||||
}
|
||||
|
||||
simulated function Texture2D GetIcon()
|
||||
{
|
||||
local KFGameReplicationInfo KFGRI;
|
||||
|
||||
if (WorldInfo != None && WorldInfo.Game != none && WorldInfo.Game.GameReplicationInfo != none)
|
||||
{
|
||||
KFGRI = KFGameReplicationInfo(WorldInfo.Game.GameReplicationInfo);
|
||||
|
||||
if (KFGRI != none && KFGRI.IsContaminationMode())
|
||||
{
|
||||
return ContaminationIcon;
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectiveIcon;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
DescriptionLocKey="DescriptionDoshHold"
|
||||
@ -561,7 +681,7 @@ defaultproperties
|
||||
ZedThresholds[5]=0
|
||||
|
||||
ObjectiveIcon=Texture2D'Objectives_UI.UI_Objectives_ObjectiveMode'
|
||||
|
||||
ContaminationIcon=Texture2D'Objectives_UI.UI_Objectives_Xmas_DefendObj'
|
||||
RemindPlayersTime=30.f
|
||||
bUseEarlyTrail=false
|
||||
|
||||
|
@ -1235,6 +1235,21 @@ defaultproperties
|
||||
)}
|
||||
)}
|
||||
|
||||
// Contamination Mode
|
||||
SetEvents[19]={(
|
||||
EventDifficulty=2,
|
||||
GameLength=GL_Normal,
|
||||
ContaminationModeZedsToFinish=5,
|
||||
ContaminationModeExtraDosh=200,
|
||||
SpawnReplacementList={(
|
||||
(SpawnEntry=AT_EliteCrawler,NewClass=(class'KFGameContent.KFPawn_ZedGorefast'),PercentChance=0.9),
|
||||
(SpawnEntry=AT_Siren,NewClass=(class'KFGameContent.KFPawn_ZedDAR_Laser'),PercentChance=0.2),
|
||||
(SpawnEntry=AT_Bloat,NewClass=(class'KFGameContent.KFPawn_ZedDAR_Rocket'),PercentChance=0.2)
|
||||
|
||||
)}
|
||||
|
||||
|
||||
)}
|
||||
//Test events from here down. These don't end up in the regular rotation.
|
||||
// The override ID starts from one higher than the last SetEvents entry above.
|
||||
// Ex: Big head = 7, Horde = 8
|
||||
|
@ -105,6 +105,9 @@ const NoAmmoSocketName = 'malfunction';
|
||||
const NoAmmoFXTemplate = ParticleSystem'WEP_AutoTurret_EMIT.FX_NoAmmo_Sparks';
|
||||
var transient ParticleSystemComponent NoAmmoFX;
|
||||
|
||||
var transient vector DeployLastLocation;
|
||||
var transient float LastMoveExpectedSize;
|
||||
|
||||
replication
|
||||
{
|
||||
if( bNetDirty )
|
||||
@ -374,7 +377,7 @@ simulated state Deploy
|
||||
SetTimer(AnimDuration, false, nameof(StartIdleAnim));
|
||||
}
|
||||
|
||||
SetPhysics(PHYS_FLYING);
|
||||
SetPhysics(PHYS_NONE);
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
@ -390,22 +393,33 @@ simulated state Deploy
|
||||
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
// If we didn't move..
|
||||
if (VSize(Location - DeployLastLocation) < (LastMoveExpectedSize * 0.8f))
|
||||
{
|
||||
SetTurretState(ETS_TargetSearch);
|
||||
return;
|
||||
}
|
||||
|
||||
LocationNext = Location;
|
||||
LocationNext.z += Velocity.z * DeltaTime;
|
||||
|
||||
// If there's little to no movement or we are going to collide
|
||||
if (Velocity.z <= 0.01f || !FastTrace(LocationNext, Location, vect(25,25,25)))
|
||||
// If we are going to collide stop
|
||||
if (!FastTrace(LocationNext, Location, vect(25,25,25)))
|
||||
{
|
||||
SetTurretState(ETS_TargetSearch);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
DeployLastLocation = Location;
|
||||
LastMoveExpectedSize = VSize(LocationNext - Location);
|
||||
|
||||
SetLocation(LocationNext);
|
||||
|
||||
// Check height to change state
|
||||
CurrentHeight = Location.Z - GroundLocation.Z;
|
||||
if (CurrentHeight >= DeployHeight)
|
||||
{
|
||||
// Check height to change state
|
||||
CurrentHeight = Location.Z - GroundLocation.Z;
|
||||
if (CurrentHeight >= DeployHeight)
|
||||
{
|
||||
SetTurretState(ETS_TargetSearch);
|
||||
}
|
||||
SetTurretState(ETS_TargetSearch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,6 +439,8 @@ simulated state Deploy
|
||||
SetTimer(0.25f, true, nameof(CheckEnemiesWithinExplosionRadius));
|
||||
}
|
||||
}
|
||||
|
||||
SetPhysics(PHYS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,6 +549,8 @@ simulated state Combat
|
||||
|
||||
local float NewAmmoPercentage;
|
||||
|
||||
local bool bIsSpotted;
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
TurretWeapon.GetMuzzleLocAndRot(MuzzleLoc, MuzzleRot);
|
||||
@ -565,11 +583,14 @@ simulated state Combat
|
||||
// Trace from the Target reference to MuzzleLoc, because MuzzleLoc could be already inside physics, as it's outside the collider of the Drone!
|
||||
HitActor = Trace(HitLocation, HitNormal, EnemyTarget.Mesh.GetBoneLocation('Spine1'), MuzzleLoc,,,,TRACEFLAG_Bullet);
|
||||
|
||||
/** Search for new enemies if current is dead, cloaked or too far, or something between the drone and the target except a player */
|
||||
// Visible by local player or team
|
||||
bIsSpotted = (EnemyTarget.bIsCloakingSpottedByLP || EnemyTarget.bIsCloakingSpottedByTeam);
|
||||
|
||||
/** Search for new enemies if current is dead, cloaked or too far, or something between the drone that's world geometry */
|
||||
if (!EnemyTarget.IsAliveAndWell()
|
||||
|| EnemyTarget.bIsCloaking
|
||||
|| (EnemyTarget.bIsCloaking && bIsSpotted == false)
|
||||
|| VSizeSq(EnemyTarget.Location - Location) > EffectiveRadius * EffectiveRadius
|
||||
|| (HitActor != none && KFPawn_Monster(HitActor) == none && KFPawn_Human(HitActor) == none))
|
||||
|| (HitActor != none && HitActor.bWorldGeometry && KFFracturedMeshGlass(HitActor) == None))
|
||||
{
|
||||
EnemyTarget = none;
|
||||
CheckForTargets();
|
||||
@ -590,13 +611,13 @@ simulated state Combat
|
||||
|
||||
RotateBySpeed(DesiredRotationRot);
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
if (Role == ROLE_Authority && ReachedRotation())
|
||||
{
|
||||
HitActor = Trace(HitLocation, HitNormal, MuzzleLoc + vector(Rotation) * EffectiveRadius, MuzzleLoc, , , HitInfo, TRACEFLAG_Bullet);
|
||||
|
||||
if (TurretWeapon != none)
|
||||
{
|
||||
if (KFPawn_Monster(HitActor) != none)
|
||||
if (HitActor != none && HitActor.bWorldGeometry == false)
|
||||
{
|
||||
TurretWeapon.Fire();
|
||||
|
||||
@ -641,6 +662,7 @@ simulated state Detonate
|
||||
{
|
||||
ExploActor.InstigatorController = Instigator.Controller;
|
||||
ExploActor.Instigator = Instigator;
|
||||
ExploActor.bIgnoreInstigator = true;
|
||||
|
||||
ExploActor.Explode(ExplosionTemplate);
|
||||
}
|
||||
@ -732,6 +754,8 @@ function CheckForTargets()
|
||||
local vector HitLocation, HitNormal;
|
||||
local Actor HitActor;
|
||||
|
||||
local bool bIsSpotted;
|
||||
|
||||
if (EnemyTarget != none)
|
||||
{
|
||||
CurrentDistance = VSizeSq(Location - EnemyTarget.Location);
|
||||
@ -745,10 +769,19 @@ function CheckForTargets()
|
||||
|
||||
foreach CollidingActors(class'KFPawn_Monster', CurrentTarget, EffectiveRadius, Location, true,, HitInfo)
|
||||
{
|
||||
// Visible by local player or team
|
||||
bIsSpotted = (CurrentTarget.bIsCloakingSpottedByLP || CurrentTarget.bIsCloakingSpottedByTeam);
|
||||
|
||||
if (!CurrentTarget.IsAliveAndWell()
|
||||
|| (CurrentTarget.bIsCloaking && bIsSpotted == false))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Trace from the Target reference to MuzzleLoc, because MuzzleLoc could be already inside physics, as it's outside the collider of the Drone!
|
||||
HitActor = Trace(HitLocation, HitNormal, CurrentTarget.Mesh.GetBoneLocation('Spine1'), MuzzleLoc,,,,TRACEFLAG_Bullet);
|
||||
|
||||
if (!CurrentTarget.IsAliveAndWell() || CurrentTarget.bIsCloaking || HitActor == none || KFPawn_Monster(HitActor) == none)
|
||||
if (HitActor == none || (HitActor.bWorldGeometry && KFFracturedMeshGlass(HitActor) == None))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -992,7 +1025,8 @@ simulated function TakeRadiusDamage(
|
||||
vector HurtOrigin,
|
||||
bool bFullDamage,
|
||||
Actor DamageCauser,
|
||||
optional float DamageFalloffExponent=1.f
|
||||
optional float DamageFalloffExponent=1.f,
|
||||
optional bool bAdjustRadiusDamage=true
|
||||
)
|
||||
{}
|
||||
|
||||
@ -1001,6 +1035,16 @@ function bool CanAITargetThisPawn(Controller TargetingController)
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool CanInteractWithPawnGrapple()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool CanInteractWithZoneVelocity()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function UpdateTurretMeshMaterialColor(float Value)
|
||||
{
|
||||
if (TurretWeaponAttachment == none)
|
||||
@ -1104,6 +1148,9 @@ defaultproperties
|
||||
CamShakeOuterRadius=900
|
||||
CamShakeFalloff=1.5f
|
||||
bOrientCameraShakeTowardsEpicenter=true
|
||||
|
||||
bIgnoreInstigator=true
|
||||
ActorClassToIgnoreForDamage = class'KFPawn_Human'
|
||||
End Object
|
||||
ExplosionTemplate=ExploTemplate0
|
||||
|
||||
@ -1163,4 +1210,7 @@ defaultproperties
|
||||
bAlwaysRelevant=true
|
||||
|
||||
AutoTurretFlashCount=0
|
||||
|
||||
DeployLastLocation=(X=-9999.f, Y=-9999.f, Z=-9999.f)
|
||||
LastMoveExpectedSize= 0.f
|
||||
}
|
||||
|
1310
KFGameContent/Classes/KFPawn_HRG_Warthog.uc
Normal file
1310
KFGameContent/Classes/KFPawn_HRG_Warthog.uc
Normal file
File diff suppressed because it is too large
Load Diff
@ -391,6 +391,7 @@ defaultproperties
|
||||
|
||||
// ---------------------------------------------
|
||||
// AI / Navigation
|
||||
EliteAIType.Add(14); // AT_EliteCrawler
|
||||
ElitePawnClass.Add(class'KFPawn_ZedCrawlerKing')
|
||||
ControllerClass=class'KFAIController_ZedCrawler'
|
||||
bDebugCrawlerPhysics=false
|
||||
|
@ -124,10 +124,19 @@ simulated function CreateExhaustFx()
|
||||
|
||||
event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
|
||||
{
|
||||
local class<KFDamageType> KFDT;
|
||||
|
||||
super.TakeDamage( Damage, InstigatedBy, HitLocation, Momentum, DamageType, HitInfo, DamageCauser );
|
||||
|
||||
if( bCanRage && !bPlayedDeath && (GetHealthPercentage() < RageHealthThreshold || GetHeadHealthPercent() < RageHealthThreshold) )
|
||||
{
|
||||
KFDT = class<KFDamageType>(DamageType);
|
||||
|
||||
if (KFDT != none && KFDT.default.bCanEnrage == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetEnraged( true );
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,20 @@ function CausePainTo(Actor Other)
|
||||
}
|
||||
}
|
||||
|
||||
simulated event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
|
||||
{
|
||||
local KFPawn KFP;
|
||||
|
||||
KFP = KFPawn(Other);
|
||||
|
||||
if (KFP != none && KFP.CanInteractWithZoneVelocity() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Super.Touch(Other, OtherComp, HitLocation, HitNormal);
|
||||
}
|
||||
|
||||
simulated event UnTouch(Actor Other)
|
||||
{
|
||||
local int RecentHitIdx;
|
||||
|
@ -205,7 +205,7 @@ defaultproperties
|
||||
// explosion
|
||||
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||
Damage=350
|
||||
DamageRadius=200
|
||||
DamageRadius=250
|
||||
DamageFalloffExponent=1.f
|
||||
DamageDelay=0.f
|
||||
|
||||
@ -240,7 +240,7 @@ defaultproperties
|
||||
End Object
|
||||
StickHelper=StickHelper0
|
||||
|
||||
SecondsBeforeDetonation=0.5f
|
||||
SecondsBeforeDetonation=0.2f
|
||||
bIsProjActive=true
|
||||
bCanDisintegrate=true
|
||||
bAlwaysReplicateExplosion=true
|
||||
|
@ -241,7 +241,7 @@ defaultproperties
|
||||
End Object
|
||||
StickHelper=StickHelper0
|
||||
|
||||
SecondsBeforeDetonation=0.5f
|
||||
SecondsBeforeDetonation=0.2f
|
||||
bIsProjActive=true
|
||||
bCanDisintegrate=true
|
||||
bAlwaysReplicateExplosion=true
|
||||
|
137
KFGameContent/Classes/KFProj_Bullet_Shotgun_S12_Alt.uc
Normal file
137
KFGameContent/Classes/KFProj_Bullet_Shotgun_S12_Alt.uc
Normal file
@ -0,0 +1,137 @@
|
||||
//=============================================================================
|
||||
// KFProj_Bullet_Shotgun_S12_Alt
|
||||
//=============================================================================
|
||||
// Class Description
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFProj_Bullet_Shotgun_S12_Alt extends KFProj_BallisticExplosive
|
||||
hidedropdown;
|
||||
|
||||
var protected KFWeapon OwnerWeapon;
|
||||
|
||||
/** Initialize the projectile */
|
||||
function Init( vector Direction )
|
||||
{
|
||||
super.Init( Direction );
|
||||
|
||||
OwnerWeapon = KFWeapon( Owner );
|
||||
if( OwnerWeapon != none )
|
||||
{
|
||||
OwnerWeapon.LastPelletFireTime = WorldInfo.TimeSeconds;
|
||||
}
|
||||
|
||||
if (KFPawn(Instigator) != none)
|
||||
{
|
||||
// Explode right away
|
||||
ForceExplode();
|
||||
}
|
||||
}
|
||||
|
||||
reliable client function ForceExplode()
|
||||
{
|
||||
local vector Normal, MuzzleLocation;
|
||||
|
||||
if (KFPawn(Instigator) != none)
|
||||
{
|
||||
Normal.X = 0.f;
|
||||
Normal.Y = 0.f;
|
||||
Normal.Z = 1.f;
|
||||
|
||||
KFSkeletalMeshComponent(OwnerWeapon.Mesh).GetSocketWorldLocationAndRotation('MuzzleFlashAlt', MuzzleLocation);
|
||||
|
||||
Explode(MuzzleLocation, Normal);
|
||||
|
||||
Detonate();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool CanDud()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Don't allow more than one pellet projectile to perform this check in a single frame */
|
||||
function bool ShouldWarnAIWhenFired()
|
||||
{
|
||||
return super.ShouldWarnAIWhenFired() && OwnerWeapon != none && OwnerWeapon.LastPelletFireTime < WorldInfo.TimeSeconds;
|
||||
}
|
||||
|
||||
simulated protected function PrepareExplosionTemplate()
|
||||
{
|
||||
super.PrepareExplosionTemplate();
|
||||
|
||||
/** Since bIgnoreInstigator is transient, its value must be defined here */
|
||||
ExplosionTemplate.bIgnoreInstigator = true;
|
||||
}
|
||||
|
||||
simulated function AdjustCanDisintigrate() {}
|
||||
|
||||
/** Can be overridden in subclasses to exclude specific projectiles from nuking */
|
||||
simulated function bool AllowNuke()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ArmDistSquared=0.f
|
||||
|
||||
MaxSpeed=0.0
|
||||
Speed=0.0
|
||||
|
||||
DamageRadius=0
|
||||
|
||||
// Grenade explosion light
|
||||
Begin Object Class=PointLightComponent Name=ExplosionPointLight
|
||||
LightColor=(R=252,G=218,B=171,A=255)
|
||||
Brightness=0.5f
|
||||
Radius=400.f
|
||||
FalloffExponent=10.f
|
||||
CastShadows=False
|
||||
CastStaticShadows=FALSE
|
||||
CastDynamicShadows=False
|
||||
bCastPerObjectShadows=false
|
||||
bEnabled=FALSE
|
||||
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
|
||||
End Object
|
||||
|
||||
// explosion
|
||||
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||
Damage=200
|
||||
DamageRadius=800
|
||||
DamageFalloffExponent=0.f
|
||||
DamageDelay=0.f
|
||||
MomentumTransferScale=10000
|
||||
bAlwaysFullDamage=true
|
||||
bDoCylinderCheck=true
|
||||
|
||||
// Damage Effects
|
||||
MyDamageType=class'KFDT_Explosive_Shotgun_S12'
|
||||
KnockDownStrength=150
|
||||
FractureMeshRadius=200.0
|
||||
FracturePartVel=500.0
|
||||
|
||||
ExplosionSound=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Alt_Fire_1P'
|
||||
ExplosionEffects=KFImpactEffectInfo'WEP_Saiga12_ARCH.WEP_Saiga12_Impacts'
|
||||
|
||||
// Dynamic Light
|
||||
ExploLight=ExplosionPointLight
|
||||
ExploLightStartFadeOutTime=0.0
|
||||
ExploLightFadeOutTime=0.3
|
||||
|
||||
bIgnoreInstigator=true
|
||||
ActorClassToIgnoreForDamage = class'KFPawn_Human'
|
||||
|
||||
// Camera Shake
|
||||
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
|
||||
CamShakeInnerRadius=0
|
||||
CamShakeOuterRadius=300
|
||||
CamShakeFalloff=1.5f
|
||||
bOrientCameraShakeTowardsEpicenter=true
|
||||
End Object
|
||||
ExplosionTemplate=ExploTemplate0
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ class KFProj_Explosive_HRG_Kaboomstick extends KFProj_BallisticExplosive
|
||||
/** Cached reference to owner weapon */
|
||||
var protected KFWeapon OwnerWeapon;
|
||||
|
||||
var bool bCanNuke;
|
||||
|
||||
/** Initialize the projectile */
|
||||
function Init( vector Direction )
|
||||
{
|
||||
@ -37,25 +39,9 @@ function bool ShouldWarnAIWhenFired()
|
||||
*/
|
||||
simulated protected function PrepareExplosionTemplate()
|
||||
{
|
||||
local KFPawn KFP;
|
||||
local KFPerk CurrentPerk;
|
||||
|
||||
ExplosionTemplate.bIgnoreInstigator = true;
|
||||
|
||||
super.PrepareExplosionTemplate();
|
||||
|
||||
if( ExplosionActorClass == class'KFPerk_Demolitionist'.static.GetNukeExplosionActorClass() )
|
||||
{
|
||||
KFP = KFPawn( Instigator );
|
||||
if( KFP != none )
|
||||
{
|
||||
CurrentPerk = KFP.GetPerk();
|
||||
if( CurrentPerk != none )
|
||||
{
|
||||
CurrentPerk.SetLastHX25NukeTime( WorldInfo.TimeSeconds );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp)
|
||||
@ -76,20 +62,7 @@ simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallCom
|
||||
/** Only allow this projectile to cause a nuke if there hasn't been another nuke very recently */
|
||||
simulated function bool AllowNuke()
|
||||
{
|
||||
local KFPawn KFP;
|
||||
local KFPerk CurrentPerk;
|
||||
|
||||
KFP = KFPawn( Instigator );
|
||||
if( KFP != none )
|
||||
{
|
||||
CurrentPerk = KFP.GetPerk();
|
||||
if( CurrentPerk != none && `TimeSince(CurrentPerk.GetLastHX25NukeTime()) < 0.25f )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return super.AllowNuke();
|
||||
return bCanNuke;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
@ -164,4 +137,6 @@ defaultproperties
|
||||
|
||||
AmbientSoundPlayEvent=none
|
||||
AmbientSoundStopEvent=none
|
||||
|
||||
bCanNuke = true
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ defaultproperties
|
||||
|
||||
// explosion
|
||||
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||
Damage=60
|
||||
Damage=45
|
||||
DamageRadius=200
|
||||
DamageFalloffExponent=0.5f
|
||||
DamageDelay=0.f
|
||||
|
422
KFGameContent/Classes/KFProj_HighExplosive_HRG_Warthog.uc
Normal file
422
KFGameContent/Classes/KFProj_HighExplosive_HRG_Warthog.uc
Normal file
@ -0,0 +1,422 @@
|
||||
//=============================================================================
|
||||
// KFProj_HighExplosive_HRG_Warthog
|
||||
//=============================================================================
|
||||
// High explosive grenade launcher grenade for the HRG Warthog
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFProj_HighExplosive_HRG_Warthog extends KFProj_BallisticExplosive
|
||||
hidedropdown;
|
||||
|
||||
var transient bool bHitWall;
|
||||
|
||||
simulated event PreBeginPlay()
|
||||
{
|
||||
local KFPawn InstigatorPawn;
|
||||
local KFPawn_HRG_Warthog InstigatorPawnWarthog;
|
||||
|
||||
InstigatorPawnWarthog = KFPawn_HRG_Warthog(Instigator);
|
||||
if (InstigatorPawnWarthog != none)
|
||||
{
|
||||
InstigatorPawn = KFPawn(InstigatorPawnWarthog.OwnerWeapon.Instigator);
|
||||
|
||||
if (InstigatorPawn != none)
|
||||
{
|
||||
Instigator = InstigatorPawn;
|
||||
}
|
||||
}
|
||||
|
||||
Super.PreBeginPlay();
|
||||
}
|
||||
|
||||
simulated function bool AllowNuke()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
simulated function bool AllowDemolitionistConcussive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
simulated function bool AllowDemolitionistExplosionChangeRadius()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Used by Demolitionist Nuke and Mad Bomber skills
|
||||
simulated function bool CanDud()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function SetupDetonationTimer(float FuseTime)
|
||||
{
|
||||
if (FuseTime > 0)
|
||||
{
|
||||
bIsTimedExplosive = true;
|
||||
SetTimer(FuseTime, false, 'ExplodeTimer');
|
||||
}
|
||||
}
|
||||
|
||||
function ExplodeTimer()
|
||||
{
|
||||
local Actor HitActor;
|
||||
local vector HitLocation, HitNormal;
|
||||
|
||||
GetExplodeEffectLocation(HitLocation, HitNormal, HitActor);
|
||||
|
||||
TriggerExplosion(HitLocation, HitNormal, HitActor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace down and get the location to spawn the explosion effects and decal
|
||||
*/
|
||||
simulated function GetExplodeEffectLocation(out vector HitLocation, out vector HitRotation, out Actor HitActor)
|
||||
{
|
||||
local vector EffectStartTrace, EffectEndTrace;
|
||||
local TraceHitInfo HitInfo;
|
||||
|
||||
EffectStartTrace = Location + vect(0,0,1) * 4.f;
|
||||
EffectEndTrace = EffectStartTrace - vect(0,0,1) * 32.f;
|
||||
|
||||
// Find where to put the decal
|
||||
HitActor = Trace(HitLocation, HitRotation, EffectEndTrace, EffectStartTrace, false,, HitInfo, TRACEFLAG_Bullet);
|
||||
|
||||
// If the locations are zero (probably because this exploded in the air) set defaults
|
||||
if( IsZero(HitLocation) )
|
||||
{
|
||||
HitLocation = Location;
|
||||
}
|
||||
|
||||
if( IsZero(HitRotation) )
|
||||
{
|
||||
HitRotation = vect(0,0,1);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp)
|
||||
{
|
||||
local Vector VNorm;
|
||||
local rotator NewRotation;
|
||||
local Vector Offset;
|
||||
|
||||
bHitWall = true;
|
||||
|
||||
if (bIsTimedExplosive)
|
||||
{
|
||||
// Reflect off Wall w/damping
|
||||
VNorm = (Velocity dot HitNormal) * HitNormal;
|
||||
|
||||
Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel;
|
||||
|
||||
Speed = VSize(Velocity);
|
||||
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer && Pawn(Wall) == none)
|
||||
{
|
||||
// do the impact effects
|
||||
`ImpactEffectManager.PlayImpactEffects(Location, Instigator, HitNormal, GrenadeBounceEffectInfo, true );
|
||||
}
|
||||
|
||||
// if we hit a pawn or we are moving too slowly stop moving and lay down flat
|
||||
if ( Speed < MinSpeedBeforeStop )
|
||||
{
|
||||
ImpactedActor = Wall;
|
||||
SetPhysics(PHYS_None);
|
||||
|
||||
if( ProjEffects != none )
|
||||
{
|
||||
ProjEffects.SetTranslation(LandedTranslationOffset);
|
||||
}
|
||||
|
||||
// Position the shell on the ground
|
||||
RotationRate.Yaw = 0;
|
||||
RotationRate.Pitch = 0;
|
||||
RotationRate.Roll = 0;
|
||||
NewRotation = Rotation;
|
||||
NewRotation.Pitch = 0;
|
||||
if(ResetRotationOnStop)
|
||||
{
|
||||
SetRotation(NewRotation);
|
||||
}
|
||||
Offset.Z = LandedTranslationOffset.X;
|
||||
SetLocation(Location + Offset);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( WorldInfo.NetMode == NM_Standalone ||
|
||||
(WorldInfo.NetMode == NM_ListenServer && Instigator != none && Instigator.IsLocallyControlled()) )
|
||||
{
|
||||
TriggerExplosion(Location, HitNormal, None);
|
||||
Shutdown(); // cleanup/destroy projectile
|
||||
return;
|
||||
}
|
||||
|
||||
if( Owner != none && KFWeapon( Owner ) != none && Instigator != none )
|
||||
{
|
||||
if( Instigator.Role == ROLE_Authority)
|
||||
{
|
||||
KFWeap_HRG_WarthogWeapon(Owner).ForceExplosionReplicateKill(Location, self);
|
||||
}
|
||||
}
|
||||
|
||||
StopSimulating(); // cleanup/destroy projectile
|
||||
}
|
||||
|
||||
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
|
||||
{
|
||||
// If we collided with a Siren shield, let the shield code handle touches
|
||||
if( Other.IsA('KFTrigger_SirenProjectileShield') )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !bCollideWithTeammates && Pawn(Other) != None )
|
||||
{
|
||||
// Don't hit teammates
|
||||
if( Other.GetTeamNum() == GetTeamNum() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Process impact hits
|
||||
if (Other != Instigator && !Other.bStatic)
|
||||
{
|
||||
ProcessBulletTouch(Other, HitLocation, HitNormal);
|
||||
}
|
||||
|
||||
if (bIsTimedExplosive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( WorldInfo.NetMode == NM_Standalone ||
|
||||
(WorldInfo.NetMode == NM_ListenServer && Instigator != none && Instigator.IsLocallyControlled()) )
|
||||
{
|
||||
// Call KFProjectile base code.. as we don't want to repeat the KFProj_BallisticExplosive base again
|
||||
TriggerExplosion(HitLocation, HitNormal, Other);
|
||||
Shutdown(); // cleanup/destroy projectile
|
||||
return;
|
||||
}
|
||||
|
||||
if( Owner != none && KFWeapon( Owner ) != none && Instigator != none )
|
||||
{
|
||||
// Special case, for some very complicate reason around replication, instigators and the Warthog pawn
|
||||
// This code on the base class was never triggered on Clients: (IsLocallyControlled() always fails, also on the rightful owner of he projectile)
|
||||
// if( Instigator.Role < ROLE_Authority && Instigator.IsLocallyControlled() )
|
||||
// Hence we call here a reliable client function on the Owner
|
||||
// That will call exactly the same code that's inside that If on the base class of this file
|
||||
|
||||
if( Instigator.Role == ROLE_Authority)
|
||||
{
|
||||
KFWeap_HRG_WarthogWeapon(Owner).ForceExplosionReplicate(Other, HitLocation, HitNormal, self);
|
||||
}
|
||||
}
|
||||
|
||||
StopSimulating();
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
if (bHitWall == false)
|
||||
{
|
||||
SetRotation(rotator(Normal(Velocity)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** This will cause the projectile to move to the Original Spawn location when first replicated. This solves the issue of the projectile spawning some distance away from the player when first replicated */
|
||||
simulated function SyncOriginalLocation()
|
||||
{
|
||||
local vector MuzzleLocation, PredictedHitLocation, AimDir, EndTrace, MuzzleToPredictedHit;
|
||||
|
||||
if ( WorldInfo.NetMode == NM_DedicatedServer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// For remote pawns, have the projectile look like its actually
|
||||
// coming from the muzzle of the third person weapon
|
||||
if( bSyncToThirdPersonMuzzleLocation && Instigator != none
|
||||
&& !Instigator.IsFirstPerson() && KFPawn(Owner) != none
|
||||
&& KFPawn(Owner).WeaponAttachment != none )
|
||||
{
|
||||
MuzzleLocation = KFPawn(Owner).WeaponAttachment.GetMuzzleLocation(bFiredFromLeftHandWeapon ? 1 : 0);
|
||||
|
||||
// Set the aim direction to the vector along the line where the
|
||||
// projectile would hit based on velocity. This is the most accurate
|
||||
if( !IsZero(Velocity) )
|
||||
{
|
||||
AimDir = Normal(Velocity);
|
||||
}
|
||||
|
||||
// Set the aim direction to the vector along the line where the
|
||||
// projectile would hit based on where it has moved away from
|
||||
// the original location
|
||||
if( IsZero(Velocity) )
|
||||
{
|
||||
AimDir = Normal(Location-OriginalLocation);
|
||||
}
|
||||
|
||||
// Use the rotation if the location calcs give a zero direction
|
||||
if( IsZero(AimDir) )
|
||||
{
|
||||
AimDir = Normal(Vector(Rotation));
|
||||
}
|
||||
|
||||
if( Location != MuzzleLocation )
|
||||
{
|
||||
// if projectile is spawned at different location than the third
|
||||
// person muzzle location, then simulate an instant trace where
|
||||
// the projectile would hit
|
||||
EndTrace = Location + AimDir * 16384;
|
||||
PredictedHitLocation = GetPredictedHitLocation(Location, EndTrace);
|
||||
|
||||
MuzzleToPredictedHit = Normal(PredictedHitLocation - MuzzleLocation);
|
||||
|
||||
// only adjust AimDir if PredictedHitLocation is "forward" (i.e. don't let projectile fire back towards the shooter)
|
||||
//@todo: still need to make this less wonky (can still shoot straight up sometimes when using long weapons, like the sawblade shooter)
|
||||
if( MuzzleToPredictedHit dot vector(Rotation) > 0.f )
|
||||
{
|
||||
// Then we realign projectile aim direction to match where the projectile would hit.
|
||||
AimDir = MuzzleToPredictedHit;
|
||||
}
|
||||
}
|
||||
|
||||
// Move the projectile to the MuzzleLocation
|
||||
SetLocation(MuzzleLocation);
|
||||
|
||||
// If the Velocity is zero (usually because the projectile impacted
|
||||
// something on the server in its first tick before replicating)
|
||||
// then turn its phyics and collion back on
|
||||
if( IsZero(Velocity) )
|
||||
{
|
||||
SetPhysics(default.Physics);
|
||||
SetCollision( default.bCollideActors, default.bBlockActors );
|
||||
}
|
||||
|
||||
// Adjust the velocity of the projectile so it will hit where
|
||||
// it is supposed to
|
||||
Velocity = Speed * Normal(AimDir);
|
||||
}
|
||||
// set location based on 'OriginalLocation'
|
||||
else if ( Role < ROLE_Authority )
|
||||
{
|
||||
// If the Velocity is zero (usually because the projectile impacted
|
||||
// something on the server in its first tick before replicating)
|
||||
// then turn its physics and collion back on and give it velocity
|
||||
// again so the simulation will work properly on the client
|
||||
if( IsZero(Velocity) )
|
||||
{
|
||||
SetPhysics(default.Physics);
|
||||
|
||||
// Set the aim direction to the vector along the line where the
|
||||
// projectile would hit
|
||||
AimDir = Normal(Location-OriginalLocation);
|
||||
|
||||
// Use the rotation if the location calcs give a zero direction
|
||||
if( IsZero(AimDir) )
|
||||
{
|
||||
AimDir = Vector(Rotation);
|
||||
}
|
||||
|
||||
Velocity = Speed * AimDir;
|
||||
SetCollision( default.bCollideActors, default.bBlockActors );
|
||||
}
|
||||
|
||||
SetLocation(OriginalLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bCollideWithTeammates = false
|
||||
|
||||
Physics=PHYS_Falling
|
||||
Speed=2000
|
||||
MaxSpeed=2000
|
||||
TerminalVelocity=2000
|
||||
TossZ=0
|
||||
GravityScale=1.0
|
||||
MomentumTransfer=50000.0
|
||||
ArmDistSquared=0
|
||||
LifeSpan=25.0f
|
||||
|
||||
bIsTimedExplosive = false
|
||||
|
||||
bWarnAIWhenFired=true
|
||||
|
||||
ProjFlightTemplate=ParticleSystem'WEP_HRG_Warthog_EMIT.FX_HRG_Warthog_Projectile'
|
||||
ProjFlightTemplateZedTime=ParticleSystem'WEP_HRG_Warthog_EMIT.FX_HRG_Warthog_Projectile_ZEDTIME'
|
||||
ProjDudTemplate=ParticleSystem'WEP_HRG_Warthog_EMIT.FX_HRG_Warthog_Projectile_Dud'
|
||||
GrenadeBounceEffectInfo=KFImpactEffectInfo'FX_Impacts_ARCH.DefaultGrenadeImpacts'
|
||||
ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01'
|
||||
AltExploEffects=KFImpactEffectInfo'WEP_HRG_Warthog_ARCH.HRG_Warthog_Explosion_Concussive_Force'
|
||||
|
||||
// Grenade explosion light
|
||||
Begin Object Class=PointLightComponent Name=ExplosionPointLight
|
||||
LightColor=(R=252,G=218,B=171,A=255)
|
||||
Brightness=4.f
|
||||
Radius=2000.f
|
||||
FalloffExponent=10.f
|
||||
CastShadows=False
|
||||
CastStaticShadows=FALSE
|
||||
CastDynamicShadows=False
|
||||
bCastPerObjectShadows=false
|
||||
bEnabled=FALSE
|
||||
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
|
||||
End Object
|
||||
|
||||
ExplosionActorClass=class'KFExplosion_HRG_Warthog'
|
||||
|
||||
// explosion
|
||||
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||
Damage=35
|
||||
DamageRadius=200
|
||||
DamageFalloffExponent=1
|
||||
DamageDelay=0.f
|
||||
|
||||
// Damage Effects
|
||||
MyDamageType=class'KFDT_Explosive_HRG_Warthog_HighExplosive'
|
||||
KnockDownStrength=0
|
||||
FractureMeshRadius=200.0
|
||||
FracturePartVel=500.0
|
||||
ExplosionEffects=KFImpactEffectInfo'WEP_HRG_WarthogWeapon_ARCH.HRG_WarthogWeapon_GrenadeExplosion'
|
||||
ExplosionSound=AkEvent'WW_WEP_HRG_Warthog.Play_WEP_HRG_Warthog_Explosion'
|
||||
|
||||
// Dynamic Light
|
||||
ExploLight=ExplosionPointLight
|
||||
ExploLightStartFadeOutTime=0.0
|
||||
ExploLightFadeOutTime=0.2
|
||||
|
||||
// Camera Shake
|
||||
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
|
||||
CamShakeInnerRadius=200
|
||||
CamShakeOuterRadius=900
|
||||
CamShakeFalloff=1.5f
|
||||
bOrientCameraShakeTowardsEpicenter=true
|
||||
bIgnoreInstigator=true
|
||||
ActorClassToIgnoreForDamage = class'KFPawn_Human'
|
||||
End Object
|
||||
ExplosionTemplate=ExploTemplate0
|
||||
|
||||
AmbientSoundPlayEvent=AkEvent'WW_WEP_HRG_Warthog.Play_WEP_HRG_Warthog_Projectile_LP'
|
||||
AmbientSoundStopEvent=AkEvent'WW_WEP_HRG_Warthog.Stop_WEP_HRG_Warthog_Projectile'
|
||||
|
||||
// The higher the more bouncing
|
||||
DampenFactor=0.4f
|
||||
DampenFactorParallel=0.4f
|
||||
|
||||
bHitWall = false
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ defaultproperties
|
||||
AmbientSoundPlayEvent=AkEvent'WW_WEP_HRG_MedicMissile.Play_WEP_HRG_MedicMissile_Projectile_Loop'
|
||||
AmbientSoundStopEvent=AkEvent'WW_WEP_HRG_MedicMissile.Stop_WEP_HRG_MedicMissile_Projectile_Loop'
|
||||
|
||||
AltExploEffects=KFImpactEffectInfo'WEP_HRG_MedicMissile_ARCH.HRG_MedicMissile_Explosion_Concussive_Force'
|
||||
AltExploEffects=KFImpactEffectInfo'WEP_HRG_MedicMissile_ARCH.HRG_MedicMissile_Explosion'
|
||||
|
||||
ExplosionActorClass=class'KFExplosion_HRG_MedicMissile'
|
||||
|
||||
|
170
KFGameContent/Classes/KFSeasonalEventStats_Summer2023.uc
Normal file
170
KFGameContent/Classes/KFSeasonalEventStats_Summer2023.uc
Normal file
@ -0,0 +1,170 @@
|
||||
//=============================================================================
|
||||
// KFSeasonalEventStats_Summer2023
|
||||
//=============================================================================
|
||||
// Tracks event-specific challenges/accomplishments for Summer 2023
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFSeasonalEventStats_Summer2023 extends KFSeasonalEventStats;
|
||||
|
||||
var transient private const int HRGBombardierZedsRequired, EMPRequired, StandYourGroundRequired, EndlessWaveRequired, SummerEventIndex;
|
||||
|
||||
private event Initialize(string MapName)
|
||||
{
|
||||
local string CapsMapName;
|
||||
CapsMapName = Caps(MapName);
|
||||
|
||||
bObjectiveIsValidForMap[0] = 1; // Kill 1500 Zeds with HRG Bombardier
|
||||
bObjectiveIsValidForMap[1] = 0; // Complete the Weekly on Subduction
|
||||
bObjectiveIsValidForMap[2] = 1; // Stun 2500 Zeds with EMP affliction
|
||||
bObjectiveIsValidForMap[3] = 1; // Complete 25 Stand your Ground objectives
|
||||
bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Subduction
|
||||
|
||||
if (CapsMapName == "KF-SUBDUCTION")
|
||||
{
|
||||
bObjectiveIsValidForMap[1] = 1;
|
||||
bObjectiveIsValidForMap[4] = 1;
|
||||
}
|
||||
|
||||
SetSeasonalEventStatsMax(HRGBombardierZedsRequired, 0, EMPRequired, StandYourGroundRequired, 0);
|
||||
}
|
||||
|
||||
private event GrantEventItems()
|
||||
{
|
||||
if (Outer.IsEventObjectiveComplete(0) &&
|
||||
Outer.IsEventObjectiveComplete(1) &&
|
||||
Outer.IsEventObjectiveComplete(2) &&
|
||||
Outer.IsEventObjectiveComplete(3) &&
|
||||
Outer.IsEventObjectiveComplete(4))
|
||||
{
|
||||
// TODO
|
||||
GrantEventItem(9672);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event OnGameWon(class<GameInfo> GameClass, int Difficulty, int GameLength, bool bCoOp)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
// Complete the Weekly on Subduction
|
||||
ObjIdx = 1;
|
||||
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (GameClass == class'KFGameInfo_WeeklySurvival')
|
||||
{
|
||||
FinishedObjective(SummerEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function OnTryCompleteObjective(int ObjectiveIndex, int EventIndex)
|
||||
{
|
||||
local int HRGBombardierIdx, EMPIdx, StandYourGroundIdx, ObjectiveLimit;
|
||||
local bool bValidIdx;
|
||||
|
||||
HRGBombardierIdx = 0;
|
||||
EMPIdx = 2;
|
||||
StandYourGroundIdx = 3;
|
||||
|
||||
bValidIdx = false;
|
||||
|
||||
if (EventIndex == SummerEventIndex)
|
||||
{
|
||||
if (ObjectiveIndex == HRGBombardierIdx)
|
||||
{
|
||||
ObjectiveLimit = HRGBombardierZedsRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
else if (ObjectiveIndex == EMPIdx)
|
||||
{
|
||||
ObjectiveLimit = EMPRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
else if (ObjectiveIndex == StandYourGroundIdx)
|
||||
{
|
||||
ObjectiveLimit = StandYourGroundRequired;
|
||||
bValidIdx = true;
|
||||
}
|
||||
|
||||
if (bValidIdx && bObjectiveIsValidForMap[ObjectiveIndex] != 0)
|
||||
{
|
||||
IncrementSeasonalEventStat(ObjectiveIndex, 1);
|
||||
|
||||
if (Outer.GetSeasonalEventStatValue(ObjectiveIndex) >= ObjectiveLimit)
|
||||
{
|
||||
FinishedObjective(SummerEventIndex, ObjectiveIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated event OnWaveCompleted(class<GameInfo> GameClass, int Difficulty, int WaveNum)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
// Complete wave 15 on Endless Hard or higher difficulty on Subduction
|
||||
ObjIdx = 4;
|
||||
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD)
|
||||
{
|
||||
FinishedObjective(SummerEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function OnAfflictionCaused(EAfflictionType Type)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
// Stun 2500 Zeds with EMP affliction
|
||||
ObjIdx = 2;
|
||||
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (Type == AF_EMP)
|
||||
{
|
||||
IncrementSeasonalEventStat(ObjIdx, 1);
|
||||
|
||||
if (Outer.GetSeasonalEventStatValue(ObjIdx) >= EMPRequired)
|
||||
{
|
||||
FinishedObjective(SummerEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function OnZedKilled(class<KFPawn_Monster> MonsterClass, int Difficulty, class<DamageType> DT)
|
||||
{
|
||||
local int ObjIdx;
|
||||
|
||||
// Kill 1500 Zeds with HRG Bombardier
|
||||
ObjIdx = 0;
|
||||
if (bObjectiveIsValidForMap[ObjIdx] != 0)
|
||||
{
|
||||
if (DT == class'KFDT_Explosive_HRG_Warthog' ||
|
||||
DT == class'KFDT_Explosive_HRG_Warthog_HighExplosive' ||
|
||||
DT == class'KFDT_Ballistic_HRG_Warthog')
|
||||
{
|
||||
IncrementSeasonalEventStat(ObjIdx, 1);
|
||||
|
||||
if (Outer.GetSeasonalEventStatValue(ObjIdx) >= HRGBombardierZedsRequired)
|
||||
{
|
||||
FinishedObjective(SummerEventIndex, ObjIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
HRGBombardierZedsRequired=1500
|
||||
EMPRequired=2500
|
||||
StandYourGroundRequired=25
|
||||
EndlessWaveRequired=15
|
||||
SummerEventIndex=SEI_Summer
|
||||
}
|
113
KFGameContent/Classes/KFWeapAttach_HRG_Warthog.uc
Normal file
113
KFGameContent/Classes/KFWeapAttach_HRG_Warthog.uc
Normal file
@ -0,0 +1,113 @@
|
||||
//=============================================================================
|
||||
// KFWeapAttach_HRG_Warthog
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFWeapAttach_HRG_Warthog extends KFWeapAttach_DualBase;
|
||||
|
||||
`define AUTOTURRET_ATTACH_MIC_LED_INDEX 2
|
||||
|
||||
const ThrowAnim = 'Drone_Throw';
|
||||
const CrouchThrowAnim = 'Drone_Throw_CH';
|
||||
|
||||
const DetonateAnim = 'Shoot';
|
||||
const CrouchDetonateAnim = 'CH_Shoot';
|
||||
|
||||
const TransitionParamName = 'transition_full_to_empty';
|
||||
const EmptyParamName = 'Blinking_0_off___1_on';
|
||||
|
||||
/** Completely overridden to play anims for both C4 firemodes (throw and detonate), also doesn't need to play effects */
|
||||
simulated function bool ThirdPersonFireEffects( vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte )
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
// Effects below this point are culled based on visibility and distance
|
||||
if ( !ActorEffectIsRelevant(P, false, MaxFireEffectDistance) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DecodeThirdPersonAnimRate( ThirdPersonAnimRateByte );
|
||||
|
||||
// Weapon shoot anims
|
||||
if (P.FiringMode == 0)
|
||||
{
|
||||
// anim simply hides and unhides bone
|
||||
Duration = WeapMesh.GetAnimLength( ThrowAnim );
|
||||
WeapMesh.PlayAnim( ThrowAnim, Duration / ThirdPersonAnimRate,, true );
|
||||
|
||||
// use timer to make sure bone gets un-hidden (in case anim gets interrupted)
|
||||
SetTimer( 0.75f, false, nameof(UnHide) );
|
||||
}
|
||||
else if (P.FiringMode == 5)
|
||||
{
|
||||
Duration = WeapMesh.GetAnimLength( DetonateAnim );
|
||||
LeftWeapMesh.PlayAnim( DetonateAnim, Duration / ThirdPersonAnimRate,, true );
|
||||
}
|
||||
|
||||
// Additive character shoot anims
|
||||
if ( !P.IsDoingSpecialMove() )
|
||||
{
|
||||
if( P.FiringMode == 0 )
|
||||
{
|
||||
if ( P.bIsCrouched )
|
||||
{
|
||||
P.PlayBodyAnim(CrouchThrowAnim, EAS_CH_UpperBody, ThirdPersonAnimRate, ShootBlendInTime, ShootBlendOutTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
P.PlayBodyAnim(ThrowAnim, EAS_UpperBody, ThirdPersonAnimRate, ShootBlendInTime, ShootBlendOutTime);
|
||||
}
|
||||
}
|
||||
else if( P.FiringMode == 5 )
|
||||
{
|
||||
if ( P.bIsCrouched )
|
||||
{
|
||||
P.PlayBodyAnim(CrouchDetonateAnim, EAS_CH_UpperBody, ThirdPersonAnimRate, ShootBlendInTime, ShootBlendOutTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
P.PlayBodyAnim(DetonateAnim, EAS_UpperBody, ThirdPersonAnimRate, ShootBlendInTime, ShootBlendOutTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prevent using "aiming" KFAnim_BlendByTargetingMode since we don't have/need the aim anims for C4
|
||||
P.LastWeaponFireTime = -1.f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Unhides the C4 unit in hand (basically the same as the notify, but don't use the notify) */
|
||||
simulated function UnHide()
|
||||
{
|
||||
if( WeapMesh != none )
|
||||
{
|
||||
WeapMesh.UnHideBoneByName( 'RW_Weapon' );
|
||||
}
|
||||
}
|
||||
|
||||
/** Special event added for weap attachments. Free for use */
|
||||
function OnSpecialEvent(int Arg)
|
||||
{
|
||||
local float Value;
|
||||
Value = (Arg - 1) / 100.0f;
|
||||
|
||||
if (Value >= 0)
|
||||
{
|
||||
if ( WeaponMIC == None && LeftWeapMesh != None )
|
||||
{
|
||||
WeaponMIC = LeftWeapMesh.CreateAndSetMaterialInstanceConstant(`AUTOTURRET_ATTACH_MIC_LED_INDEX);
|
||||
}
|
||||
|
||||
WeaponMIC.SetScalarParameterValue(TransitionParamName, 1.0f - Value);
|
||||
WeaponMIC.SetScalarParameterValue(EmptyParamName, Value == 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bHasLaserSight=false
|
||||
}
|
271
KFGameContent/Classes/KFWeapAttach_HRG_WarthogWeap.uc
Normal file
271
KFGameContent/Classes/KFWeapAttach_HRG_WarthogWeap.uc
Normal file
@ -0,0 +1,271 @@
|
||||
//=============================================================================
|
||||
// KFWeapAttach_HRG_WarthogWeapon
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFWeapAttach_HRG_WarthogWeap extends KFWeaponAttachment;
|
||||
|
||||
const DeployAnimName = 'Drone_Deploy';
|
||||
const DroneFireAnim = 'Drone_Shoot';
|
||||
const DroneEmptyStartAnim = 'Drone_Start_Empty';
|
||||
const DroneEmptyAnim = 'Drone_Empty';
|
||||
const DroneIdleAnim = 'Drone_Idle';
|
||||
const DroneClosedAnim = 'Drone_IdleClose';
|
||||
|
||||
const LaserSightSocketName = 'LaserSightSocket';
|
||||
const LaserColorParamName = '0blue_1red';
|
||||
|
||||
var transient MaterialInstanceConstant LaserDotMIC;
|
||||
var transient MaterialInstanceConstant LaserBeamMIC;
|
||||
|
||||
simulated function float PlayDeployAnim()
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DeployAnimName );
|
||||
WeapMesh.PlayAnim( DeployAnimName, Duration / ThirdPersonAnimRate, false, true );
|
||||
|
||||
return Duration;
|
||||
}
|
||||
|
||||
simulated function PlayEmptyState()
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
ClearTimer(nameof(PlayIdleAnim));
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DroneEmptyStartAnim );
|
||||
WeapMesh.PlayAnim( DroneEmptyStartAnim, Duration / ThirdPersonAnimRate, true, false);
|
||||
|
||||
SetTimer(Duration, false, 'PlayEmptyAnim');
|
||||
}
|
||||
|
||||
simulated function PlayEmptyAnim()
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DroneEmptyAnim );
|
||||
WeapMesh.PlayAnim( DroneEmptyAnim, Duration / ThirdPersonAnimRate, true, false);
|
||||
|
||||
if (LaserSight != none)
|
||||
{
|
||||
LaserSight.ChangeVisibility(false);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayIdleAnim()
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DroneIdleAnim );
|
||||
WeapMesh.PlayAnim( DroneIdleAnim, Duration / ThirdPersonAnimRate, true, false );
|
||||
}
|
||||
|
||||
simulated function PlayCloseAnim()
|
||||
{
|
||||
local float Duration;
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DroneClosedAnim );
|
||||
WeapMesh.PlayAnim( DroneClosedAnim, Duration / ThirdPersonAnimRate, true, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn all of the effects that will be seen in behindview/remote clients. This
|
||||
* function is called from the pawn, and should only be called when on a remote client or
|
||||
* if the local client is in a 3rd person mode.
|
||||
* @return TRUE if the effect culling check passes
|
||||
*/
|
||||
simulated function bool ThirdPersonFireEffects( vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte )
|
||||
{
|
||||
// local EAnimSlotStance AnimType;
|
||||
|
||||
SpawnTracer(GetMuzzleLocation(), HitLocation);
|
||||
|
||||
// Effects below this point are culled based on visibility and distance
|
||||
if ( !ActorIsRelevant(self, false, MaxFireEffectDistance) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DecodeThirdPersonAnimRate( ThirdPersonAnimRateByte );
|
||||
|
||||
// Weapon shoot anims
|
||||
if( !bWeapMeshIsPawnMesh )
|
||||
{
|
||||
PlayWeaponFireAnim();
|
||||
}
|
||||
|
||||
/*
|
||||
if( P.IsDoingSpecialMove() && P.SpecialMoves[P.SpecialMove].bAllowFireAnims )
|
||||
{
|
||||
AnimType = EAS_Additive;
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimType = EAS_FullBody;
|
||||
}
|
||||
*/
|
||||
// AnimType = EAS_FullBody;
|
||||
|
||||
// Character shoot anims
|
||||
/*
|
||||
if ( AnimType == EAS_Additive )
|
||||
{
|
||||
PlayPawnFireAnim( P, AnimType );
|
||||
|
||||
// interrupt other weapon action anims (e.g. Reload)
|
||||
if( !P.IsDoingSpecialMove() )
|
||||
{
|
||||
P.StopBodyAnim(P.bIsCrouched ? EAS_CH_UpperBody : EAS_UpperBody, 0.1f);
|
||||
}
|
||||
|
||||
if ( OnWeaponStateChanged != None )
|
||||
{
|
||||
OnWeaponStateChanged(true);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Always DEFAULT_FIREMODE
|
||||
CauseMuzzleFlash(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
simulated function bool ActorIsRelevant(Actor EffectInstigator, bool bForceDedicated, optional float VisibleCullDistance=5000.0, optional float HiddenCullDistance=350.0 )
|
||||
{
|
||||
local PlayerController P;
|
||||
local float DistSq;
|
||||
local vector CameraLoc;
|
||||
local rotator CameraRot;
|
||||
|
||||
if ( EffectInstigator == None )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// No local player, so only spawn on dedicated server if bForceDedicated
|
||||
if ( WorldInfo.NetMode == NM_DedicatedServer )
|
||||
{
|
||||
return bForceDedicated;
|
||||
}
|
||||
|
||||
if ( bForceDedicated && (WorldInfo.NetMode == NM_ListenServer) && (WorldInfo.Game.NumPlayers > 1) )
|
||||
{
|
||||
// Is acting as server, so spawn effect if bForceDedicated
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Determine how far to the nearest local viewer
|
||||
DistSq = 10000000000.0;
|
||||
ForEach LocalPlayerControllers(class'PlayerController', P)
|
||||
{
|
||||
if ( P.GetViewTarget() == self )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
P.GetPlayerViewPoint(CameraLoc, CameraRot);
|
||||
DistSq = FMin(DistSq, VSizeSq(Location - CameraLoc)*Square(P.LODDistanceFactor));
|
||||
}
|
||||
|
||||
if ( DistSq > VisibleCullDistance*VisibleCullDistance )
|
||||
{
|
||||
// never spawn beyond cull distance
|
||||
return FALSE;
|
||||
}
|
||||
else if ( DistSq < HiddenCullDistance*HiddenCullDistance )
|
||||
{
|
||||
// If close enough, always spawn even if hidden
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This doesn't seem to be updating the render time, so ignore it */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Plays fire animation on weapon mesh */
|
||||
simulated function PlayWeaponFireAnim()
|
||||
{
|
||||
local float Duration;
|
||||
local bool bAnimPlayed;
|
||||
|
||||
Duration = WeapMesh.GetAnimLength( DroneFireAnim );
|
||||
|
||||
bAnimPlayed = WeapMesh.PlayAnim( DroneFireAnim, Duration / ThirdPersonAnimRate, false, false );
|
||||
|
||||
if (bAnimPlayed)
|
||||
{
|
||||
ClearTimer(nameof(PlayIdleAnim));
|
||||
SetTimer(Duration, false, nameof(PlayIdleAnim));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Laser
|
||||
*/
|
||||
|
||||
simulated function AttachLaserSight()
|
||||
{
|
||||
if ( WeapMesh != none && LaserSight == None && LaserSightArchetype != None )
|
||||
{
|
||||
LaserSight = new(self) Class'KFLaserSightAttachment' (LaserSightArchetype);
|
||||
LaserSight.AttachLaserSight(WeapMesh, false, LaserSightSocketName);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function UpdateLaserColor(bool bInCombat)
|
||||
{
|
||||
if (LaserSight != none)
|
||||
{
|
||||
if (LaserDotMIC == none)
|
||||
{
|
||||
LaserDotMIC = LaserSight.LaserDotMeshComp.CreateAndSetMaterialInstanceConstant(0);
|
||||
}
|
||||
|
||||
if (LaserBeamMIC == none)
|
||||
{
|
||||
LaserBeamMIC = LaserSight.LaserBeamMeshComp.CreateAndSetMaterialInstanceConstant(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (LaserDotMIC != none)
|
||||
{
|
||||
LaserDotMIC.SetScalarParameterValue(LaserColorParamName, bInCombat ? 1 : 0);
|
||||
}
|
||||
|
||||
if (LaserBeamMIC != none)
|
||||
{
|
||||
LaserBeamMIC.SetScalarParameterValue(LaserColorParamName, bInCombat ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign weapon skin to 3rd person mesh
|
||||
*/
|
||||
simulated event SetWeaponSkin(int ItemId, optional bool bFinishedLoading = false)
|
||||
{
|
||||
local array<MaterialInterface> SkinMICs;
|
||||
|
||||
if ( ItemId > 0 && WorldInfo.NetMode != NM_DedicatedServer && !bWaitingForWeaponSkinLoad)
|
||||
{
|
||||
if (!bFinishedLoading && StartLoadWeaponSkin(ItemId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SkinMICs = class'KFWeaponSkinList'.static.GetWeaponSkin(ItemId, WST_ThirdPerson);
|
||||
|
||||
if ( SkinMICs.Length > 0 )
|
||||
{
|
||||
WeapMesh.SetMaterial(0, SkinMICs[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
//defaults
|
||||
bHasLaserSight=true
|
||||
}
|
153
KFGameContent/Classes/KFWeapAttach_Shotgun_S12.uc
Normal file
153
KFGameContent/Classes/KFWeapAttach_Shotgun_S12.uc
Normal file
@ -0,0 +1,153 @@
|
||||
//=============================================================================
|
||||
// KFWeapAttach_shotgun_s12
|
||||
//=============================================================================
|
||||
//
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
class KFWeapAttach_Shotgun_S12 extends KFWeaponAttachment;
|
||||
|
||||
const SecondaryMuzzleSocket = 'MuzzleFlashAlt';
|
||||
const SecondaryReloadAnim = 'Reload_Secondary';
|
||||
const SecondaryReloadCHAnim = 'Reload_Secondary_CH';
|
||||
const SecondaryReloadEliteAnim = 'Reload_Secondary_Elite';
|
||||
const SecondaryReloadEliteCHAnim = 'Reload_Secondary_Elite_CH';
|
||||
|
||||
var transient ParticleSystemComponent ExplosionPSC;
|
||||
var transient ParticleSystem ExplosionEffect;
|
||||
var protected transient KFMuzzleFlash SecondaryMuzzleFlash;
|
||||
var protected transient bool bWasSecondaryShot;
|
||||
|
||||
simulated function bool ThirdPersonFireEffects( vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte )
|
||||
{
|
||||
local vector SocketLocation;
|
||||
|
||||
bWasSecondaryShot = P.FiringMode == 1;
|
||||
|
||||
if (Super.ThirdPersonFireEffects(HitLocation, P, ThirdPersonAnimRateByte))
|
||||
{
|
||||
if (P.FiringMode == 1 && !P.IsLocallyControlled())
|
||||
{
|
||||
if (ExplosionEffect != None)
|
||||
{
|
||||
WeapMesh.GetSocketWorldLocationAndRotation('MuzzleFlashAlt', SocketLocation);
|
||||
|
||||
ExplosionPSC = WorldInfo.MyEmitterPool.SpawnEmitter(class'KFWeap_Shotgun_S12'.default.ExplosionEffect, SocketLocation, rotator(vect(0,0,1)));
|
||||
ExplosionPSC.ActivateSystem();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return the starting location for effects (e.g. tracers) */
|
||||
simulated function vector GetMuzzleLocation(optional byte MuzzleID)
|
||||
{
|
||||
if (bWasSecondaryShot)
|
||||
{
|
||||
return GetAltMuzzleLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Super.GetMuzzleLocation(MuzzleID);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function vector GetAltMuzzleLocation(optional byte MuzzleID)
|
||||
{
|
||||
local vector SocketLocation;
|
||||
|
||||
if (SecondaryMuzzleFlash == None)
|
||||
{
|
||||
AttachMuzzleFlash();
|
||||
}
|
||||
|
||||
if( SecondaryMuzzleFlash != none )
|
||||
{
|
||||
WeapMesh.GetSocketWorldLocationAndRotation(SecondaryMuzzleFlash.GetSocketName(), SocketLocation);
|
||||
return SocketLocation;
|
||||
}
|
||||
|
||||
return Super.GetMuzzleLocation(MuzzleID);
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
local vector SocketLocation;
|
||||
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
if (ExplosionPSC != none && ExplosionPSC.bIsActive)
|
||||
{
|
||||
WeapMesh.GetSocketWorldLocationAndRotation('MuzzleFlashAlt', SocketLocation);
|
||||
ExplosionPSC.SetVectorParameter('WeaponEndpoint', SocketLocation);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function CauseMuzzleFlash(byte FiringMode)
|
||||
{
|
||||
if ( FiringMode == 1 ) // AltFire
|
||||
{
|
||||
if (SecondaryMuzzleFlash == None)
|
||||
{
|
||||
AttachMuzzleFlash();
|
||||
}
|
||||
|
||||
if (SecondaryMuzzleFlash != None )
|
||||
{
|
||||
SecondaryMuzzleFlash.CauseMuzzleFlash(FiringMode);
|
||||
if ( SecondaryMuzzleFlash.bAutoActivateShellEject )
|
||||
{
|
||||
SecondaryMuzzleFlash.CauseShellEject();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.CauseMuzzleFlash(FiringMode);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function AttachMuzzleFlash()
|
||||
{
|
||||
Super.AttachMuzzleFlash();
|
||||
|
||||
if ( WeapMesh != none && SecondaryMuzzleFlash == None )
|
||||
{
|
||||
SecondaryMuzzleFlash = new(self) Class'KFMuzzleFlash'(class'KFWeap_Shotgun_S12'.default.SecondaryMuzzleFlashTemplate);
|
||||
SecondaryMuzzleFlash.AttachMuzzleFlash(WeapMesh, SecondaryMuzzleSocket,);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayReloadMagazineAnim(EWeaponState NewWeaponState, KFPawn P)
|
||||
{
|
||||
local name AnimName;
|
||||
|
||||
switch (NewWeaponState)
|
||||
{
|
||||
|
||||
case WEP_ReloadSecondary:
|
||||
AnimName = (P.bIsCrouched) ? SecondaryReloadCHAnim : SecondaryReloadAnim;
|
||||
break;
|
||||
case WEP_ReloadSecondary_Elite:
|
||||
AnimName = (P.bIsCrouched) ? SecondaryReloadEliteCHAnim : SecondaryReloadEliteAnim;
|
||||
break;
|
||||
}
|
||||
|
||||
if (AnimName != '')
|
||||
{
|
||||
PlayCharacterMeshAnim(P, AnimName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.PlayReloadMagazineAnim(NewWeaponState, P);
|
||||
}
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ExplosionEffect=ParticleSystem'WEP_1P_Saiga12_EMIT.FX_Saiga12_Explosion_3P'
|
||||
bWasSecondaryShot=false
|
||||
}
|
@ -192,7 +192,14 @@ simulated function Detonate(optional bool bKeepTurret = false)
|
||||
continue;
|
||||
}
|
||||
|
||||
KFPawn_AutoTurret(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
||||
if (KFPawn_HRG_Warthog(TurretsCopy[i]) != none)
|
||||
{
|
||||
KFPawn_HRG_Warthog(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
||||
}
|
||||
else if (KFPawn_Autoturret(TurretsCopy[i]) != none)
|
||||
{
|
||||
KFPawn_Autoturret(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
||||
}
|
||||
}
|
||||
|
||||
KFPC.DeployedTurrets.Remove(bKeepTurret ? 1 : 0, KFPC.DeployedTurrets.Length);
|
||||
@ -231,6 +238,7 @@ function RemoveDeployedTurret( optional int Index = INDEX_NONE, optional Actor T
|
||||
function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
|
||||
{
|
||||
local int i;
|
||||
local Actor WeaponPawn;
|
||||
|
||||
super.SetOriginalValuesFromPickup( PickedUpWeapon );
|
||||
|
||||
@ -256,13 +264,24 @@ function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
|
||||
|
||||
for( i = 0; i < NumDeployedTurrets; ++i )
|
||||
{
|
||||
// charge alerts (beep, light) need current instigator
|
||||
KFPC.DeployedTurrets[i].Instigator = Instigator;
|
||||
KFPC.DeployedTurrets[i].SetOwner(self);
|
||||
WeaponPawn = KFPC.DeployedTurrets[i];
|
||||
if (WeaponPawn != none)
|
||||
{
|
||||
// charge alerts (beep, light) need current instigator
|
||||
WeaponPawn.Instigator = Instigator;
|
||||
WeaponPawn.SetOwner(self);
|
||||
|
||||
if( Instigator.Controller != none )
|
||||
{
|
||||
KFPawn_AutoTurret(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
||||
if (Instigator.Controller != none)
|
||||
{
|
||||
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]) != none)
|
||||
{
|
||||
KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
||||
}
|
||||
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[i]) != none)
|
||||
{
|
||||
KFPawn_Autoturret(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,6 +362,8 @@ simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
|
||||
|
||||
simulated function BeginFire( byte FireModeNum )
|
||||
{
|
||||
local bool bCanDetonate;
|
||||
|
||||
// Clear any pending detonate if we pressed the main fire
|
||||
// That prevents strange holding right click behaviour and sound issues
|
||||
if (FireModeNum == DEFAULT_FIREMODE)
|
||||
@ -359,11 +380,21 @@ simulated function BeginFire( byte FireModeNum )
|
||||
|
||||
if (NumDeployedTurrets > 0 && bTurretReadyToUse)
|
||||
{
|
||||
PrepareAndDetonate();
|
||||
bCanDetonate = NumDeployedTurrets > 0;
|
||||
|
||||
if (bCanDetonate)
|
||||
{
|
||||
PrepareAndDetonate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KFPC != none)
|
||||
{
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
}
|
||||
|
||||
if (FireModeNum == DEFAULT_FIREMODE
|
||||
&& NumDeployedTurrets >= MaxTurretsDeployed
|
||||
&& HasAnyAmmo())
|
||||
@ -573,7 +604,15 @@ function CheckTurretAmmo()
|
||||
|
||||
if (KFPC.DeployedTurrets.Length > 0)
|
||||
{
|
||||
Weapon = KFWeapon(KFPawn_AutoTurret(KFPC.DeployedTurrets[0]).Weapon);
|
||||
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]) != none)
|
||||
{
|
||||
Weapon = KFWeapon(KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]).Weapon);
|
||||
}
|
||||
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[0]) != none)
|
||||
{
|
||||
Weapon = KFWeapon(KFPawn_Autoturret(KFPC.DeployedTurrets[0]).Weapon);
|
||||
}
|
||||
|
||||
if (Weapon != none)
|
||||
{
|
||||
Percentage = float(Weapon.AmmoCount[0]) / Weapon.MagazineCapacity[0];
|
||||
@ -797,4 +836,5 @@ defaultproperties
|
||||
NumBloodMapMaterials=3
|
||||
|
||||
bDetonateLocked=false
|
||||
CurrentAmmoPercentage=-1.0f
|
||||
}
|
||||
|
@ -45,13 +45,13 @@ defaultproperties
|
||||
End Object
|
||||
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Bludgeon_ChainBat'
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=68// 34
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=75// 34
|
||||
|
||||
InstantHitDamageTypes(HEAVY_ATK_FIREMODE)=class'KFDT_Bludgeon_ChainBatHeavy'
|
||||
InstantHitDamage(HEAVY_ATK_FIREMODE)=90 //68
|
||||
InstantHitDamage(HEAVY_ATK_FIREMODE)=100 //68
|
||||
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_ChainBatBash'
|
||||
InstantHitDamage(BASH_FIREMODE)=68
|
||||
InstantHitDamage(BASH_FIREMODE)=75
|
||||
|
||||
// Inventory
|
||||
GroupPriority=50
|
||||
|
@ -40,7 +40,7 @@ defaultproperties
|
||||
End Object
|
||||
|
||||
// Inventory
|
||||
GroupPriority=25
|
||||
GroupPriority=47
|
||||
InventorySize=4
|
||||
WeaponSelectTexture=Texture2D'ui_weaponselect_tex.UI_WeaponSelect_Crovel'
|
||||
|
||||
|
@ -22,6 +22,11 @@ var bool bLastFireWasAlt;
|
||||
|
||||
var const bool bDebugDrawVortex;
|
||||
|
||||
static simulated event EFilterTypeUI GetTraderFilter()
|
||||
{
|
||||
return FT_Explosive;
|
||||
}
|
||||
|
||||
simulated function Activate()
|
||||
{
|
||||
super.Activate();
|
||||
|
@ -15,6 +15,8 @@ var protected const array<vector2D> PelletSpread;
|
||||
/** Last time a submunition projectile was fired from this weapon */
|
||||
var float LastSubmunitionFireTime;
|
||||
|
||||
var transient bool AlreadyIssuedCanNuke;
|
||||
|
||||
/*********************************************************************************************
|
||||
Firing / Projectile
|
||||
********************************************************************************************* */
|
||||
@ -79,6 +81,38 @@ static simulated event EFilterTypeUI GetAltTraderFilter()
|
||||
return FT_Pistol;
|
||||
}
|
||||
|
||||
simulated function KFProjectile SpawnAllProjectiles(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
|
||||
{
|
||||
local KFProjectile Proj;
|
||||
|
||||
AlreadyIssuedCanNuke = false;
|
||||
|
||||
Proj = Super.SpawnAllProjectiles(KFProjClass, RealStartLoc, AimDir);
|
||||
|
||||
AlreadyIssuedCanNuke = false;
|
||||
|
||||
return Proj;
|
||||
}
|
||||
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local KFProj_ExplosiveSubMunition_HX25 Proj;
|
||||
|
||||
Proj = KFProj_ExplosiveSubMunition_HX25(Super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir));
|
||||
|
||||
if (AlreadyIssuedCanNuke == false)
|
||||
{
|
||||
Proj.bCanNuke = true;
|
||||
AlreadyIssuedCanNuke = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Proj.bCanNuke = false;
|
||||
}
|
||||
|
||||
return Proj;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
ForceReloadTime=0.3f
|
||||
@ -200,4 +234,6 @@ defaultproperties
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.4f), (Stat=EWUS_Weight, Add=2)))
|
||||
WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.6f), (Stat=EWUS_Weight, Add=3)))
|
||||
WeaponUpgrades[4]=(Stats=((Stat=EWUS_Damage0, Scale=1.9f), (Stat=EWUS_Weight, Add=4)))
|
||||
|
||||
AlreadyIssuedCanNuke = false
|
||||
}
|
@ -55,6 +55,11 @@ Replication
|
||||
ChargeTime;
|
||||
}
|
||||
|
||||
static simulated event EFilterTypeUI GetTraderFilter()
|
||||
{
|
||||
return FT_Projectile;
|
||||
}
|
||||
|
||||
simulated event PostInitAnimTree( SkeletalMeshComponent SkelComp )
|
||||
{
|
||||
local vector vec;
|
||||
|
@ -343,7 +343,7 @@ defaultproperties
|
||||
InstantHitDamage(ALTFIRE_FIREMODE)=0.0 //override by AfflictionHandler.GetBigHeadAfflictionDamageModifier()
|
||||
InstantHitDamageTypes(ALTFIRE_FIREMODE)=Class'KFDT_Blast_HRG_CranialPopper'
|
||||
FireInterval(ALTFIRE_FIREMODE)=+0.25
|
||||
AmmoCost(ALTFIRE_FIREMODE)=100
|
||||
AmmoCost(ALTFIRE_FIREMODE)=25
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_CranialPopper'
|
||||
|
844
KFGameContent/Classes/KFWeap_HRG_Warthog.uc
Normal file
844
KFGameContent/Classes/KFWeap_HRG_Warthog.uc
Normal file
@ -0,0 +1,844 @@
|
||||
//=============================================================================
|
||||
// KFWeap_HRG_Warthog
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_HRG_Warthog extends KFWeap_ThrownBase;
|
||||
|
||||
`define AUTOTURRET_MIC_LED_INDEX 2
|
||||
|
||||
const DETONATE_FIREMODE = 5; // NEW - IronSights Key
|
||||
|
||||
var(Animations) const editconst name DetonateAnim;
|
||||
var(Animations) const editconst name DetonateLastAnim;
|
||||
|
||||
/** Sound to play upon successful detonation */
|
||||
var() AkEvent DetonateAkEvent;
|
||||
|
||||
/** Strenght applied to forward dir to get the throwing velocity */
|
||||
var const float ThrowStrength;
|
||||
/** Max num of turrets that can be deployed */
|
||||
var const byte MaxTurretsDeployed;
|
||||
/** Offset to spawn the dron (screen coordinates) */
|
||||
var const vector TurretSpawnOffset;
|
||||
|
||||
var transient byte NumDeployedTurrets;
|
||||
var transient KFPlayerController KFPC;
|
||||
|
||||
/** If the turret is in a state available for throw another to fix some animation issues. */
|
||||
var transient bool bTurretReadyToUse;
|
||||
|
||||
var repnotify float CurrentAmmoPercentage;
|
||||
|
||||
const TransitionParamName = 'transition_full_to_empty';
|
||||
const EmptyParamName = 'Blinking_0_off___1_on';
|
||||
|
||||
var transient bool bDetonateLocked;
|
||||
|
||||
replication
|
||||
{
|
||||
if( bNetDirty )
|
||||
NumDeployedTurrets, CurrentAmmoPercentage, bTurretReadyToUse;
|
||||
}
|
||||
|
||||
simulated event ReplicatedEvent(name VarName)
|
||||
{
|
||||
if (VarName == nameof(CurrentAmmoPercentage))
|
||||
{
|
||||
UpdateMaterialColor(CurrentAmmoPercentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.ReplicatedEvent(VarName);
|
||||
}
|
||||
}
|
||||
|
||||
simulated event PreBeginPlay()
|
||||
{
|
||||
local class<KFWeap_HRG_WarthogWeapon> WeaponClass;
|
||||
|
||||
super.PreBeginPlay();
|
||||
|
||||
WeaponClass = class<KFWeap_HRG_WarthogWeapon> (DynamicLoadObject(class'KFPawn_HRG_Warthog'.default.WeaponDefinition.default.WeaponClassPath, class'Class'));
|
||||
WeaponClass.static.TriggerAsyncContentLoad(WeaponClass);
|
||||
}
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
KFPC = KFPlayerController(Instigator.Controller);
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
}
|
||||
}
|
||||
|
||||
/** Route ironsight player input to detonate */
|
||||
simulated function SetIronSights(bool bNewIronSights)
|
||||
{
|
||||
if ( !Instigator.IsLocallyControlled() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( bNewIronSights )
|
||||
{
|
||||
StartFire(DETONATE_FIREMODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
StopFire(DETONATE_FIREMODE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Overridded to add spawned turret to list of spawned turrets */
|
||||
simulated function Projectile ProjectileFire()
|
||||
{
|
||||
local vector SpawnLocation, SpawnDirection;
|
||||
local KFPawn_HRG_Warthog SpawnedActor;
|
||||
|
||||
if (Role != ROLE_Authority)
|
||||
{
|
||||
return none;
|
||||
}
|
||||
|
||||
if (CurrentFireMode == DEFAULT_FIREMODE)
|
||||
{
|
||||
GetTurretSpawnLocationAndDir(SpawnLocation, SpawnDirection);
|
||||
SpawnedActor = Spawn(class'KFPawn_HRG_Warthog', self,, SpawnLocation + (TurretSpawnOffset >> Rotation), Rotation,,true);
|
||||
|
||||
if( SpawnedActor != none )
|
||||
{
|
||||
SpawnedActor.OwnerWeapon = self;
|
||||
SpawnedActor.SetPhysics(PHYS_Falling);
|
||||
SpawnedActor.Velocity = SpawnDirection * ThrowStrength;
|
||||
SpawnedActor.UpdateInstigator(Instigator);
|
||||
SpawnedActor.UpdateWeaponUpgrade(CurrentWeaponUpgradeIndex);
|
||||
SpawnedActor.SetTurretState(ETS_Throw);
|
||||
|
||||
if (KFPC != none)
|
||||
{
|
||||
KFPC.DeployedTurrets.AddItem( SpawnedActor );
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
}
|
||||
|
||||
bTurretReadyToUse = false;
|
||||
bForceNetUpdate = true;
|
||||
}
|
||||
|
||||
return none;
|
||||
}
|
||||
|
||||
return super.ProjectileFire();
|
||||
}
|
||||
|
||||
simulated function GetTurretSpawnLocationAndDir(out vector SpawnLocation, out vector SpawnDirection)
|
||||
{
|
||||
local vector StartTrace, EndTrace, RealStartLoc, AimDir;
|
||||
local ImpactInfo TestImpact;
|
||||
local vector DirA, DirB;
|
||||
local Quat Q;
|
||||
|
||||
// This is where we would start an instant trace. (what CalcWeaponFire uses)
|
||||
StartTrace = GetSafeStartTraceLocation();
|
||||
AimDir = Vector(GetAdjustedAim( StartTrace ));
|
||||
|
||||
// this is the location where the projectile is spawned.
|
||||
RealStartLoc = GetPhysicalFireStartLoc(AimDir);
|
||||
|
||||
if( StartTrace != RealStartLoc )
|
||||
{
|
||||
// if projectile is spawned at different location of crosshair,
|
||||
// then simulate an instant trace where crosshair is aiming at, Get hit info.
|
||||
EndTrace = StartTrace + AimDir * GetTraceRange();
|
||||
TestImpact = CalcWeaponFire( StartTrace, EndTrace );
|
||||
// Store the original aim direction without correction
|
||||
DirB = AimDir;
|
||||
|
||||
// Then we realign projectile aim direction to match where the crosshair did hit.
|
||||
AimDir = Normal(TestImpact.HitLocation - RealStartLoc);
|
||||
|
||||
// Store the desired corrected aim direction
|
||||
DirA = AimDir;
|
||||
|
||||
// Clamp the maximum aim adjustment for the AimDir so you don't get wierd
|
||||
// cases where the projectiles velocity is going WAY off of where you
|
||||
// are aiming. This can happen if you are really close to what you are
|
||||
// shooting - Ramm
|
||||
if ( (DirA dot DirB) < MaxAimAdjust_Cos )
|
||||
{
|
||||
Q = QuatFromAxisAndAngle(Normal(DirB cross DirA), MaxAimAdjust_Angle);
|
||||
AimDir = QuatRotateVector(Q,DirB);
|
||||
}
|
||||
}
|
||||
|
||||
SpawnDirection = AimDir;
|
||||
SpawnLocation = RealStartLoc;
|
||||
}
|
||||
|
||||
/** Detonates the oldest turret */
|
||||
simulated function Detonate(optional bool bKeepTurret = false)
|
||||
{
|
||||
local int i;
|
||||
local array<Actor> TurretsCopy;
|
||||
|
||||
// auto switch weapon when out of ammo and after detonating the last deployed turret
|
||||
if( Role == ROLE_Authority )
|
||||
{
|
||||
TurretsCopy = KFPC.DeployedTurrets;
|
||||
for (i = 0; i < TurretsCopy.Length; i++)
|
||||
{
|
||||
if (bKeepTurret && i == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (KFPawn_HRG_Warthog(TurretsCopy[i]) != none)
|
||||
{
|
||||
KFPawn_HRG_Warthog(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
||||
}
|
||||
else if (KFPawn_Autoturret(TurretsCopy[i]) != none)
|
||||
{
|
||||
KFPawn_Autoturret(TurretsCopy[i]).SetTurretState(ETS_Detonate);
|
||||
}
|
||||
}
|
||||
|
||||
KFPC.DeployedTurrets.Remove(bKeepTurret ? 1 : 0, KFPC.DeployedTurrets.Length);
|
||||
|
||||
SetReadyToUse(true);
|
||||
|
||||
if( !HasAnyAmmo() && NumDeployedTurrets == 0 )
|
||||
{
|
||||
if( CanSwitchWeapons() )
|
||||
{
|
||||
Instigator.Controller.ClientSwitchToBestWeapon(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes a turret from the list using either an index or an actor and updates NumDeployedTurrets */
|
||||
function RemoveDeployedTurret( optional int Index = INDEX_NONE, optional Actor TurretActor )
|
||||
{
|
||||
if( Index == INDEX_NONE )
|
||||
{
|
||||
if( TurretActor != none )
|
||||
{
|
||||
Index = KFPC.DeployedTurrets.Find( TurretActor );
|
||||
}
|
||||
}
|
||||
|
||||
if( Index != INDEX_NONE )
|
||||
{
|
||||
KFPC.DeployedTurrets.Remove( Index, 1 );
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
bForceNetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
|
||||
{
|
||||
local int i;
|
||||
local Actor WeaponPawn;
|
||||
|
||||
super.SetOriginalValuesFromPickup( PickedUpWeapon );
|
||||
|
||||
if (PickedUpWeapon.KFPlayer != none && PickedUpWeapon.KFPlayer != KFPC)
|
||||
{
|
||||
for (i = 0; i < PickedUpWeapon.KFPlayer.DeployedTurrets.Length; i++)
|
||||
{
|
||||
KFPC.DeployedTurrets.AddItem(PickedUpWeapon.KFPlayer.DeployedTurrets[i]);
|
||||
}
|
||||
|
||||
PickedUpWeapon.KFPlayer.DeployedTurrets.Remove(0, PickedUpWeapon.KFPlayer.DeployedTurrets.Length);
|
||||
}
|
||||
|
||||
if (KFPC.DeployedTurrets.Length > 1)
|
||||
{
|
||||
Detonate(true);
|
||||
}
|
||||
|
||||
PickedUpWeapon.KFPlayer = none;
|
||||
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
bForceNetUpdate = true;
|
||||
|
||||
for( i = 0; i < NumDeployedTurrets; ++i )
|
||||
{
|
||||
WeaponPawn = KFPC.DeployedTurrets[i];
|
||||
if (WeaponPawn != none)
|
||||
{
|
||||
// charge alerts (beep, light) need current instigator
|
||||
WeaponPawn.Instigator = Instigator;
|
||||
WeaponPawn.SetOwner(self);
|
||||
|
||||
if (Instigator.Controller != none)
|
||||
{
|
||||
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]) != none)
|
||||
{
|
||||
KFPawn_HRG_Warthog(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
||||
}
|
||||
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[i]) != none)
|
||||
{
|
||||
KFPawn_Autoturret(KFPC.DeployedTurrets[i]).InstigatorController = Instigator.Controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drop this item out in to the world
|
||||
*/
|
||||
function DropFrom(vector StartLocation, vector StartVelocity)
|
||||
{
|
||||
local DroppedPickup P;
|
||||
|
||||
// Offset spawn closer to eye location
|
||||
StartLocation.Z += Instigator.BaseEyeHeight / 2;
|
||||
|
||||
// for some reason, Inventory::DropFrom removes weapon from inventory whether it was able to spawn the pickup or not.
|
||||
// we only want the weapon removed from inventory if pickup was successfully spawned, so instead of calling the supers,
|
||||
// do all the super functionality here.
|
||||
|
||||
if( !CanThrow() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( DroppedPickupClass == None || DroppedPickupMesh == None )
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// the last bool param is to prevent collision from preventing spawns
|
||||
P = Spawn(DroppedPickupClass,,, StartLocation,,,true);
|
||||
if( P == None )
|
||||
{
|
||||
// if we can't spawn the pickup (likely for collision reasons),
|
||||
// just return without removing from inventory or destroying, which removes from inventory
|
||||
PlayerController(Instigator.Controller).ReceiveLocalizedMessage( class'KFLocalMessage_Game', GMT_FailedDropInventory );
|
||||
return;
|
||||
}
|
||||
|
||||
if( Instigator != None && Instigator.InvManager != None )
|
||||
{
|
||||
Instigator.InvManager.RemoveFromInventory(Self);
|
||||
|
||||
if( Instigator.IsAliveAndWell() && !Instigator.InvManager.bPendingDelete )
|
||||
{
|
||||
`DialogManager.PlayDropWeaponDialog( KFPawn(Instigator) );
|
||||
}
|
||||
}
|
||||
|
||||
SetupDroppedPickup( P, StartVelocity );
|
||||
|
||||
KFDroppedPickup(P).PreviousOwner = KFPlayerController(Instigator.Controller);
|
||||
|
||||
Instigator = None;
|
||||
GotoState('');
|
||||
|
||||
AIController = None;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this weapon uses a secondary ammo pool
|
||||
*/
|
||||
static simulated event bool UsesAmmo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
|
||||
{
|
||||
if( FireModeNum == DETONATE_FIREMODE )
|
||||
{
|
||||
return NumDeployedTurrets > 0;
|
||||
}
|
||||
|
||||
return super.HasAmmo( FireModeNum, Amount );
|
||||
}
|
||||
|
||||
simulated function BeginFire( byte FireModeNum )
|
||||
{
|
||||
local bool bCanDetonate;
|
||||
|
||||
// Clear any pending detonate if we pressed the main fire
|
||||
// That prevents strange holding right click behaviour and sound issues
|
||||
if (FireModeNum == DEFAULT_FIREMODE)
|
||||
{
|
||||
ClearPendingFire(DETONATE_FIREMODE);
|
||||
}
|
||||
|
||||
if (FireModeNum == DETONATE_FIREMODE )
|
||||
{
|
||||
if (bDetonateLocked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (NumDeployedTurrets > 0 && bTurretReadyToUse)
|
||||
{
|
||||
bCanDetonate = NumDeployedTurrets > 0;
|
||||
|
||||
if (bCanDetonate)
|
||||
{
|
||||
PrepareAndDetonate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KFPC != none)
|
||||
{
|
||||
NumDeployedTurrets = KFPC.DeployedTurrets.Length;
|
||||
}
|
||||
|
||||
if (FireModeNum == DEFAULT_FIREMODE
|
||||
&& NumDeployedTurrets >= MaxTurretsDeployed
|
||||
&& HasAnyAmmo())
|
||||
{
|
||||
if (!bTurretReadyToUse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PrepareAndDetonate();
|
||||
}
|
||||
|
||||
super.BeginFire( FireModeNum );
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PrepareAndDetonate()
|
||||
{
|
||||
local name DetonateAnimName;
|
||||
local float AnimDuration;
|
||||
local bool bInSprintState;
|
||||
DetonateAnimName = ShouldPlayLastAnims() ? DetonateLastAnim : DetonateAnim;
|
||||
AnimDuration = MySkelMesh.GetAnimLength( DetonateAnimName );
|
||||
bInSprintState = IsInState( 'WeaponSprinting' );
|
||||
|
||||
if( WorldInfo.NetMode != NM_DedicatedServer )
|
||||
{
|
||||
if( NumDeployedTurrets > 0 )
|
||||
{
|
||||
PlaySoundBase( DetonateAkEvent, true );
|
||||
}
|
||||
|
||||
if( bInSprintState )
|
||||
{
|
||||
AnimDuration *= 0.25f;
|
||||
PlayAnimation( DetonateAnimName, AnimDuration );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayAnimation( DetonateAnimName );
|
||||
}
|
||||
}
|
||||
|
||||
if( Role == ROLE_Authority )
|
||||
{
|
||||
Detonate();
|
||||
}
|
||||
|
||||
IncrementFlashCount();
|
||||
|
||||
if( bInSprintState )
|
||||
{
|
||||
SetTimer( AnimDuration * 0.8f, false, nameof(PlaySprintStart) );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTimer( AnimDuration * 0.5f, false, nameof(GotoActiveState) );
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing, as we have no alt fire mode
|
||||
simulated function AltFireMode();
|
||||
|
||||
/** Allow weapons with abnormal state transitions to always use zed time resist*/
|
||||
simulated function bool HasAlwaysOnZedTimeResist()
|
||||
{
|
||||
return GetStateName() != FiringStatesArray[BASH_FIREMODE];
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State Active
|
||||
* A Weapon this is being held by a pawn should be in the active state. In this state,
|
||||
* a weapon should loop any number of idle animations, as well as check the PendingFire flags
|
||||
* to see if a shot has been fired.
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state Active
|
||||
{
|
||||
/** Overridden to prevent playing fidget if play has no more ammo */
|
||||
simulated function bool CanPlayIdleFidget(optional bool bOnReload)
|
||||
{
|
||||
if( !HasAmmo(0) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.CanPlayIdleFidget( bOnReload );
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State WeaponDetonating
|
||||
* The weapon is in this state while detonating a charge
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated function GotoActiveState();
|
||||
|
||||
simulated state WeaponDetonating
|
||||
{
|
||||
ignores AllowSprinting;
|
||||
|
||||
simulated event BeginState( name PreviousStateName )
|
||||
{
|
||||
PrepareAndDetonate();
|
||||
}
|
||||
|
||||
simulated function GotoActiveState()
|
||||
{
|
||||
GotoState('Active');
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State WeaponThrowing
|
||||
* Handles throwing weapon (similar to state GrenadeFiring)
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state WeaponThrowing
|
||||
{
|
||||
/** Never refires. Must re-enter this state instead. */
|
||||
simulated function bool ShouldRefire()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function EndState(Name NextStateName)
|
||||
{
|
||||
local KFPerk InstigatorPerk;
|
||||
|
||||
Super.EndState(NextStateName);
|
||||
|
||||
//Targeted fix for Demolitionist w/ the C4. It should remain in zed time while waiting on
|
||||
// the fake reload to be triggered. This will return 0 for other perks.
|
||||
InstigatorPerk = GetPerk();
|
||||
if( InstigatorPerk != none )
|
||||
{
|
||||
SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State WeaponEquipping
|
||||
* The Weapon is in this state while transitioning from Inactive to Active state.
|
||||
* Typically, the weapon will remain in this state while its selection animation is being played.
|
||||
* While in this state, the weapon cannot be fired.
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state WeaponEquipping
|
||||
{
|
||||
simulated event BeginState( name PreviousStateName )
|
||||
{
|
||||
super.BeginState( PreviousStateName );
|
||||
|
||||
// perform a "reload" if we refilled our ammo from empty while it was unequipped
|
||||
if( !HasAmmo(THROW_FIREMODE) && HasSpareAmmo() )
|
||||
{
|
||||
PerformArtificialReload();
|
||||
}
|
||||
StopFire(DETONATE_FIREMODE);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State WeaponPuttingDown
|
||||
* Putting down weapon in favor of a new one.
|
||||
* Weapon is transitioning to the Inactive state.
|
||||
*
|
||||
* Detonating while putting down causes C4 not to be put down, which causes problems, so let's
|
||||
* just ignore SetIronSights, which causes detonation
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state WeaponPuttingDown
|
||||
{
|
||||
ignores SetIronSights;
|
||||
|
||||
simulated event BeginState( name PreviousStateName )
|
||||
{
|
||||
super.BeginState( PreviousStateName );
|
||||
StopFire(DETONATE_FIREMODE);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* @name Trader
|
||||
*********************************************************************************************/
|
||||
|
||||
/** Returns trader filter index based on weapon type */
|
||||
static simulated event EFilterTypeUI GetTraderFilter()
|
||||
{
|
||||
return FT_Explosive;
|
||||
}
|
||||
|
||||
function CheckTurretAmmo()
|
||||
{
|
||||
local float Percentage;
|
||||
local KFWeapon Weapon;
|
||||
local KFPawn KFP;
|
||||
|
||||
if (Role == Role_Authority)
|
||||
{
|
||||
if (KFPC == none)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (KFPC.DeployedTurrets.Length > 0)
|
||||
{
|
||||
if (KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]) != none)
|
||||
{
|
||||
Weapon = KFWeapon(KFPawn_HRG_Warthog(KFPC.DeployedTurrets[0]).Weapon);
|
||||
}
|
||||
else if (KFPawn_Autoturret(KFPC.DeployedTurrets[0]) != none)
|
||||
{
|
||||
Weapon = KFWeapon(KFPawn_Autoturret(KFPC.DeployedTurrets[0]).Weapon);
|
||||
}
|
||||
|
||||
if (Weapon != none)
|
||||
{
|
||||
Percentage = float(Weapon.AmmoCount[0]) / Weapon.MagazineCapacity[0];
|
||||
if (Percentage != CurrentAmmoPercentage)
|
||||
{
|
||||
CurrentAmmoPercentage = Percentage;
|
||||
bNetDirty = true;
|
||||
|
||||
if (WorldInfo.NetMode == NM_Standalone)
|
||||
{
|
||||
UpdateMaterialColor(CurrentAmmoPercentage);
|
||||
}
|
||||
else
|
||||
{
|
||||
KFP = KFPawn(Instigator);
|
||||
if (KFP != none)
|
||||
{
|
||||
KFP.OnWeaponSpecialAction( 1 + (CurrentAmmoPercentage * 100) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SetReadyToUse(bool bReady)
|
||||
{
|
||||
if (bTurretReadyToUse != bReady)
|
||||
{
|
||||
bTurretReadyToUse = bReady;
|
||||
bNetDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
super.Tick(DeltaTime);
|
||||
|
||||
if (Role == Role_Authority)
|
||||
{
|
||||
CheckTurretAmmo();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function UpdateMaterialColor(float Percentage)
|
||||
{
|
||||
if (NumDeployedTurrets == 0)
|
||||
{
|
||||
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(EmptyParamName, 0);
|
||||
}
|
||||
else if (Percentage >= 0)
|
||||
{
|
||||
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(TransitionParamName, 1.0f - Percentage);
|
||||
WeaponMICs[`AUTOTURRET_MIC_LED_INDEX].SetScalarParameterValue(EmptyParamName, Percentage == 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function SetWeaponUpgradeLevel(int WeaponUpgradeLevel)
|
||||
{
|
||||
local Actor Turret;
|
||||
local KFPawn_HRG_Warthog TurretPawn;
|
||||
|
||||
super.SetWeaponUpgradeLevel(WeaponUpgradeLevel);
|
||||
|
||||
if (KFPC != none)
|
||||
{
|
||||
foreach KFPC.DeployedTurrets(Turret)
|
||||
{
|
||||
TurretPawn = KFPawn_HRG_Warthog(Turret);
|
||||
if (TurretPawn != none)
|
||||
{
|
||||
TurretPawn.UpdateWeaponUpgrade(WeaponUpgradeLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GRENADE FIRING
|
||||
* There's a bug that alt fire interrupts the grenade anim at any moment,
|
||||
* This avoids being able to altfire until the throw animation ends or the
|
||||
* interrupt notify is reached.
|
||||
*/
|
||||
|
||||
simulated state GrenadeFiring
|
||||
{
|
||||
simulated function EndState(Name NextStateName)
|
||||
{
|
||||
ClearDetonateLock();
|
||||
Super.EndState(NextStateName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Play animation at the start of the GrenadeFiring state */
|
||||
simulated function PlayGrenadeThrow()
|
||||
{
|
||||
local name WeaponFireAnimName;
|
||||
local float InterruptTime;
|
||||
|
||||
PlayFiringSound(CurrentFireMode);
|
||||
|
||||
if( Instigator != none && Instigator.IsFirstPerson() )
|
||||
{
|
||||
WeaponFireAnimName = GetGrenadeThrowAnim();
|
||||
|
||||
if ( WeaponFireAnimName != '' )
|
||||
{
|
||||
InterruptTime = MySkelMesh.GetAnimInterruptTime(WeaponFireAnimName);
|
||||
PlayAnimation(WeaponFireAnimName, MySkelMesh.GetAnimLength(WeaponFireAnimName),,FireTweenTime);
|
||||
|
||||
bDetonateLocked = true;
|
||||
SetTimer(InterruptTime, false, nameof(ClearDetonateLock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function ClearDetonateLock()
|
||||
{
|
||||
bDetonateLocked = false;
|
||||
ClearTimer(nameof(ClearDetonateLock));
|
||||
}
|
||||
|
||||
/***/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Trader
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Allows weapon to calculate its own stats for display in trader */
|
||||
static simulated event SetTraderWeaponStats( out array<STraderItemWeaponStats> WeaponStats )
|
||||
{
|
||||
super.SetTraderWeaponStats(WeaponStats);
|
||||
|
||||
WeaponStats.Length = 4;
|
||||
|
||||
WeaponStats[0].StatType = TWS_Damage;
|
||||
WeaponStats[0].StatValue = class'KFWeap_HRG_WarthogWeapon'.static.CalculateTraderWeaponStatDamage();
|
||||
|
||||
WeaponStats[1].StatType = TWS_Penetration;
|
||||
WeaponStats[1].StatValue = class'KFWeap_HRG_WarthogWeapon'.default.PenetrationPower[DEFAULT_FIREMODE];
|
||||
|
||||
WeaponStats[2].StatType = TWS_Range;
|
||||
// This is now set in native since EffectiveRange has been moved to KFWeaponDefinition
|
||||
// WeaponStats[2].StatValue = CalculateTraderWeaponStatRange();
|
||||
|
||||
WeaponStats[3].StatType = TWS_RateOfFire;
|
||||
WeaponStats[3].StatValue = class'KFWeap_HRG_WarthogWeapon'.static.CalculateTraderWeaponStatFireRate();
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// start in detonate mode so that an attempt to detonate before any charges are thrown results in
|
||||
// the proper third-person anim
|
||||
CurrentFireMode=DETONATE_FIREMODE
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=6.0,Y=2,Z=-4)
|
||||
FireOffset=(X=0,Y=0)
|
||||
TurretSpawnOffset=(X=0, Y=15, Z=-50)
|
||||
|
||||
// Content
|
||||
PackageKey="HRG_Warthog"
|
||||
FirstPersonMeshName="Wep_1P_HRG_Warthog_MESH.Wep_1P_Warthog_Rig"
|
||||
FirstPersonAnimSetNames(0)="Wep_1P_HRG_Warthog_ANIM.Wep_1P_HRG_Warthog_ANIM"
|
||||
PickupMeshName="wep_3p_hrg_warthog_mesh.Wep_HRG_Warthog_Pickup"
|
||||
AttachmentArchetypeName="WEP_HRG_Warthog_ARCH.Wep_HRG_Warthog_3P"
|
||||
|
||||
// Anim
|
||||
FireAnim=C4_Throw
|
||||
FireLastAnim=C4_Throw_Last
|
||||
|
||||
DetonateAnim=Detonate
|
||||
DetonateLastAnim=Detonate_Last
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=1
|
||||
SpareAmmoCapacity[0]=3
|
||||
InitialSpareMags[0]=1
|
||||
AmmoPickupScale[0]=1.0
|
||||
|
||||
// THROW_FIREMODE
|
||||
FireInterval(THROW_FIREMODE)=0.25
|
||||
FireModeIconPaths(THROW_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Drone'
|
||||
|
||||
// DETONATE_FIREMODE
|
||||
FiringStatesArray(DETONATE_FIREMODE)=WeaponDetonating
|
||||
WeaponFireTypes(DETONATE_FIREMODE)=EWFT_Custom
|
||||
AmmoCost(DETONATE_FIREMODE)=0
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_Warthog'
|
||||
InstantHitDamage(BASH_FIREMODE)=26
|
||||
|
||||
// Inventory / Grouping
|
||||
InventoryGroup=IG_Equipment
|
||||
GroupPriority=11
|
||||
WeaponSelectTexture=Texture2D'WEP_UI_HRG_Warthog_TEX.UI_WeaponSelect_HRG_Warthog'
|
||||
InventorySize=3
|
||||
|
||||
DetonateAkEvent=AkEvent'WW_WEP_HRG_Warthog.Play_WEP_HRG_Warthog_Detonate_Trigger'
|
||||
|
||||
// Weapon Upgrade stat boosts
|
||||
//WeaponUpgrades[1]=(IncrementDamage=1.05f,IncrementWeight=1)
|
||||
//WeaponUpgrades[2]=(IncrementDamage=1.1f,IncrementWeight=2)
|
||||
//WeaponUpgrades[3]=(IncrementDamage=1.15f,IncrementWeight=3)
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
MaxTurretsDeployed=1
|
||||
NumDeployedTurrets=0
|
||||
ThrowStrength=1350.0f
|
||||
bTurretReadyToUse=true
|
||||
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Damage1, Scale=1.3f), (Stat=EWUS_Weight, Add=2)))
|
||||
NumBloodMapMaterials=3
|
||||
|
||||
bDetonateLocked=false
|
||||
CurrentAmmoPercentage=-1.0f
|
||||
}
|
492
KFGameContent/Classes/KFWeap_HRG_WarthogWeapon.uc
Normal file
492
KFGameContent/Classes/KFWeap_HRG_WarthogWeapon.uc
Normal file
@ -0,0 +1,492 @@
|
||||
//=============================================================================
|
||||
// KFWeap_HRG_WarthogWeapon
|
||||
//=============================================================================
|
||||
// An HRG Warthog Grenade Launcher
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2022 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_HRG_WarthogWeapon extends KFWeap_GrenadeLauncher_Base;
|
||||
|
||||
var KFPawn_HRG_Warthog InstigatorDrone;
|
||||
|
||||
// Used to calculate parabola when spawn projectile
|
||||
var KFPawn_Monster CurrentTarget;
|
||||
|
||||
// Used to force distance when throwing projectiles when the pawn dies
|
||||
var float CurrentDistanceProjectile;
|
||||
|
||||
var float DistanceParabolicLaunch;
|
||||
|
||||
var transient float LastTimeFireSeconds;
|
||||
|
||||
simulated event PreBeginPlay()
|
||||
{
|
||||
super.PreBeginPlay();
|
||||
StartLoadWeaponContent();
|
||||
}
|
||||
|
||||
simulated state WeaponFiring
|
||||
{
|
||||
simulated function EndState(Name NextStateName)
|
||||
{
|
||||
local Pawn OriginalInstigator;
|
||||
|
||||
// The Instigator for this weapon is the Player owning the weapon (for Perk, damage, etc,. calculations)
|
||||
// But for Weapon Firing end state logic we need to point to the real Drone Pawn so we don't mess
|
||||
// With whichever weapon the Player had equipped at that point
|
||||
|
||||
OriginalInstigator = Instigator;
|
||||
|
||||
Instigator = InstigatorDrone;
|
||||
|
||||
super.EndState(NextStateName);
|
||||
|
||||
Instigator = OriginalInstigator;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function FireAmmunition()
|
||||
{
|
||||
CurrentFireMode = DEFAULT_FIREMODE;
|
||||
super.FireAmmunition();
|
||||
}
|
||||
|
||||
simulated function GetMuzzleLocAndRot(out vector MuzzleLoc, out rotator MuzzleRot)
|
||||
{
|
||||
if (KFSkeletalMeshComponent(Mesh).GetSocketWorldLocationAndRotation('MuzzleFlash', MuzzleLoc, MuzzleRot) == false)
|
||||
{
|
||||
`Log("MuzzleFlash not found!");
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Projectile ProjectileFire()
|
||||
{
|
||||
local vector RealStartLoc, AimDir, TargetLocation;
|
||||
local rotator AimRot;
|
||||
local class<KFProjectile> MyProjectileClass;
|
||||
|
||||
// tell remote clients that we fired, to trigger effects
|
||||
|
||||
if ( ShouldIncrementFlashCountOnFire() )
|
||||
{
|
||||
IncrementFlashCount();
|
||||
}
|
||||
|
||||
MyProjectileClass = GetKFProjectileClass();
|
||||
|
||||
if( Role == ROLE_Authority || (MyProjectileClass.default.bUseClientSideHitDetection
|
||||
&& MyProjectileClass.default.bNoReplicationToInstigator && Instigator != none
|
||||
&& Instigator.IsLocallyControlled()) )
|
||||
{
|
||||
GetMuzzleLocAndRot(RealStartLoc, AimRot);
|
||||
|
||||
if (CurrentTarget != none)
|
||||
{
|
||||
TargetLocation = CurrentTarget.Location;
|
||||
TargetLocation.Z += CurrentTarget.GetCollisionHeight() * 0.5f; // Add an offset on the location, so it matches correctly
|
||||
|
||||
AimDir = Normal(TargetLocation - RealStartLoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
AimDir = Vector(Owner.Rotation);
|
||||
}
|
||||
|
||||
return SpawnAllProjectiles(MyProjectileClass, RealStartLoc, AimDir);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local KFProjectile SpawnedProjectile;
|
||||
local int ProjDamage;
|
||||
local Pawn OriginalInstigator;
|
||||
local vector TargetLocation, Distance;
|
||||
local float HorizontalDistance, TermA, TermB, TermC, InitialSpeed;
|
||||
|
||||
/*
|
||||
* Instigator issues here. The instigator of the weapon here is the PlayerController which needs to replicate the projectile.
|
||||
* We spawn it with that instigator, then we change to be able to be able to apply perk effects.
|
||||
*/
|
||||
|
||||
// Spawn projectile
|
||||
|
||||
OriginalInstigator = Instigator;
|
||||
Instigator = InstigatorDrone;
|
||||
|
||||
SpawnedProjectile = Spawn( KFProjClass, self,, RealStartLoc);
|
||||
|
||||
if( SpawnedProjectile != none && !SpawnedProjectile.bDeleteMe )
|
||||
{
|
||||
if (CurrentTarget != none)
|
||||
{
|
||||
//TargetLocation = CurrentTarget.Mesh.GetBoneLocation('Spine1');
|
||||
TargetLocation = CurrentTarget.Location;
|
||||
TargetLocation.Z += CurrentTarget.GetCollisionHeight() * 0.5f; // Add an offset on the location, so it matches correctly
|
||||
}
|
||||
else if (CurrentDistanceProjectile > 0.f)
|
||||
{
|
||||
TargetLocation = RealStartLoc + AimDir * CurrentDistanceProjectile;
|
||||
TargetLocation.Z -= InstigatorDrone.DeployHeight; // We target more or less the ground
|
||||
}
|
||||
|
||||
//CurrentTarget.DrawDebugSphere(TargetLocation, 100, 10, 0, 255, 0, true);
|
||||
|
||||
Distance = TargetLocation - RealStartLoc;
|
||||
Distance.Z = 0.f;
|
||||
HorizontalDistance = VSize(Distance); // 2D
|
||||
|
||||
// If bigger than minimal horizontal distance, and drone is higher than target..
|
||||
if (HorizontalDistance > DistanceParabolicLaunch
|
||||
&& RealStartLoc.Z > TargetLocation.Z)
|
||||
{
|
||||
// Parabolic launch calculation
|
||||
// Tweak speed so it can fall on the TargetLocation, use parabolic launch, we assume an Angle = 0
|
||||
// We transform from 3D to 2D, assume horizontal start is 0, and horizontal distance is the modulus of the vector distance to target
|
||||
|
||||
// Angle = 0 -> sin(0) -> 0 so no need to apply any initial Y velocity
|
||||
|
||||
// ( ( Y - Y0 ) / ( 0.5 * gravity ) )
|
||||
TermA = (TargetLocation.Z - RealStartLoc.Z) / (-11.5f * 0.5f * 100.f); // gravity to cm/s
|
||||
|
||||
// ( X - X0 )^2 / V^2 -> assume XO is 0
|
||||
TermB = HorizontalDistance * HorizontalDistance;
|
||||
|
||||
TermC = TermB / TermA;
|
||||
|
||||
InitialSpeed = Sqrt(TermC);
|
||||
|
||||
AimDir = Normal(Distance);
|
||||
AimDir.Z = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No parabollic, so we force Speed
|
||||
if (RealStartLoc.Z < TargetLocation.Z)
|
||||
{
|
||||
InitialSpeed = 3000.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
InitialSpeed = 1000.f;
|
||||
}
|
||||
}
|
||||
|
||||
SpawnedProjectile.Speed = InitialSpeed;
|
||||
SpawnedProjectile.MaxSpeed = 0;
|
||||
SpawnedProjectile.TerminalVelocity = InitialSpeed * 2.f;
|
||||
SpawnedProjectile.TossZ = 0.f;
|
||||
|
||||
// Mirror damage and damage type from weapon. This is set on the server only and
|
||||
// these properties are replicated via TakeHitInfo
|
||||
if ( InstantHitDamage.Length > CurrentFireMode && InstantHitDamageTypes.Length > CurrentFireMode )
|
||||
{
|
||||
ProjDamage = GetModifiedDamage(CurrentFireMode);
|
||||
SpawnedProjectile.Damage = ProjDamage;
|
||||
SpawnedProjectile.MyDamageType = InstantHitDamageTypes[CurrentFireMode];
|
||||
}
|
||||
|
||||
SpawnedProjectile.UpgradeDamageMod = GetUpgradeDamageMod();
|
||||
|
||||
SpawnedProjectile.Init( AimDir );
|
||||
}
|
||||
|
||||
Instigator = OriginalInstigator;
|
||||
|
||||
return SpawnedProjectile;
|
||||
}
|
||||
|
||||
simulated function IncrementFlashCount()
|
||||
{
|
||||
local KFPawn P;
|
||||
P = KFPawn(Owner);
|
||||
|
||||
if( P != None )
|
||||
{
|
||||
P.IncrementFlashCount( Self, CurrentFireMode );
|
||||
}
|
||||
}
|
||||
|
||||
simulated function Fire()
|
||||
{
|
||||
if (HasAmmo(DEFAULT_FIREMODE))
|
||||
{
|
||||
//if (WorldInfo.TimeSeconds - LastTimeFireSeconds > GetFireInterval(DEFAULT_FIREMODE))
|
||||
//{
|
||||
LastTimeFireSeconds = WorldInfo.TimeSeconds;
|
||||
|
||||
SendToFiringState(DEFAULT_FIREMODE);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function StopFire(byte FireModeNum)
|
||||
{
|
||||
super.StopFire(FireModeNum);
|
||||
|
||||
GoToState('Inactive');
|
||||
}
|
||||
|
||||
simulated function bool ShouldRefire()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function ForceExplosionReplicateKill(Vector HitLocation, KFProj_HighExplosive_HRG_Warthog Proj)
|
||||
{
|
||||
HandleClientProjectileExplosion(HitLocation, Proj);
|
||||
|
||||
Proj.Shutdown(); // cleanup/destroy projectile
|
||||
}
|
||||
|
||||
simulated function ForceExplosionReplicate(Actor Other, Vector HitLocation, Vector HitNormal, KFProj_HighExplosive_HRG_Warthog Proj)
|
||||
{
|
||||
HandleClientProjectileExplosion(HitLocation, Proj);
|
||||
|
||||
if (Proj.ExplosionTemplate != None)
|
||||
{
|
||||
Proj.TriggerExplosion(HitLocation, HitNormal, Other);
|
||||
}
|
||||
|
||||
Proj.Shutdown(); // cleanup/destroy projectile
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts playing looping FireSnd only (used for switching sounds in Zedtime)
|
||||
*/
|
||||
simulated function StartLoopingFireSound(byte FireModeNum)
|
||||
{
|
||||
if ( FireModeNum < bLoopingFireSnd.Length && bLoopingFireSnd[FireModeNum] && !ShouldForceSingleFireSound() )
|
||||
{
|
||||
bPlayingLoopingFireSnd = true;
|
||||
KFPawn(Owner).SetWeaponAmbientSound(WeaponFireSnd[FireModeNum].DefaultCue, WeaponFireSnd[FireModeNum].FirstPersonCue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playing looping FireSnd only (used for switching sounds in Zedtime)
|
||||
*/
|
||||
simulated function StopLoopingFireSound(byte FireModeNum)
|
||||
{
|
||||
if ( bPlayingLoopingFireSnd )
|
||||
{
|
||||
KFPawn(Owner).SetWeaponAmbientSound(None);
|
||||
if ( FireModeNum < WeaponFireLoopEndSnd.Length )
|
||||
{
|
||||
WeaponPlayFireSound(WeaponFireLoopEndSnd[FireModeNum].DefaultCue, WeaponFireLoopEndSnd[FireModeNum].FirstPersonCue);
|
||||
}
|
||||
|
||||
bPlayingLoopingFireSnd = false;
|
||||
}
|
||||
}
|
||||
|
||||
simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation )
|
||||
{
|
||||
local name WeaponFireAnimName;
|
||||
local KFPerk CurrentPerk;
|
||||
local float TempTweenTime, AdjustedAnimLength;
|
||||
local KFPawn KFPO;
|
||||
|
||||
// If we have stopped the looping fire sound to play single fire sounds for zed time
|
||||
// start the looping sound back up again when the time is back above zed time speed
|
||||
if( FireModeNum < bLoopingFireSnd.Length && bLoopingFireSnd[FireModeNum] && !bPlayingLoopingFireSnd )
|
||||
{
|
||||
StartLoopingFireSound(FireModeNum);
|
||||
}
|
||||
|
||||
PlayFiringSound(CurrentFireMode);
|
||||
KFPO = KFPawn(Owner);
|
||||
|
||||
if( KFPO != none )
|
||||
{
|
||||
// Tell our pawn about any changes in animation speed
|
||||
UpdateWeaponAttachmentAnimRate( GetThirdPersonAnimRate() );
|
||||
|
||||
if( KFPO.IsLocallyControlled() )
|
||||
{
|
||||
if( KFPO.IsFirstPerson() )
|
||||
{
|
||||
if ( !bPlayingLoopingFireAnim )
|
||||
{
|
||||
WeaponFireAnimName = GetWeaponFireAnim(FireModeNum);
|
||||
|
||||
if ( WeaponFireAnimName != '' )
|
||||
{
|
||||
AdjustedAnimLength = MySkelMesh.GetAnimLength(WeaponFireAnimName);
|
||||
TempTweenTime = FireTweenTime;
|
||||
|
||||
CurrentPerk = GetPerk();
|
||||
if( CurrentPerk != none )
|
||||
{
|
||||
CurrentPerk.ModifyRateOfFire( AdjustedAnimLength, self );
|
||||
|
||||
// We need to unlock the slide if we fire from zero ammo while uber ammo is active
|
||||
if( EmptyMagBlendNode != none
|
||||
&& BonesToLockOnEmpty.Length > 0
|
||||
&& AmmoCount[GetAmmoType(FireModeNum)] == 0
|
||||
&& CurrentPerk.GetIsUberAmmoActive(self) )
|
||||
{
|
||||
EmptyMagBlendNode.SetBlendTarget( 0, 0 );
|
||||
TempTweenTime = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
PlayAnimation(WeaponFireAnimName, AdjustedAnimLength,, TempTweenTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Start muzzle flash effect
|
||||
CauseMuzzleFlash(FireModeNum);
|
||||
}
|
||||
|
||||
HandleRecoil();
|
||||
ShakeView();
|
||||
|
||||
if (AmmoCount[0] == 0 && ForceReloadTimeOnEmpty > 0)
|
||||
{
|
||||
SetTimer(ForceReloadTimeOnEmpty, false, nameof(ForceReload));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function WeaponPlayFireSound(AkBaseSoundObject DefaultSound, AkBaseSoundObject FirstPersonSound)
|
||||
{
|
||||
// ReplicateSound needs an "out" vector
|
||||
local vector SoundLocation;
|
||||
|
||||
if( Owner != None && !bSuppressSounds )
|
||||
{
|
||||
SoundLocation = KFPawn(Owner).GetPawnViewLocation();
|
||||
|
||||
if ( DefaultSound != None )
|
||||
{
|
||||
Owner.PlaySoundBase( DefaultSound, false, false, false, SoundLocation );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** True if we want to override the looping fire sounds with fire sounds from another firemode */
|
||||
simulated function bool ShouldForceSingleFireSound()
|
||||
{
|
||||
// If this weapon has a single-shot firemode, disable looping fire sounds during zedtime
|
||||
if ( `IsInZedTime(Instigator) && SingleFireSoundIndex != 255 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
simulated function bool HasAlwaysOnZedTimeResist()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// Inventory / Grouping
|
||||
InventorySize=5
|
||||
GroupPriority=25
|
||||
WeaponSelectTexture=Texture2D'WEP_UI_AutoTurret_TEX.UI_WeaponSelect_AutoTurret'
|
||||
|
||||
// FOV
|
||||
MeshIronSightFOV=52
|
||||
PlayerIronSightFOV=70
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=75
|
||||
DOF_FG_MaxNearBlurSize=3.5
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=9.0,Y=10,Z=-4)
|
||||
|
||||
// Content
|
||||
PackageKey="HRG_WarthogWeapon"
|
||||
FirstPersonMeshName="Wep_1P_HRG_WarthogWeapon_MESH.Wep_1stP_HRG_WarthogWeapon_Rig"
|
||||
FirstPersonAnimSetNames(0)="Wep_1P_HRG_WarthogWeapon_ANIM.Wep_1stP_HRG_WarthogWeapon_Anim"
|
||||
PickupMeshName="WEP_3P_HRG_WarthogWeapon_MESH.Wep_HRG_Warthog_Pickup"
|
||||
AttachmentArchetypeName="WEP_HRG_WarthogWeapon_ARCH.HRG_WarthogWeaponAttachment"
|
||||
MuzzleFlashTemplateName="WEP_HRG_WarthogWeapon_ARCH.HRG_WarthogWeapon_MuzzleFlash"
|
||||
|
||||
// Zooming/Position
|
||||
IronSightPosition=(X=0,Y=0,Z=0)
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=35
|
||||
SpareAmmoCapacity[0]=0
|
||||
InitialSpareMags[0]=0
|
||||
bCanBeReloaded=false
|
||||
bReloadFromMagazine=false
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=225
|
||||
minRecoilPitch=150
|
||||
maxRecoilYaw=150
|
||||
minRecoilYaw=-150
|
||||
RecoilRate=0.085
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=65035
|
||||
RecoilMaxPitchLimit=900
|
||||
RecoilMinPitchLimit=65035
|
||||
RecoilISMaxYawLimit=75
|
||||
RecoilISMinYawLimit=65460
|
||||
RecoilISMaxPitchLimit=195
|
||||
RecoilISMinPitchLimit=65460
|
||||
RecoilViewRotationScale=0.25
|
||||
IronSightMeshFOVCompensationScale=1.5
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_HighExplosive_HRG_Warthog'
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.7
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=10.0
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Warthog'
|
||||
Spread(DEFAULT_FIREMODE)=0.0
|
||||
FireOffset=(X=30,Y=4.5,Z=-4)
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_None
|
||||
|
||||
// BASH_FIREMODE
|
||||
WeaponFireTypes(BASH_FIREMODE)=EWFT_None
|
||||
|
||||
// Fire Effects
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_Warthog.Play_WEP_HRG_Warthog_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_HRG_Warthog.Play_WEP_HRG_Warthog_Fire_1P')
|
||||
|
||||
//@todo: add akevent when we have it
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=none
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=false
|
||||
bHasFlashlight=false
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_Demolitionist'
|
||||
|
||||
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil_SingleShot'
|
||||
|
||||
// Weapon Upgrade stat boosts
|
||||
//WeaponUpgrades[1]=(IncrementDamage=1.12f,IncrementWeight=1)
|
||||
//WeaponUpgrades[2]=(IncrementDamage=1.3f,IncrementWeight=2)
|
||||
//WeaponUpgrades[3]=(IncrementDamage=1.55f,IncrementWeight=3)
|
||||
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.12f), (Stat=EWUS_Weight, Add=1)))
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Weight, Add=2)))
|
||||
WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.55f), (Stat=EWUS_Weight, Add=3)))
|
||||
|
||||
InstigatorDrone=none
|
||||
|
||||
CurrentTarget=none
|
||||
CurrentDistanceProjectile=-1.f
|
||||
|
||||
DistanceParabolicLaunch=150.f //cm
|
||||
|
||||
LastTimeFireSeconds=0.f
|
||||
}
|
@ -905,7 +905,7 @@ defaultproperties
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=MineReconstructorCharge
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Mine_Reconstructor'
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.223 //+0.33
|
||||
FireInterval(DEFAULT_FIREMODE)=+0.2 //+0.33
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=120
|
||||
PenetrationPower(DEFAULT_FIREMODE)=0.0;
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Toxic_MineReconstructorImpact'
|
||||
@ -969,4 +969,6 @@ defaultproperties
|
||||
End Object
|
||||
//iCounterA = 0
|
||||
bBlocked = false;
|
||||
|
||||
bForceCrosshair=true
|
||||
}
|
@ -217,8 +217,8 @@ defaultproperties
|
||||
IronSightPosition=(X=3.0,Y=15,Z=15)
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=90 //125 //175 //250
|
||||
SpareAmmoCapacity[0]=540 //500 //750
|
||||
MagazineCapacity[0]=120 //125 //175 //250
|
||||
SpareAmmoCapacity[0]=600 //500 //750
|
||||
InitialSpareMags[0]=1
|
||||
AmmoPickupScale[0]=1 //0.67
|
||||
bCanBeReloaded=true
|
||||
|
@ -53,6 +53,11 @@ replication
|
||||
|
||||
}
|
||||
|
||||
static simulated event EFilterTypeUI GetTraderFilter()
|
||||
{
|
||||
return FT_Explosive;
|
||||
}
|
||||
|
||||
simulated function AltFireMode()
|
||||
{
|
||||
if ( !Instigator.IsLocallyControlled() )
|
||||
|
@ -10,6 +10,40 @@
|
||||
|
||||
class KFWeap_Shotgun_HRG_Kaboomstick extends KFWeap_Shotgun_DoubleBarrel;
|
||||
|
||||
var transient bool AlreadyIssuedCanNuke;
|
||||
|
||||
simulated function KFProjectile SpawnAllProjectiles(class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir)
|
||||
{
|
||||
local KFProjectile Proj;
|
||||
|
||||
AlreadyIssuedCanNuke = false;
|
||||
|
||||
Proj = Super.SpawnAllProjectiles(KFProjClass, RealStartLoc, AimDir);
|
||||
|
||||
AlreadyIssuedCanNuke = false;
|
||||
|
||||
return Proj;
|
||||
}
|
||||
|
||||
simulated function KFProjectile SpawnProjectile( class<KFProjectile> KFProjClass, vector RealStartLoc, vector AimDir )
|
||||
{
|
||||
local KFProj_Explosive_HRG_Kaboomstick Proj;
|
||||
|
||||
Proj = KFProj_Explosive_HRG_Kaboomstick(Super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir));
|
||||
|
||||
if (AlreadyIssuedCanNuke == false)
|
||||
{
|
||||
Proj.bCanNuke = true;
|
||||
AlreadyIssuedCanNuke = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Proj.bCanNuke = false;
|
||||
}
|
||||
|
||||
return Proj;
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
// Inventory
|
||||
@ -126,4 +160,6 @@ defaultproperties
|
||||
WeaponUpgrades[0]=(Stats=((Stat=EWUS_Damage0, Scale=1.f, Add=0), (Stat=EWUS_Weight, Scale=1.f, Add=0)))
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||
WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.30f), (Stat=EWUS_Damage1, Scale=1.30f), (Stat=EWUS_Weight, Add=2)))
|
||||
|
||||
AlreadyIssuedCanNuke = false
|
||||
}
|
717
KFGameContent/Classes/KFWeap_Shotgun_S12.uc
Normal file
717
KFGameContent/Classes/KFWeap_Shotgun_S12.uc
Normal file
@ -0,0 +1,717 @@
|
||||
//=============================================================================
|
||||
// KFWeap_Shotgun_S12
|
||||
//=============================================================================
|
||||
// AA12 Auto Shotgun Weapon Class
|
||||
//=============================================================================
|
||||
// Killing Floor 2
|
||||
// Copyright (C) 2023 Tripwire Interactive LLC
|
||||
//=============================================================================
|
||||
|
||||
class KFWeap_Shotgun_S12 extends KFWeap_ShotgunBase;
|
||||
|
||||
var (Positioning) vector SecondaryFireOffset;
|
||||
|
||||
const SecondaryFireAnim = 'Shoot_Secondary';
|
||||
const SecondaryFireIronAnim = 'Shoot_Secondary_Iron';
|
||||
|
||||
const SecondaryReloadAnim = 'Reload_Secondary';
|
||||
const SecondaryReloadEliteAnim = 'Reload_Secondary_Elite';
|
||||
|
||||
var() KFMuzzleFlash SecondaryMuzzleFlashTemplate;
|
||||
|
||||
// Used on the server to keep track of grenades
|
||||
var int ServerTotalAltAmmo;
|
||||
|
||||
var transient bool bCanceledAltAutoReload;
|
||||
|
||||
var GameExplosion ExplosionTemplate;
|
||||
var transient ParticleSystemComponent ExplosionPSC;
|
||||
var ParticleSystem ExplosionEffect;
|
||||
|
||||
var float ExplosionOriginalDamage;
|
||||
|
||||
simulated event PostBeginPlay()
|
||||
{
|
||||
super.PostBeginPlay();
|
||||
|
||||
ExplosionOriginalDamage = ExplosionTemplate.Damage;
|
||||
}
|
||||
|
||||
/** Instead of switch fire mode use as immediate alt fire */
|
||||
simulated function AltFireMode()
|
||||
{
|
||||
if ( !Instigator.IsLocallyControlled() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bCanceledAltAutoReload)
|
||||
{
|
||||
bCanceledAltAutoReload = false;
|
||||
TryToAltReload();
|
||||
return;
|
||||
}
|
||||
|
||||
StartFire(ALTFIRE_FIREMODE);
|
||||
}
|
||||
|
||||
simulated function BeginFire( Byte FireModeNum )
|
||||
{
|
||||
local bool bStoredAutoReload;
|
||||
|
||||
// We are trying to reload the weapon but the primary ammo in already at full capacity
|
||||
if ( FireModeNum == RELOAD_FIREMODE && !CanReload() )
|
||||
{
|
||||
// Store the cuurent state of bCanceledAltAutoReload in case its not possible to do the reload
|
||||
bStoredAutoReload = bCanceledAltAutoReload;
|
||||
bCanceledAltAutoReload = false;
|
||||
|
||||
if(CanAltAutoReload())
|
||||
{
|
||||
TryToAltReload();
|
||||
return;
|
||||
}
|
||||
|
||||
bCanceledAltAutoReload = bStoredAutoReload;
|
||||
}
|
||||
|
||||
super.BeginFire( FireModeNum );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes ammo counts, when weapon is spawned.
|
||||
*/
|
||||
function InitializeAmmo()
|
||||
{
|
||||
Super.InitializeAmmo();
|
||||
|
||||
// Add Secondary ammo to our secondary spare ammo count both of these are important, in order to allow dropping the weapon to function properly.
|
||||
SpareAmmoCount[1] = Min(SpareAmmoCount[1] + InitialSpareMags[1] * default.MagazineCapacity[1], GetMaxAmmoAmount(1) - AmmoCount[1]);
|
||||
ServerTotalAltAmmo += SpareAmmoCount[1];
|
||||
|
||||
// Make sure the server doesn't get extra shots on listen servers.
|
||||
if(Role == ROLE_Authority && !Instigator.IsLocallyControlled())
|
||||
{
|
||||
ServerTotalAltAmmo += AmmoCount[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Weapon::ConsumeAmmo
|
||||
*/
|
||||
simulated function ConsumeAmmo( byte FireModeNum )
|
||||
{
|
||||
local byte AmmoType;
|
||||
local bool bNoInfiniteAmmo;
|
||||
local int OldAmmoCount;
|
||||
|
||||
if(UsesSecondaryAmmo() && FireModeNum == ALTFIRE_FIREMODE && Role == ROLE_Authority && !Instigator.IsLocallyControlled())
|
||||
{
|
||||
AmmoType = GetAmmoType(FireModeNum);
|
||||
|
||||
OldAmmoCount = AmmoCount[AmmoType];
|
||||
Super.ConsumeAmmo(FireModeNum);
|
||||
|
||||
bNoInfiniteAmmo = (OldAmmoCount - AmmoCount[AmmoType]) > 0 || AmmoCount[AmmoType] == 0;
|
||||
if ( bNoInfiniteAmmo )
|
||||
{
|
||||
ServerTotalAltAmmo--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.ConsumeAmmo(FireModeNum);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function bool HasAnyAmmo()
|
||||
{
|
||||
return HasSpareAmmo() || HasAmmo(DEFAULT_FIREMODE) || SpareAmmoCount[1] > 0 || HasAmmo(ALTFIRE_FIREMODE);
|
||||
}
|
||||
|
||||
/** Make sure user can't fire infinitely if they cheat to get infinite ammo locally. */
|
||||
simulated event bool HasAmmo( byte FireModeNum, optional int Amount=1 )
|
||||
{
|
||||
local byte AmmoType;
|
||||
|
||||
AmmoType = GetAmmoType(FireModeNum);
|
||||
|
||||
if(AmmoType == 1 && Role == ROLE_Authority && Instigator != none && UsesSecondaryAmmo() && !Instigator.IsLocallyControlled())
|
||||
{
|
||||
if(ServerTotalAltAmmo <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return Super.HasAmmo(FireModeNum, Amount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden so any grenades added will go to the spare ammo and no the clip.
|
||||
*/
|
||||
function int AddSecondaryAmmo(int Amount)
|
||||
{
|
||||
local int OldAmmo;
|
||||
|
||||
// If we can't accept spare ammo, then abort
|
||||
if( !CanRefillSecondaryAmmo() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Role == ROLE_Authority && !Instigator.IsLocallyControlled())
|
||||
{
|
||||
OldAmmo = ServerTotalAltAmmo;
|
||||
|
||||
ServerTotalAltAmmo = Min(ServerTotalAltAmmo + Amount, GetMaxAmmoAmount(1));
|
||||
ClientGiveSecondaryAmmo(Amount);
|
||||
return ServerTotalAltAmmo - OldAmmo;
|
||||
}
|
||||
else
|
||||
{
|
||||
OldAmmo = SpareAmmoCount[1];
|
||||
ClientGiveSecondaryAmmo(Amount);
|
||||
return SpareAmmoCount[1] - OldAmmo;
|
||||
}
|
||||
}
|
||||
|
||||
/** Give client specified amount of ammo (used player picks up ammo on the server) */
|
||||
reliable client function ClientGiveSecondaryAmmo(byte Amount)
|
||||
{
|
||||
SpareAmmoCount[1] = Min(SpareAmmoCount[1] + Amount, GetMaxAmmoAmount(1) - AmmoCount[1]);
|
||||
TryToAltReload();
|
||||
}
|
||||
|
||||
function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon )
|
||||
{
|
||||
local KFWeap_Shotgun_S12 Weap;
|
||||
|
||||
Super.SetOriginalValuesFromPickup(PickedUpWeapon);
|
||||
|
||||
if(Role == ROLE_Authority && !Instigator.IsLocallyControlled())
|
||||
{
|
||||
Weap = KFWeap_Shotgun_S12(PickedUpWeapon);
|
||||
ServerTotalAltAmmo = Weap.ServerTotalAltAmmo;
|
||||
SpareAmmoCount[1] = ServerTotalAltAmmo - AmmoCount[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're locally controlled, don't bother using ServerTotalAltAmmo.
|
||||
SpareAmmoCount[1] = PickedUpWeapon.SpareAmmoCount[1];
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State GrenadeFiring
|
||||
* Handles firing grenade launcher.
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state FiringSecondaryState extends WeaponSingleFiring
|
||||
{
|
||||
// Overriden to not call FireAmmunition right at the start of the state
|
||||
simulated event BeginState( Name PreviousStateName )
|
||||
{
|
||||
Super.BeginState(PreviousStateName);
|
||||
NotifyBeginState();
|
||||
}
|
||||
|
||||
simulated function EndState(Name NextStateName)
|
||||
{
|
||||
Super.EndState(NextStateName);
|
||||
NotifyEndState();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the world location for spawning the visual effects
|
||||
* Overridden to use a special offset for throwing grenades
|
||||
*/
|
||||
simulated event vector GetMuzzleLoc()
|
||||
{
|
||||
local vector MuzzleLocation;
|
||||
|
||||
// swap fireoffset temporarily
|
||||
FireOffset = SecondaryFireOffset;
|
||||
MuzzleLocation = Global.GetMuzzleLoc();
|
||||
FireOffset = default.FireOffset;
|
||||
|
||||
return MuzzleLocation;
|
||||
}
|
||||
|
||||
/** Get whether we should play the reload anim as well or not */
|
||||
simulated function name GetWeaponFireAnim(byte FireModeNum)
|
||||
{
|
||||
return bUsingSights ? SecondaryFireIronAnim : SecondaryFireAnim;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow secondary fire to make a primary fire shell particle come out of the gun.
|
||||
*/
|
||||
simulated function CauseMuzzleFlash(byte FireModeNum)
|
||||
{
|
||||
local bool AutoShellEject;
|
||||
|
||||
if(FireModeNum == ALTFIRE_FIREMODE)
|
||||
{
|
||||
if (MuzzleFlash == None)
|
||||
{
|
||||
AttachSecondaryMuzzleFlash();
|
||||
}
|
||||
|
||||
AutoShellEject = MuzzleFlash.bAutoActivateShellEject;
|
||||
|
||||
MuzzleFlash.bAutoActivateShellEject = false;
|
||||
|
||||
Super.CauseMuzzleFlash(FireModeNum);
|
||||
|
||||
MuzzleFlash.bAutoActivateShellEject = AutoShellEject;
|
||||
}
|
||||
else
|
||||
{
|
||||
Super.CauseMuzzleFlash(FireModeNum);
|
||||
}
|
||||
}
|
||||
|
||||
simulated function AttachSecondaryMuzzleFlash()
|
||||
{
|
||||
if ( MySkelMesh != none )
|
||||
{
|
||||
if (MuzzleFlashTemplate != None)
|
||||
{
|
||||
MuzzleFlash = new(self) Class'KFMuzzleFlash'(SecondaryMuzzleFlashTemplate);
|
||||
MuzzleFlash.AttachMuzzleFlash(MySkelMesh, 'MuzzleFlashAlt');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State Reloading
|
||||
* This is the default Reloading State. It's performed on both the client and the server.
|
||||
*********************************************************************************************/
|
||||
|
||||
/** Do not allow alternate fire to tell the weapon to reload. Alt reload occurs in a separate codepath */
|
||||
simulated function bool ShouldAutoReload(byte FireModeNum)
|
||||
{
|
||||
if(FireModeNum == ALTFIRE_FIREMODE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Super.ShouldAutoReload(FireModeNum);
|
||||
}
|
||||
|
||||
/** Called on local player when reload starts and replicated to server */
|
||||
simulated function SendToAltReload()
|
||||
{
|
||||
ReloadAmountLeft = MagazineCapacity[1];
|
||||
GotoState('AltReloading');
|
||||
if ( Role < ROLE_Authority )
|
||||
{
|
||||
ServerSendToAltReload();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called from client when reload starts */
|
||||
reliable server function ServerSendToAltReload()
|
||||
{
|
||||
ReloadAmountLeft = MagazineCapacity[1];
|
||||
GotoState('AltReloading');
|
||||
}
|
||||
|
||||
/**
|
||||
* State Reloading
|
||||
* State the weapon is in when it is being reloaded (current magazine replaced with a new one, related animations and effects played).
|
||||
*/
|
||||
simulated state AltReloading extends Reloading
|
||||
{
|
||||
ignores ForceReload, ShouldAutoReload, AllowSprinting;
|
||||
|
||||
simulated function byte GetWeaponStateId()
|
||||
{
|
||||
local KFPerk Perk;
|
||||
local bool bTacticalReload;
|
||||
|
||||
Perk = GetPerk();
|
||||
bTacticalReload = (Perk != None && Perk.GetUsingTactialReload(self));
|
||||
|
||||
return (bTacticalReload ? WEP_ReloadSecondary_Elite : WEP_ReloadSecondary);
|
||||
}
|
||||
|
||||
simulated event BeginState(Name PreviousStateName)
|
||||
{
|
||||
super.BeginState(PreviousStateName);
|
||||
bCanceledAltAutoReload = true;
|
||||
}
|
||||
|
||||
// Overridding super so we don't call functions we don't want to call.
|
||||
simulated function EndState(Name NextStateName)
|
||||
{
|
||||
ClearZedTimeResist();
|
||||
ClearTimer(nameof(ReloadStatusTimer));
|
||||
ClearTimer(nameof(ReloadAmmoTimer));
|
||||
|
||||
CheckBoltLockPostReload();
|
||||
NotifyEndState();
|
||||
|
||||
`DialogManager.PlayAmmoDialog( KFPawn(Instigator), float(SpareAmmoCount[1]) / float(GetMaxAmmoAmount(1)) );
|
||||
}
|
||||
|
||||
// Overridding super so when this reload is called directly after normal reload state there
|
||||
// are not complications resulting from back to back reloads.
|
||||
simulated event ReplicatedEvent(name VarName)
|
||||
{
|
||||
Global.ReplicatedEvent(Varname);
|
||||
}
|
||||
|
||||
/** Make sure we can inturrupt secondary reload with anything. */
|
||||
simulated function bool CanOverrideMagReload(byte FireModeNum)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns animation to play based on reload type and status */
|
||||
simulated function name GetReloadAnimName( bool bTacticalReload )
|
||||
{
|
||||
return (bTacticalReload) ? SecondaryReloadEliteAnim : SecondaryReloadAnim;
|
||||
}
|
||||
|
||||
simulated function PerformReload(optional byte FireModeNum)
|
||||
{
|
||||
Global.PerformReload(ALTFIRE_FIREMODE);
|
||||
|
||||
if(Instigator.IsLocallyControlled() && Role < ROLE_Authority)
|
||||
{
|
||||
ServerSetAltAmmoCount(AmmoCount[1]);
|
||||
}
|
||||
|
||||
bCanceledAltAutoReload = false;
|
||||
}
|
||||
|
||||
simulated function EReloadStatus GetNextReloadStatus(optional byte FireModeNum)
|
||||
{
|
||||
return Global.GetNextReloadStatus(ALTFIRE_FIREMODE);
|
||||
}
|
||||
}
|
||||
|
||||
reliable server function ServerSetAltAmmoCount(byte Amount)
|
||||
{
|
||||
AmmoCount[1] = min(Amount, MagazineCapacity[1]);
|
||||
}
|
||||
|
||||
/** Allow reloads for primary weapon to be interupted by firing secondary weapon. */
|
||||
simulated function bool CanOverrideMagReload(byte FireModeNum)
|
||||
{
|
||||
if(FireModeNum == ALTFIRE_FIREMODE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Super.CanOverrideMagReload(FireModeNum);
|
||||
}
|
||||
|
||||
/*********************************************************************************************
|
||||
* State Active
|
||||
* Try to get weapon to automatically reload secondary fire types when it can.
|
||||
*********************************************************************************************/
|
||||
|
||||
simulated state Active
|
||||
{
|
||||
/** Initialize the weapon as being active and ready to go. */
|
||||
simulated event BeginState(Name PreviousStateName)
|
||||
{
|
||||
// do this last so the above code happens before any state changes
|
||||
Super.BeginState(PreviousStateName);
|
||||
|
||||
// If nothing happened, try to reload
|
||||
TryToAltReload();
|
||||
}
|
||||
}
|
||||
|
||||
/** Network: Local Player */
|
||||
simulated function bool CanAltAutoReload()
|
||||
{
|
||||
if ( !Instigator.IsLocallyControlled() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!UsesSecondaryAmmo())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the weapon wants to fire its primary weapon, and it can fire, do not allow weapon to automatically alt reload
|
||||
if(PendingFire(DEFAULT_FIREMODE) && HasAmmo(DEFAULT_FIREMODE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CanReload(ALTFIRE_FIREMODE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bCanceledAltAutoReload)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
simulated function TryToAltReload()
|
||||
{
|
||||
if ((IsInState('Active') || IsInState('WeaponSprinting')) && CanAltAutoReload())
|
||||
{
|
||||
SendToAltReload();
|
||||
}
|
||||
}
|
||||
|
||||
simulated function TriggerAltExplosion()
|
||||
{
|
||||
local vector MuzzleLocation, HitLocation, HitNormal;
|
||||
local KFExplosionActorReplicated ExploActor;
|
||||
|
||||
// TriggerExplosion
|
||||
if (Role == ROLE_Authority)
|
||||
{
|
||||
MuzzleLocation = GetMuzzleLoc();
|
||||
Trace( HitLocation, HitNormal, MuzzleLocation + vect(0, 0, -1) * 250000, MuzzleLocation);
|
||||
// Move a bit from hit location
|
||||
HitLocation = HitLocation + (vect(0,0,1) * 128.f);
|
||||
|
||||
// Explode using the given template
|
||||
ExploActor = Spawn(class'KFExplosionActorReplicated', self,, HitLocation, rotator(vect(0,0,1)),, true);
|
||||
if (ExploActor != None)
|
||||
{
|
||||
ExploActor.InstigatorController = Instigator.Controller;
|
||||
ExploActor.Instigator = Instigator;
|
||||
ExploActor.bIgnoreInstigator = true;
|
||||
ExplosionTemplate.Damage = ExplosionOriginalDamage * GetUpgradeDamageMod(ALTFIRE_FIREMODE);
|
||||
|
||||
ExploActor.Explode(ExplosionTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
// Trigger VFX ?
|
||||
|
||||
if (HitLocation == vect(0,0,0))
|
||||
{
|
||||
MySkelMesh.GetSocketWorldLocationAndRotation('MuzzleFlashAlt', MuzzleLocation);
|
||||
Trace( HitLocation, HitNormal, MuzzleLocation + vect(0, 0, -1) * 250000, MuzzleLocation);
|
||||
// Move a bit from hit location
|
||||
HitLocation = HitLocation + (vect(0,0,1) * 128.f);
|
||||
}
|
||||
|
||||
if (ExplosionEffect != None)
|
||||
{
|
||||
ExplosionPSC = WorldInfo.MyEmitterPool.SpawnEmitter(ExplosionEffect, HitLocation, rotator(vect(0,0,1)));
|
||||
ExplosionPSC.ActivateSystem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simulated function CustomFire()
|
||||
{
|
||||
// Alt-fire blast only (server authoritative)
|
||||
if ( CurrentFireMode != ALTFIRE_FIREMODE )
|
||||
{
|
||||
Super.CustomFire();
|
||||
return;
|
||||
}
|
||||
|
||||
TriggerAltExplosion();
|
||||
IncrementFlashCount();
|
||||
}
|
||||
|
||||
simulated event Tick(float DeltaTime)
|
||||
{
|
||||
local vector SocketLocation;
|
||||
Super.Tick(DeltaTime);
|
||||
|
||||
// Client only
|
||||
if (WorldInfo.NetMode != NM_DedicatedServer)
|
||||
{
|
||||
KFSkeletalMeshComponent(Mesh).GetSocketWorldLocationAndRotation('MuzzleFlashAlt', SocketLocation);
|
||||
|
||||
if (ExplosionPSC != None && ExplosionPSC.bIsActive)
|
||||
{
|
||||
ExplosionPSC.SetVectorParameter('WeaponEndpoint', SocketLocation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defaultproperties
|
||||
{
|
||||
bCanRefillSecondaryAmmo = true;
|
||||
|
||||
// Shooting Animations
|
||||
FireSightedAnims[0]=Shoot_Iron
|
||||
FireSightedAnims[1]=Shoot_Iron2
|
||||
FireSightedAnims[2]=Shoot_Iron3
|
||||
|
||||
// FOV
|
||||
MeshFOV=86
|
||||
MeshIronSightFOV=35
|
||||
PlayerIronSightFOV=70
|
||||
|
||||
// Depth of field
|
||||
DOF_FG_FocalRadius=85
|
||||
DOF_FG_MaxNearBlurSize=3.5
|
||||
|
||||
// Content
|
||||
PackageKey="Saiga12"
|
||||
FirstPersonMeshName="Wep_1P_Saiga12_MESH.Wep_1stP_Saiga12_Rig"
|
||||
FirstPersonAnimSetNames(0)="Wep_1P_Saiga12_ANIM.Wep_1stP_Saiga12_Anim_New"
|
||||
PickupMeshName="WEP_3P_Saiga12_MESH.Wep_Saiga12_Pickup"
|
||||
AttachmentArchetypeName="WEP_Saiga12_ARCH.Wep_Saiga12_3P"
|
||||
MuzzleFlashTemplateName="WEP_Saiga12_ARCH.Wep_Saiga12_MuzzleFlash"
|
||||
SecondaryMuzzleFlashTemplate=KFMuzzleFlash'WEP_Saiga12_ARCH.Wep_Saiga12_MuzzleFlashAlt'
|
||||
|
||||
// Zooming/Position
|
||||
PlayerViewOffset=(X=0,Y=12.5,Z=-18)//
|
||||
IronSightPosition=(X=12,Y=0,Z=-10.6)
|
||||
|
||||
// Pickup
|
||||
AmmoPickupScale[0]=2.0
|
||||
AmmoPickupScale[1]=1.0
|
||||
|
||||
// Ammo
|
||||
MagazineCapacity[0]=10
|
||||
SpareAmmoCapacity[0]=130
|
||||
InitialSpareMags[0]=4
|
||||
|
||||
//grenades
|
||||
MagazineCapacity[1]=1
|
||||
SpareAmmoCapacity[1]=5
|
||||
InitialSpareMags[1]=2
|
||||
|
||||
bCanBeReloaded=true
|
||||
bReloadFromMagazine=true
|
||||
|
||||
// Recoil
|
||||
maxRecoilPitch=250
|
||||
minRecoilPitch=225
|
||||
maxRecoilYaw=125
|
||||
minRecoilYaw=-125
|
||||
RecoilRate=0.075
|
||||
RecoilBlendOutRatio=0.25
|
||||
RecoilMaxYawLimit=500
|
||||
RecoilMinYawLimit=65035
|
||||
RecoilMaxPitchLimit=900
|
||||
RecoilMinPitchLimit=64785
|
||||
RecoilISMaxYawLimit=75
|
||||
RecoilISMinYawLimit=65460
|
||||
RecoilISMaxPitchLimit=375
|
||||
RecoilISMinPitchLimit=65460
|
||||
RecoilViewRotationScale=0.7
|
||||
FallingRecoilModifier=1.5
|
||||
HippedRecoilModifier=1.25
|
||||
|
||||
SecondaryAmmoTexture=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity'
|
||||
bUseGrenadeAsSecondaryAmmo=true
|
||||
|
||||
// Inventory / Grouping
|
||||
InventorySize=8
|
||||
GroupPriority=100
|
||||
WeaponSelectTexture=Texture2D'WEP_UI_Saiga12_TEX.UI_WeaponSelect_Saiga12'
|
||||
|
||||
AssociatedPerkClasses(0)=class'KFPerk_Support'
|
||||
|
||||
// DEFAULT_FIREMODE
|
||||
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle'
|
||||
FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFiring
|
||||
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile
|
||||
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Pellet'
|
||||
InstantHitDamage(DEFAULT_FIREMODE)=24.0 //25 //20
|
||||
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_Shotgun_S12'
|
||||
PenetrationPower(DEFAULT_FIREMODE)=2.0
|
||||
FireInterval(DEFAULT_FIREMODE)=0.2 // 300 RPM
|
||||
Spread(DEFAULT_FIREMODE)=0.08
|
||||
FireOffset=(X=30,Y=5,Z=-4)
|
||||
NumPellets(DEFAULT_FIREMODE)=7
|
||||
|
||||
// ALT_FIREMODE
|
||||
FiringStatesArray(ALTFIRE_FIREMODE)=FiringSecondaryState
|
||||
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Custom
|
||||
AmmoCost(ALTFIRE_FIREMODE)=1
|
||||
FireInterval(ALTFIRE_FIREMODE)=+0.25 // 300 RPM
|
||||
SecondaryFireOffset=(X=20.f,Y=4.5,Z=-7.f)
|
||||
|
||||
// BASH_FIREMODE
|
||||
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_Shotgun_S12'
|
||||
InstantHitDamage(BASH_FIREMODE)=30
|
||||
|
||||
// Fire Effects
|
||||
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Fire_1P')
|
||||
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Alt_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Alt_Fire_1P')
|
||||
|
||||
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Handling_DryFire'
|
||||
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Handling_DryFire'
|
||||
|
||||
WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil'
|
||||
|
||||
// Attachments
|
||||
bHasIronSights=true
|
||||
bHasFlashlight=false
|
||||
|
||||
// Weapon Upgrade stat boosts
|
||||
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
|
||||
|
||||
// Grenade explosion light
|
||||
Begin Object Class=PointLightComponent Name=ExplosionPointLight
|
||||
LightColor=(R=252,G=218,B=171,A=255)
|
||||
Brightness=0.5f
|
||||
Radius=400.f
|
||||
FalloffExponent=10.f
|
||||
CastShadows=False
|
||||
CastStaticShadows=FALSE
|
||||
CastDynamicShadows=False
|
||||
bCastPerObjectShadows=false
|
||||
bEnabled=FALSE
|
||||
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
|
||||
End Object
|
||||
|
||||
// explosion
|
||||
Begin Object Class=KFGameExplosion Name=ExploTemplate0
|
||||
Damage=200
|
||||
DamageRadius=800
|
||||
DamageFalloffExponent=0.f
|
||||
DamageDelay=0.f
|
||||
MomentumTransferScale=10000
|
||||
bAlwaysFullDamage=true
|
||||
bDoCylinderCheck=true
|
||||
|
||||
// Damage Effects
|
||||
MyDamageType=class'KFDT_Explosive_Shotgun_S12'
|
||||
KnockDownStrength=150
|
||||
FractureMeshRadius=200.0
|
||||
FracturePartVel=500.0
|
||||
|
||||
ExplosionSound=AkEvent'WW_WEP_Saiga12.Play_WEP_Saiga12_Alt_Fire_3P'
|
||||
ExplosionEffects=KFImpactEffectInfo'WEP_Saiga12_ARCH.WEP_Saiga12_Impacts'
|
||||
|
||||
// Dynamic Light
|
||||
ExploLight=ExplosionPointLight
|
||||
ExploLightStartFadeOutTime=0.0
|
||||
ExploLightFadeOutTime=0.3
|
||||
|
||||
bIgnoreInstigator=true
|
||||
ActorClassToIgnoreForDamage = class'KFPawn_Human'
|
||||
|
||||
// Camera Shake
|
||||
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
|
||||
CamShakeInnerRadius=0
|
||||
CamShakeOuterRadius=300
|
||||
CamShakeFalloff=1.5f
|
||||
bOrientCameraShakeTowardsEpicenter=true
|
||||
End Object
|
||||
ExplosionTemplate=ExploTemplate0
|
||||
|
||||
ExplosionEffect=ParticleSystem'WEP_1P_Saiga12_EMIT.FX_Saiga12_Explosion'
|
||||
|
||||
}
|
Reference in New Issue
Block a user