1
0
This commit is contained in:
GenZmeY 2022-09-01 18:58:51 +03:00
parent 670ad3af13
commit 3e3e8af04f
119 changed files with 5648 additions and 371 deletions

View File

@ -1498,6 +1498,7 @@ struct native ItemProperties
/** Key ID used to open this item (used for playfab locked containers) */
var string RequiredKeyId;
var string Name;
var string KeyName;
var ItemType Type;
var ItemRarity Rarity;
var string ShortDescription;

View File

@ -2596,17 +2596,10 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector
Killer = SetKillInstigator(InstigatedBy, DamageType);
TearOffMomentum = momentum;
Died(Killer, damageType, HitLocation);
// using the passed in damage type instead of the hitfxinfo since that doesn't get updated when zero damage is done
HandleAfflictionsOnHit(InstigatedBy, Normal(Momentum), DamageType, DamageCauser);
}
else
{
HandleMomentum( momentum, HitLocation, DamageType, HitInfo );
// using the passed in damage type instead of the hitfxinfo since that doesn't get updated when zero damage is done
HandleAfflictionsOnHit(InstigatedBy, Normal(Momentum), DamageType, DamageCauser);
NotifyTakeHit(InstigatedBy, HitLocation, ActualDamage, DamageType, Momentum, DamageCauser);
if (DrivenVehicle != None)
{
@ -2626,8 +2619,6 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector
`endif
}
function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class<DamageType> DamageType, Actor DamageCauser);
/*
* Queries the PRI and returns our current team index.
*/

View File

@ -508,6 +508,15 @@ var const int ZedBumpEffectThreshold;
/** The chance of obliterating a zed on an enraged bump */
var const float ZedBumpObliterationEffectChance;
// Only enabled while we didn't receive damage and we use Aggro for choosing Enemy
var bool CanForceEnemy;
var Pawn ForcedEnemy;
var Pawn LastForcedEnemy;
var float ForcedEnemyLastTime;
var float DamageRatioToChangeForcedEnemy;
var float TimeCanRestartForcedEnemy;
var float TimeCannotChangeFromForcedEnemy;
/*********************************************************************************************
Evasion / Blocking
********************************************************************************************* */
@ -1282,6 +1291,33 @@ native function StopAllLatentMoveExecution();
/** Am I being targeted by a player (optionally returns first found) */
native function bool IsTargetedByPlayer( optional out KFPawn outThreateningPlayer );
function Pawn FindForcedEnemy()
{
local KFGameInfo KFGI;
local KFPlayerController_WeeklySurvival KFPC_WS;
local class<KFPawn_Monster> MyMonster;
KFGI = KFGameInfo(WorldInfo.Game);
if(KFGI != none && KFGI.OutbreakEvent != none && KFGI.OutbreakEvent.ActiveEvent.bVIPGameMode)
{
MyMonster = class<KFPawn_Monster>(Pawn.Class);
// If this monster is included on the vip targetting, force VIP as enemy
if (KFGI.OutbreakEvent.ActiveEvent.VIPTargetting.Find(MyMonster) != INDEX_NONE)
{
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
{
if (KFPC_WS.VIPGameData.IsVIP && KFPC_WS.Pawn.IsAliveAndWell() && KFPC_WS.Pawn.CanAITargetThisPawn(self))
{
return KFPC_WS.Pawn;
}
}
}
}
return none;
}
/**
* Originally from KF1, KFMonsterController.uc, added check to take # of Zeds targeting
* the threat into account.
@ -1300,45 +1336,50 @@ event bool FindNewEnemy()
}
BestEnemy = none;
foreach WorldInfo.AllPawns( class'Pawn', PotentialEnemy )
{
if( !PotentialEnemy.IsAliveAndWell() || Pawn.IsSameTeam( PotentialEnemy ) ||
!PotentialEnemy.CanAITargetThisPawn(self) )
{
continue;
}
NewDist = VSizeSq( PotentialEnemy.Location - Pawn.Location );
if( BestEnemy == none || BestDist > NewDist )
if (BestEnemy == none)
{
foreach WorldInfo.AllPawns( class'Pawn', PotentialEnemy )
{
// New best enemies do not care about the number of zeds around us yet
BestEnemyZedCount = INDEX_None;
bUpdateBestEnemy = true;
}
else
{
// Only update NumZedsTargetingBestEnemy if it's a new best enemy and the best enemy is further
if(BestEnemyZedCount == INDEX_None)
if( !PotentialEnemy.IsAliveAndWell() || Pawn.IsSameTeam( PotentialEnemy ) ||
!PotentialEnemy.CanAITargetThisPawn(self) )
{
// Cache BestEnemyZedCount so we don't need to calculate it again
BestEnemyZedCount = NumberOfZedsTargetingPawn( BestEnemy );
continue;
}
PotentialEnemyZedCount = NumberOfZedsTargetingPawn( PotentialEnemy );
if( PotentialEnemyZedCount < BestEnemyZedCount )
NewDist = VSizeSq( PotentialEnemy.Location - Pawn.Location );
if( BestEnemy == none || BestDist > NewDist )
{
BestEnemyZedCount = PotentialEnemyZedCount;
// New best enemies do not care about the number of zeds around us yet
BestEnemyZedCount = INDEX_None;
bUpdateBestEnemy = true;
}
}
else
{
// Only update NumZedsTargetingBestEnemy if it's a new best enemy and the best enemy is further
if(BestEnemyZedCount == INDEX_None)
{
// Cache BestEnemyZedCount so we don't need to calculate it again
BestEnemyZedCount = NumberOfZedsTargetingPawn( BestEnemy );
}
if( bUpdateBestEnemy )
{
BestEnemy = PotentialEnemy;
BestDist = NewDist;
bUpdateBestEnemy = false;
PotentialEnemyZedCount = NumberOfZedsTargetingPawn( PotentialEnemy );
if( PotentialEnemyZedCount < BestEnemyZedCount )
{
BestEnemyZedCount = PotentialEnemyZedCount;
bUpdateBestEnemy = true;
}
}
if( bUpdateBestEnemy )
{
BestEnemy = PotentialEnemy;
BestDist = NewDist;
bUpdateBestEnemy = false;
}
}
}
if( Enemy != none && BestEnemy != none && BestEnemy == Enemy )
{
return false;
@ -1536,10 +1577,37 @@ event bool SetEnemy( Pawn NewEnemy )
function ChangeEnemy( Pawn NewEnemy, optional bool bCanTaunt = true )
{
local Pawn OldEnemy;
local Pawn OldEnemy, NewForcedEnemy;
local KFGameInfo KFGI;
if (CanForceEnemy)
{
NewForcedEnemy = FindForcedEnemy();
}
else if (NewEnemy == LastForcedEnemy)
{
return; // Don't allow to change to the ForcedEnemy while we can't (we reenable that again from outside)
}
if (NewForcedEnemy != none)
{
ForcedEnemy = NewForcedEnemy;
if (Enemy != ForcedEnemy)
{
LastForcedEnemy = ForcedEnemy;
ForcedEnemyLastTime = WorldInfo.TimeSeconds;
}
NewEnemy = NewForcedEnemy;
}
else
{
ForcedEnemy = none;
}
// gameinfo hook that calls mutator hook
KFGI = KFGameInfo( WorldInfo.Game );
if( KFGI != none )
@ -7626,6 +7694,13 @@ DefaultProperties
LastFrustrationCheckTime=0.f
LowIntensityAttackCooldown=2.0
//bUseOldAttackDecisions=true
CanForceEnemy=true
ForcedEnemy=none
LastForcedEnemy=none
ForcedEnemyLastTime=0.f
DamageRatioToChangeForcedEnemy=0.5f
TimeCanRestartForcedEnemy=10.f
TimeCannotChangeFromForcedEnemy=10.f
// ---------------------------------------------
// AI / Navigation

View File

@ -96,30 +96,35 @@ event bool FindNewEnemy()
local Controller C;
local Pawn PotentialEnemy;
foreach WorldInfo.AllControllers( class'Controller', C )
BestEnemy = none;
if (BestEnemy == none)
{
if( C.Pawn == none || !C.Pawn.IsAliveAndWell() || Pawn.IsSameTeam( C.Pawn ) ||
!C.Pawn.CanAITargetThisPawn(self) )
foreach WorldInfo.AllControllers( class'Controller', C )
{
continue;
}
if( C.Pawn == none || !C.Pawn.IsAliveAndWell() || Pawn.IsSameTeam( C.Pawn ) ||
!C.Pawn.CanAITargetThisPawn(self) )
{
continue;
}
PotentialEnemy = C.Pawn;
NewDist = VSizeSq( PotentialEnemy.Location - Pawn.Location );
PotentialEnemy = C.Pawn;
NewDist = VSizeSq( PotentialEnemy.Location - Pawn.Location );
if( BestEnemy == none )
{
BestEnemy = PotentialEnemy;
BestDist = NewDist;
}
else if( BestEnemy != none )
{
if( (BestDist > NewDist) || (NumberOfZedsTargetingPawn( PotentialEnemy ) < NumberOfZedsTargetingPawn( BestEnemy )) )
if( BestEnemy == none )
{
BestEnemy = PotentialEnemy;
BestDist = NewDist;
}
else if( BestEnemy != none )
{
if( (BestDist > NewDist) || (NumberOfZedsTargetingPawn( PotentialEnemy ) < NumberOfZedsTargetingPawn( BestEnemy )) )
{
BestEnemy = PotentialEnemy;
BestDist = NewDist;
}
}
}
}

View File

@ -143,6 +143,8 @@ var const int ForcedBossNum;
var bool bTemporarilyEndless;
var int VIP_CurrentSpawnCounter;
var int VIP_MaxSpawnCounter;
/************************************************************************************
* Debugging
@ -154,6 +156,51 @@ var config bool bLogRateVolume;
/** Builds a sorted list of spawn volumes based on distance to a specific player */
native function bool SortSpawnVolumes(Controller C, bool bTeleporting, float MinDistSquared);
delegate int SortVIPSpawnVolumesDelegate(KFSpawnVolume A, KFSpawnVolume B)
{
if (A.CurrentRating == B.CurrentRating)
{
return 0;
}
if (A.CurrentRating < B.CurrentRating)
{
return 1;
}
return -1;
}
function SortVIPSpawnVolumes()
{
local KFGameReplicationInfo KFGRI;
local int VolumeIndex;
if (VIP_CurrentSpawnCounter < VIP_MaxSpawnCounter)
{
++VIP_CurrentSpawnCounter;
return;
}
VIP_CurrentSpawnCounter = 0;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none && KFGRI.VIPRepPlayer != none)
{
// Recalculate rating based on the distance to VIP player
for (VolumeIndex = 0; VolumeIndex < SpawnVolumes.Length; VolumeIndex++)
{
if (SpawnVolumes[VolumeIndex].CurrentRating > 0)
{
SpawnVolumes[VolumeIndex].CurrentRating = VSizeSq( SpawnVolumes[VolumeIndex].Location - KFGRI.VIPRepPlayer.Location );
}
}
}
// Sort vector based on closest
SpawnVolumes.Sort(SortVIPSpawnVolumesDelegate);
}
static function string ZedTypeToString(EAIType AiTypeToConvert)
{
`if(`notdefined(ShippingPC))
@ -226,8 +273,11 @@ function RegisterSpawnVolumes()
function SetupNextWave(byte NextWaveIndex, int TimeToNextWaveBuffer = 0)
{
local KFGameReplicationInfo KFGRI;
local bool bIsBossRush;
if (OutbreakEvent.ActiveEvent.bBossRushMode)
bIsBossRush = OutbreakEvent != none && OutbreakEvent.ActiveEvent.bBossRushMode;
if (bIsBossRush)
{
NextWaveIndex = MyKFGRI.WaveMax - 1;
}
@ -255,7 +305,7 @@ function SetupNextWave(byte NextWaveIndex, int TimeToNextWaveBuffer = 0)
// Initialize our recycle number
NumSpecialSquadRecycles = 0;
if (MyKFGRI.IsBossWave() || OutbreakEvent.ActiveEvent.bBossRushMode)
if (MyKFGRI.IsBossWave() || bIsBossRush)
{
WaveTotalAI = 1;
}
@ -1208,6 +1258,7 @@ function KFSpawnVolume GetBestSpawnVolume( optional array< class<KFPawn_Monster>
{
local int VolumeIndex, ControllerIndex;
local Controller RateController;
local KFGameReplicationInfo KFGRI;
if( OverrideController != none )
{
@ -1250,6 +1301,13 @@ function KFSpawnVolume GetBestSpawnVolume( optional array< class<KFPawn_Monster>
// pre-sort the list to reduce the number of line checks performed by IsValidForSpawn
SortSpawnVolumes(RateController, bTeleporting, MinDistSquared);
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none && KFGRI.IsVIPMode())
{
SortVIPSpawnVolumes();
}
for ( VolumeIndex = 0; VolumeIndex < SpawnVolumes.Length; VolumeIndex++ )
{
if ( SpawnVolumes[VolumeIndex].IsValidForSpawn(DesiredSquadType, OtherController)
@ -1396,5 +1454,8 @@ defaultproperties
MaxBossMinionScaleByPlayers(5)=2.0 // 6 players
bForceRequiredSquad=false
VIP_CurrentSpawnCounter = 0
VIP_MaxSpawnCounter = 5
}

View File

@ -19,8 +19,15 @@ var localized string FailedToReachInventoryServerString;
var localized array<string> DifficultyStrings;
var localized array<string> LengthStrings;
var localized string SpecialLengthString;
var localized string WeaponLevelString;
var localized string GunPointsString;
var localized string VIPString;
var localized string VIPObjectiveAString;
var localized string VIPObjectiveBString;
var localized string VIPObjectiveCString;
var localized array<string> ServerTypeStrings;
var localized array<string> PermissionStrings;
var localized array<string> ConsolePermissionStrings;

View File

@ -0,0 +1,36 @@
//=============================================================================
// KFDT_Ballistic_HRG_Locust
//=============================================================================
// HRG Locust bullet impact
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Toxic_HRG_Locust extends KFDT_Bleeding
abstract
hidedropdown;
// Damage dealt when zeds touch each other and spread the afflictions
var int SpreadOnTouchDamage;
static function int GetSpreadOnTouchDamage()
{
return default.SpreadOnTouchDamage;
}
defaultproperties
{
DoT_Type=DOT_Bleeding
DoT_Duration=3.0
DoT_Interval=0.5
DoT_DamageScale=1.0
BleedPower = 20
PoisonPower = 25
ModifierPerkList(0)=class'KFPerk_Survivalist'
WeaponDef=class'KFWeapDef_HRG_Locust'
SpreadOnTouchDamage=40
}

View File

@ -40,6 +40,9 @@ var bool bConsideredIndirectOrAoE;
/** If true, this damagetype will destroy a door if closed and unwelded */
var bool bAllowAIDoorDestruction;
/** If true can PlayDeadHitEffects the Zeds when killing them */
var bool bCanPlayDeadHitEffects;
/*********************************************************************************************
Damage over time
********************************************************************************************* */
@ -233,6 +236,9 @@ var AKEvent OverrideImpactSound;
//For use on in world trap damage types
var bool bIsTrapDamage;
//When doing armour piercing damage (this is a % of total damage received, the rest is considered as base if defined)
var float DamageModifierAP;
/**
* Take the primary HitDirection and modify it to add more spread.
* Use the BloodSpread property to calculate the spread amount
@ -421,6 +427,11 @@ static function bool AlwaysPoisons()
/** Do anything related to killing a pawn */
static function ApplyKillResults(KFPawn KilledPawn);
static function bool CanPlayDeadHitEffects()
{
return default.bCanPlayDeadHitEffects;
}
Defaultproperties
{
bNoPain=false
@ -444,4 +455,8 @@ Defaultproperties
bCanObliterate=false;
bHasToSpawnMicrowaveFire=true
DamageModifierAP=0.f
bCanPlayDeadHitEffects=true
}

View File

@ -121,14 +121,14 @@ protected simulated function bool DoExplosionDamage(bool bCauseDamage, bool bCau
if(bOnlyDamagePawns)
{
return ExplodePawns();
return ExplodePawns(bCauseDamage);
}
return super.DoExplosionDamage(bCauseDamage, bCauseEffects);
}
/** Stripped down and optimized version of DoExplosionDamage that only checks for pawns */
protected simulated function bool ExplodePawns()
protected simulated function bool ExplodePawns(bool bCauseDamage)
{
local Pawn Victim;
local float CheckRadius;
@ -171,6 +171,11 @@ protected simulated function bool ExplodePawns()
DamageScale = (DamageScalePerStack < 1.f) ? CalcStackingDamageScale(KFPawn(Victim), Interval) : 1.f;
if ( DamageScale > 0.f )
{
if (bCauseDamage == false)
{
DamageScale = 0.f; // We still want effects
}
AffectsPawn(Victim, DamageScale);
bHitPawn = true;
}

View File

@ -38,7 +38,7 @@ simulated function Explode(GameExplosion NewExplosionTemplate, optional vector D
ExplosionTemplate.MyDamageType = class'KFPerk_Demolitionist'.static.GetLingeringDamageType();
}
protected simulated function bool ExplodePawns()
protected simulated function bool ExplodePawns(bool bCauseDamage)
{
local Pawn Victim;
local float CheckRadius;

View File

@ -26,6 +26,8 @@ var class<KFDamageType> ZedativeDamageType;
var class<KFDamageType> ZedativeHealingType;
var int ZedativeEffectRadius;
var array<KFPawn_Human> AffectedHumans;
replication
{
if(bNetInitial)
@ -79,16 +81,16 @@ protected simulated function AffectsPawn(Pawn Victim, float DamageScale)
local Actor HitActor;
local bool bDamageBlocked;
if( bWasFadedOut|| bDeleteMe || bPendingDelete )
{
return;
}
if( Victim != none && Victim.IsAliveAndWell() )
{
MonsterVictim = KFPawn_Monster(Victim);
if( MonsterVictim != none )
{
if( bWasFadedOut|| bDeleteMe || bPendingDelete )
{
return;
}
Victim.GetComponentsBoundingBox(BBox);
BBoxCenter = (BBox.Min + BBox.Max) * 0.5f;
HitActor = TraceExplosive(BBoxCenter, Location + vect(0, 0, 20));
@ -109,7 +111,12 @@ protected simulated function AffectsPawn(Pawn Victim, float DamageScale)
HumanVictim = KFPawn_Human(Victim);
if( HumanVictim != none && HumanVictim.GetExposureTo(Location) > 0 )
{
HumanVictim.HealDamage(ZedativeHealth, InstigatorController, ZedativeHealingType, false);
if (AffectedHumans.Find(HumanVictim) == INDEX_NONE)
{
AffectedHumans.AddItem(HumanVictim);
HumanVictim.HealDamage(ZedativeHealth, InstigatorController, ZedativeHealingType, false);
}
}
}
}

View File

@ -31,6 +31,10 @@ var localized string AimAssistLockOnString;
var localized string AimAssistRotationString;
var localized string AimAssistSlowDownString;
var localized string ForceFeedbackString;
var localized string MouseLookUpScaleString;
var localized string MouseLookRightScaleString;
var localized string ViewSmoothingString;
var localized string ViewAccelerationString;
var KFGFxOptionsMenu_Controls ControlsMenu;
@ -61,6 +65,14 @@ function LocalizeText()
LocalizedObject.SetString("controllerDeadzoneLabel" , ControllerDeadzoneString);
LocalizedObject.SetString("controllerAccelerationJumpLabel" , ControllerAccelerationJumpString);
if(!class'WorldInfo'.static.IsConsoleBuild() )
{
LocalizedObject.SetString("lookUpScaleLabel", MouseLookUpScaleString);
LocalizedObject.SetString("lookRightScaleLabel", MouseLookRightScaleString);
LocalizedObject.SetString("viewSmoothingLabel", ViewSmoothingString);
LocalizedObject.SetString("viewAccelerationLabel", ViewAccelerationString);
}
// Localization alternative for Xbox
if( class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Durango) )
{
@ -104,8 +116,19 @@ function InitializeOptions()
ValuesObject.SetBool("invertedValue" , KFPI.bInvertMouse);
ValuesObject.SetBool("mouseSmoothingLabel" , KFPI.bEnableMouseSmoothing);
ValuesObject.SetFloat("lookUpScaleValue" , -KFPI.MouseLookUpScale);
ValuesObject.SetFloat("lookUpScaleMin" , ControlsMenu.MinMouseLookUpScale);
ValuesObject.SetFloat("lookUpScaleMax" , ControlsMenu.MaxMouseLookUpScale);
ValuesObject.SetFloat("lookRightScaleValue" , KFPI.MouseLookRightScale);
ValuesObject.SetFloat("lookRightScaleMin" , ControlsMenu.MinMouseLookRightScale);
ValuesObject.SetFloat("lookRightScaleMax" , ControlsMenu.MaxMouseLookRightScale);
ValuesObject.SetBool("viewSmoothingValue" , KFPI.bViewSmoothingEnabled);
ValuesObject.SetBool("viewAccelerationValue" , KFPI.bViewAccelerationEnabled);
}
ValuesObject.SetBool("forceFeedbackValue" , KFPI.bForceFeedbackEnabled);
ValuesObject.SetFloat("controllerSensitivityValue" , 100 * KFPI.GamepadSensitivityScale);
@ -152,6 +175,23 @@ function ResetInputOptions()
KFPI.bEnableMouseSmoothing = ControlsMenu.Manager.CachedProfile.GetDefaultBool(KFID_EnableMouseSmoothing);
ControlsMenu.Manager.CachedProfile.SetProfileSettingValueBool(KFID_EnableMouseSmoothing, KFPI.bEnableMouseSmoothing);
KFPI.MouseLookUpScale = ControlsMenu.Manager.CachedProfile.GetDefaultFloat(KFID_MouseLookUpScale);
ControlsMenu.Manager.CachedProfile.SetProfileSettingValueFloat(KFID_MouseLookUpScale, KFPI.MouseLookUpScale);
KFPI.LookUpScale = KFPI.MouseLookUpScale;
class'PlayerInput'.default.LookUpScale = KFPI.MouseLookUpScale;
KFPI.MouseLookRightScale = ControlsMenu.Manager.CachedProfile.GetDefaultFloat(KFID_MouseLookRightScale);
ControlsMenu.Manager.CachedProfile.SetProfileSettingValueFloat(KFID_MouseLookRightScale, KFPI.MouseLookRightScale);
KFPI.LookRightScale = KFPI.MouseLookRightScale;
class'PlayerInput'.default.LookRightScale = KFPI.MouseLookRightScale;
class'PlayerInput'.static.StaticSaveConfig();
KFPI.bViewSmoothingEnabled = ControlsMenu.Manager.CachedProfile.GetDefaultBool(KFID_ViewSmoothingEnabled);
ControlsMenu.Manager.CachedProfile.SetProfileSettingValueBool(KFID_ViewSmoothingEnabled, KFPI.bViewSmoothingEnabled);
KFPI.bViewAccelerationEnabled = ControlsMenu.Manager.CachedProfile.GetDefaultBool(KFID_ViewAccelerationEnabled);
ControlsMenu.Manager.CachedProfile.SetProfileSettingValueBool(KFID_ViewAccelerationEnabled, KFPI.bViewAccelerationEnabled);
}
//durango

View File

@ -30,6 +30,8 @@ var int LastEXPValue;
var localized string EXPString;
var float LastUpdateTime;
function InitializeHUD()
{
MyPC = KFPlayerController(GetPC());
@ -48,9 +50,11 @@ function TickHud(float DeltaTime)
UpdateArmor();
UpdateHealer();
UpdateGlobalDamage();
LastUpdateTime = MyPC.WorldInfo.TimeSeconds;
}
function ShowActiveIndicators( array<string> IconPathStrings )
function ShowActiveIndicators( array<ActiveSkill> ActiveSkills )
{
local byte i;
local GFxObject DataProvider;
@ -58,11 +62,14 @@ function ShowActiveIndicators( array<string> IconPathStrings )
DataProvider = CreateArray();
for (i = 0; i < IconPathStrings.length; i++)
for (i = 0; i < ActiveSkills.length; i++)
{
//Corresponding AS3 class reads string off of the object to load in icon
TempObj = CreateObject( "Object" );
TempObj.SetString( "iconPath", "img://"$IconPathStrings[i] );
TempObj.SetString( "iconPath", "img://" $ActiveSkills[i].IconPath );
TempObj.SetInt( "Multiplier", ActiveSkills[i].Multiplier );
TempObj.SetFloat( "MaxDuration", ActiveSkills[i].MaxDuration );
TempObj.SetFloat( "Duration", ActiveSkills[i].Duration );
DataProvider.SetElementObject( i, TempObj );
}
@ -229,5 +236,5 @@ function UpdateGlobalDamage()
DefaultProperties
{
LastUpdateTime = 0.f;
}

View File

@ -141,12 +141,21 @@ struct InventoryHelper
var int SkinType;
var ItemRarity Rarity;
var int Quality;
// For ordering items
var string KeyName;
var bool IsKey;
};
var array<InventoryHelper> SkinListWeaponsSearchCache;
var array<InventoryHelper> SkinListOrderedCache;
var bool NeedToRegenerateSkinList;
struct ByTypeItemsHelper
{
var() array<InventoryHelper> ItemsOnType;
};
var EInventoryWeaponType_Filter CurrentWeaponTypeFilter;
var int CurrentPerkIndexFilter;
var ItemRarity CurrentRarityFilter;
@ -282,41 +291,12 @@ final function int Crc(coerce string Text)
return CrcValue;
}
delegate int SortByWeaponTypeDefinition(InventoryHelper A, InventoryHelper B)
delegate int SortSkinList(InventoryHelper A, InventoryHelper B)
{
return A.WeaponDef < B.WeaponDef ? -1 : +1;
}
delegate int SortByPrice(InventoryHelper A, InventoryHelper B)
{
return A.Price > B.Price ? -1 : +1;
}
delegate int SortByRarity(InventoryHelper A, InventoryHelper B)
{
return A.Rarity > B.Rarity ? -1 : +1;
}
delegate int SortBySkinType(InventoryHelper A, InventoryHelper B)
{
return A.SkinType > B.SkinType ? -1 : +1;
}
delegate int SortByQuality(InventoryHelper A, InventoryHelper B)
{
return A.Quality < B.Quality ? -1 : +1;
}
delegate int SortByAll(InventoryHelper A, InventoryHelper B)
{
//local int WeapDefValue, SkinTypeValue;
/** Format: Compare lower ? -1 : (Compare upper) : 1 : (Equal case, repeat formula with the next sort condition) */
return A.Price > B.Price ? -1 : (A.Price < B.Price ? 1 : (
//STRCompare(A.WeaponDef, B.WeaponDef, WeapDefValue) < 0 ? -1 : ( WeapDefValue != 0 ? 1 : (
A.WeaponDef < B.WeaponDef ? -1 : (A.WeaponDef > B.WeaponDef ? 1 : (
A.Rarity > B.Rarity ? -1 : (A.Rarity < B.Rarity ? 1 : (
//STRCompare(A.SkinType, B.SkinType, SkinTypeValue) > 0 ? -1 : ( SkinTypeValue != 0 ? 1 : (
A.SkinType > B.SkinType ? -1 : (A.SkinType < B.SkinType ? 1 : (
A.Quality < B.Quality ? -1 : 1
))
@ -325,13 +305,33 @@ delegate int SortByAll(InventoryHelper A, InventoryHelper B)
));
}
delegate int SortItemList(InventoryHelper A, InventoryHelper B)
{
if (A.IsKey && B.IsKey)
{
return 0;
}
if (A.IsKey == false && B.IsKey == false)
{
return 0;
}
if (A.IsKey)
{
return 1;
}
return -1;
}
function InitInventory()
{
local int i, ItemIndex, HelperIndex, WeaponItemID, SearchWeaponSkinIndex;
local int i, j, z, ItemIndex, HelperIndex, WeaponItemID, SearchWeaponSkinIndex, SearchKeyKeywordIndex;
local ItemProperties TempItemDetailsHolder;
local GFxObject ItemArray, ItemObject;
local bool bActiveItem;
local array<InventoryHelper> ActiveItems, ValidSkinItems, FailedSkinItems;
local ByTypeItemsHelper ByTypeItems[7];
local InventoryHelper HelperItem;
local array<ExchangeRuleSets> ExchangeRules;
local class<KFWeaponDefinition> WeaponDef;
@ -348,6 +348,10 @@ function InitInventory()
return;
}
// While reading from the profile we also order by type, then we might want to order again some stuff that's inside the same item type later
//`Log("NEW MENU OPEN: " $CurrentInventoryFilter);
for (i = 0; i < OnlineSub.CurrentInventory.length; i++)
{
//look item up to get info on it.
@ -358,22 +362,25 @@ function InitInventory()
{
TempItemDetailsHolder = OnlineSub.ItemPropertiesList[ItemIndex];
if (((CurrentInventoryFilter == EInv_All || Int(CurrentInventoryFilter) == Int(TempItemDetailsHolder.Type)) && DoesMatchFilter(TempItemDetailsHolder)) || bool(OnlineSub.CurrentInventory[i].NewlyAdded))
if (((CurrentInventoryFilter == EInv_All || Int(CurrentInventoryFilter) == Int(TempItemDetailsHolder.Type))
&& DoesMatchFilter(TempItemDetailsHolder))
|| bool(OnlineSub.CurrentInventory[i].NewlyAdded))
{
ItemObject = CreateObject("Object");
HelperIndex = ActiveItems.Find('ItemDefinition', onlineSub.CurrentInventory[i].Definition);
ItemObject = CreateObject("Object");
HelperIndex = ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType.Find('ItemDefinition', onlineSub.CurrentInventory[i].Definition);
if (HelperIndex == INDEX_NONE)
{
HelperItem.Type = TempItemDetailsHolder.Type;
//HelperItem.FullName = TempItemDetailsHolder.Name;
HelperItem.ItemDefinition = onlineSub.CurrentInventory[i].Definition;
HelperItem.ItemCount = onlineSub.CurrentInventory[i].Quantity;
if (TempItemDetailsHolder.Type == ITP_WeaponSkin)
{
// Copy required stuff
//HelperItem.FullName = TempItemDetailsHolder.Name;
HelperItem.Rarity = TempItemDetailsHolder.Rarity;
HelperItem.Quality = TempItemDetailsHolder.Quality;
HelperItem.Rarity = TempItemDetailsHolder.Rarity;
HelperItem.Quality = TempItemDetailsHolder.Quality;
if (bool(OnlineSub.CurrentInventory[i].NewlyAdded))
{
@ -397,6 +404,7 @@ function InitInventory()
// Get the left part of the string without the next "| "
SearchWeaponSkinIndex = InStr(SkinType, "|");
// Store as CRC, that speeds up comparisons later
HelperItem.SkinType = CrC(Left(SkinType, SearchWeaponSkinIndex));
WeaponItemID = class'KFWeaponSkinList'.default.Skins.Find('Id', HelperItem.ItemDefinition);
@ -406,6 +414,7 @@ function InitInventory()
WeaponDef = class'KFWeaponSkinList'.default.Skins[WeaponItemID].WeaponDef;
// All Weapons start by KFGameContent.KFWeap_ Skip that prefix.
// Store as CRC, that speeds up comparisons later
HelperItem.WeaponDef = CrC(Mid(WeaponDef.default.WeaponClassPath, 21));
HelperItem.Price = WeaponDef.default.BuyPrice;
}
@ -418,18 +427,22 @@ function InitInventory()
SkinListWeaponsSearchCache.AddItem(HelperItem);
}
}
else
{
HelperItem.KeyName = TempItemDetailsHolder.KeyName;
}
ActiveItems.AddItem(HelperItem);
HelperIndex = ActiveItems.length - 1;
ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType.AddItem(HelperItem);
HelperIndex = ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType.Length - 1;
}
else
{
ActiveItems[HelperIndex].ItemCount += onlineSub.CurrentInventory[i].Quantity;
ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType[HelperIndex].ItemCount += onlineSub.CurrentInventory[i].Quantity;
}
OnlineSub.IsExchangeable(onlineSub.CurrentInventory[i].Definition, ExchangeRules);
ItemObject.SetInt("count", ActiveItems[HelperIndex].ItemCount);
ItemObject.SetInt("count", ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType[HelperIndex].ItemCount);
ItemObject.SetString("label", TempItemDetailsHolder.Name);
ItemObject.SetString("price", TempItemDetailsHolder.price);
ItemObject.Setstring("typeRarity", TempItemDetailsHolder.ShortDescription);
@ -445,7 +458,7 @@ function InitInventory()
ItemObject.SetInt("definition", TempItemDetailsHolder.Definition);
ItemObject.SetBool("newlyAdded", bool(OnlineSub.CurrentInventory[i].NewlyAdded) );
ActiveItems[HelperIndex].GfxItemObject = ItemObject;
ByTypeItems[TempItemDetailsHolder.Type].ItemsOnType[HelperIndex].GfxItemObject = ItemObject;
if(onlineSub.CurrentInventory[i].Definition == Manager.SelectIDOnOpen)
{
@ -465,86 +478,84 @@ function InitInventory()
OnlineSub.ClearNewlyAdded();
if (CurrentInventoryFilter == EInv_WeaponSkins)
if (CurrentInventoryFilter == EInv_All || CurrentInventoryFilter == EInv_WeaponSkins)
{
// If need to refresh... we regenerate the list, if not reuse our Cache
NeedToRegenerateSkinList = NeedToRegenerateSkinList || ActiveItems.Length != SkinListOrderedCache.Length;
NeedToRegenerateSkinList = NeedToRegenerateSkinList || ByTypeItems[ITP_WeaponSkin].ItemsOnType.Length != SkinListOrderedCache.Length;
if (NeedToRegenerateSkinList)
{
NeedToRegenerateSkinList = false;
/*`Log("START ORDERING!!!");
`Log("----------");*/
for (i = 0 ; i < ActiveItems.Length; i++)
{
// If doesn't have weapon definition, don't consider, only add as FailedItem to be added at the end
if (ActiveItems[i].WeaponDef != -1)
{
ValidSkinItems.AddItem(ActiveItems[i]);
}
else
{
FailedSkinItems.AddItem(ActiveItems[i]);
}
}
// Now we have all valid weapons
// We want to order by Price - Weapon Def - Rarity - Quality
// So we order inverse that way we keep the final list with the design intention
ValidSkinItems.Sort(SortByAll);
ByTypeItems[ITP_WeaponSkin].ItemsOnType.Sort(SortSkinList);
SkinListOrderedCache = ValidSkinItems;
SkinListOrderedCache = ByTypeItems[ITP_WeaponSkin].ItemsOnType;
/*`Log("----------");*/
/*for (i = 0 ; i < SkinListOrderedCache.Length; i++)
{
`Log("ID : " $SkinListOrderedCache[i].ItemDefinition);
`Log("Weapon Def : " $SkinListOrderedCache[i].WeaponDef);
`Log("Price : " $SkinListOrderedCache[i].Price);
//`Log("Full Name : " $SkinListOrderedCache[i].FullName);
`Log("Full Name : " $SkinListOrderedCache[i].FullName);
`Log("Skin : " $SkinListOrderedCache[i].SkinType);
`Log("Rarity : " $SkinListOrderedCache[i].Rarity);
`Log("Quality : " $SkinListOrderedCache[i].Quality);
`Log("----------");
}*/
// FailedItems are weapons that don't have a Weapon Definition, this might be a case with old unsupported content?
for (i = 0; i < FailedSkinItems.Length; i++)
{
/*if (FailedSkinItems[i].FullName != "")
{
`Log("FailedSkinItems ID : " $FailedSkinItems[i].ItemDefinition);
`Log("FailedSkinItems Price : " $FailedSkinItems[i].Price);
`Log("FailedSkinItems Full Name : " $FailedSkinItems[i].FullName);
`Log("FailedSkinItems Skin : " $FailedSkinItems[i].SkinType);
`Log("FailedSkinItems Rarity : " $FailedSkinItems[i].Rarity);
`Log("FailedFailedSkinItemsItems Quality : " $FailedSkinItems[i].Quality);
`Log("----------");
}*/
SkinListOrderedCache.AddItem(FailedSkinItems[i]);
}
/*`Log("FINISH ORDERING!!!");
`Log("----------");*/
}
else
{
//`Log("USING SKIN LIST CACHE!!!");
}
for (i = 0; i < SkinListOrderedCache.length; i++)
{
ItemArray.SetElementObject(i, SkinListOrderedCache[i].GfxItemObject);
ByTypeItems[ITP_WeaponSkin].ItemsOnType = SkinListOrderedCache;
}
}
else
if (CurrentInventoryFilter == EInv_All || CurrentInventoryFilter == EInv_Consumables)
{
for (i = 0; i < ActiveItems.length; i++)
// Consumables is the type for the "Items" category on the UI
// First we have to distinguish if the Item is a KEY or not
for (i = 0; i < ByTypeItems[ITP_KeyCrate].ItemsOnType.Length; i++)
{
ItemArray.SetElementObject(i, ActiveItems[i].GfxItemObject);
// KeyName is something like : "NameItem:KeyCrate", we first remove the part from the : to the right
SearchKeyKeywordIndex = InStr(ByTypeItems[ITP_KeyCrate].ItemsOnType[i].KeyName, ":");
ByTypeItems[ITP_KeyCrate].ItemsOnType[i].KeyName = Left(ByTypeItems[ITP_KeyCrate].ItemsOnType[i].KeyName, SearchKeyKeywordIndex);
// Then we search if the name of the Item contains "Key"
SearchKeyKeywordIndex = InStr(ByTypeItems[ITP_KeyCrate].ItemsOnType[i].KeyName, "Key");
if (SearchKeyKeywordIndex != -1)
{
ByTypeItems[ITP_KeyCrate].ItemsOnType[i].IsKey = true;
}
else
{
ByTypeItems[ITP_KeyCrate].ItemsOnType[i].IsKey = false;
}
}
ByTypeItems[ITP_KeyCrate].ItemsOnType.Sort(SortItemList);
}
//`Log("--------------------------------");
z = 0;
for (i = 0; i < ArrayCount(ByTypeItems); i++)
{
for (j = 0 ; j < ByTypeItems[i].ItemsOnType.Length; j++)
{
ItemArray.SetElementObject(z, ByTypeItems[i].ItemsOnType[j].GfxItemObject);
++z;
}
}

View File

@ -72,7 +72,8 @@ var KFGFxWidget_MapText MapTextWidget;
var KFGFxWidget_MapCounterText MapCounterTextWidget;
// Widget that displays gun mode texts
var KFGFxWidget_GunGame GunGameWidget;
// Widget that displays vip mode texts
var KFGFxWidget_VIP VIPWidget;
var KFPlayerController KFPC;
@ -108,6 +109,9 @@ var string PendingKickPlayerName;
// Gun game variables
var transient bool bLastGunGameVisibility;
// VIP variables
var transient bool bLastVIPVisibility;
/** On creation of the HUD */
function Init(optional LocalPlayer LocPlay)
{
@ -361,6 +365,13 @@ event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
SetWidgetPathBinding( Widget, WidgetPath );
}
break;
case 'VIPContainer':
if (VIPWidget == none)
{
VIPWidget=KFGFxWidget_VIP(Widget);
SetWidgetPathBinding( Widget, WidgetPath );
}
break;
}
return true;
@ -389,7 +400,7 @@ function UpdateWeaponSelect()
/** Update all the unique HUD pieces */
function TickHud(float DeltaTime)
{
local bool bGunGameVisibility;
local bool bGunGameVisibility, bVIPModeVisibility;
if(KFPC == none || KFPC.WorldInfo.TimeSeconds - LastUpdateTime < UpdateInterval )
{
@ -456,8 +467,6 @@ function TickHud(float DeltaTime)
TraderCompassWidget.TickHUD( DeltaTime);
}
if(GfxScoreBoardPlayer != none)
{
GfxScoreBoardPlayer.TickHud(DeltaTime);
@ -478,6 +487,17 @@ function TickHud(float DeltaTime)
bLastGunGameVisibility = bGunGameVisibility;
}
}
if (VIPWidget != none)
{
bVIPModeVisibility = KFPC.CanUseVIP();
if (bVIPModeVisibility != bLastVIPVisibility)
{
VIPWidget.UpdateVIPVisibility(bVIPModeVisibility);
bLastVIPVisibility = bVIPModeVisibility;
}
}
}
function UpdateObjectiveActive()
@ -1141,6 +1161,26 @@ function UpdateGunGameWidget(int score, int max_score, int level, int max_level)
}
}
function UpdateVIP(ReplicatedVIPGameInfo VIPInfo, bool bIsVIP)
{
local KFGameReplicationInfo KFGRI;
KFGRI=KFGameReplicationInfo(KFPC.WorldInfo.GRI);
if (VipWidget == none || KFGRI == none || !KFGRI.IsVIPMode())
{
return;
}
if (bIsVIP)
{
VIPWidget.SetVIP();
}
else if (VipInfo.VIPPlayer != none)
{
VIPWidget.SetNOVIP(VIPInfo.VIPPlayer.PlayerName, VIPInfo.CurrentHealth, VIPInfo.MaxHealth);
}
}
//==============================================================
// Input
//==============================================================
@ -1303,8 +1343,6 @@ function UpdatePauseGameVoteCount(byte YesVotes, byte NoVotes)
{
if(KickVoteWidget != none)
{
`Log("UPDATING PAUSE GAME VOTE COUNT - YES: "$YesVotes);
`Log("UPDATING PAUSE GAME VOTE COUNT - NO: "$NoVotes);
KickVoteWidget.UpdateVoteCount(YesVotes, NoVotes);
}
}
@ -1492,6 +1530,7 @@ DefaultProperties
bIsSpectating=false
bLastGunGameVisibility=true
bLastVIPVisibility=true
WidgetBindings.Add((WidgetName="ObjectiveContainer",WidgetClass=class'KFGFxHUD_ObjectiveConatiner'))
WidgetBindings.Add((WidgetName="SpectatorInfoWidget",WidgetClass=class'KFGFxHUD_SpectatorInfo'))
@ -1518,7 +1557,7 @@ DefaultProperties
WidgetBindings.Add((WidgetName="mapTextWidget", WidgetClass=class'KFGFxWidget_MapText'))
WidgetBindings.Add((WidgetName="counterMapTextWidget", WidgetClass=class'KFGFxWidget_MapCounterText'))
WidgetBindings.ADD((WidgetName="GunGameContainer", WidgetClass=class'KFGFxWidget_GunGame'));
WidgetBindings.ADD((WidgetName="VIPContainer", WidgetClass=class'KFGFxWidget_VIP'));
SpecialWaveIconPath(AT_Clot)="UI_Endless_TEX.ZEDs.UI_ZED_Endless_Cyst"
SpecialWaveIconPath(AT_SlasherClot)="UI_Endless_TEX.ZEDs.UI_ZED_Endless_Slasher"

View File

@ -28,6 +28,10 @@ var const float MinMouseLookSensitivity;
var const float MaxMouseLookSensitivity;
var const float MinMouseLookZoomSensitivity;
var const float MaxMouseLookZoomSensitivity;
var const float MinMouseLookUpScale;
var const float MaxMouseLookUpScale;
var const float MinMouseLookRightScale;
var const float MaxMouseLookRightScale;
var localized array<string> TabStrings;
var localized string HeaderText;
@ -330,6 +334,55 @@ function CallBack_ResetInputOptions()
}
}
function Callback_MouseLookUpScale(float NewValue)
{
local KFPlayerInput KFPI;
NewValue = -NewValue;
KFPI = KFPlayerInput(GetPC().PlayerInput);
KFPI.MouseLookUpScale = NewValue;
KFPI.LookUpScale = NewValue;
class'PlayerInput'.default.LookUpScale = KFPI.MouseLookUpScale;
class'PlayerInput'.static.StaticSaveConfig();
Manager.CachedProfile.SetProfileSettingValueFloat(KFID_MouseLookUpScale, NewValue);
}
function Callback_MouseLookRightScale(float NewValue)
{
local KFPlayerInput KFPI;
KFPI = KFPlayerInput(GetPC().PlayerInput);
KFPI.MouseLookRightScale = NewValue;
KFPI.LookRightScale = NewValue;
class'PlayerInput'.default.LookRightScale = KFPI.MouseLookRightScale;
class'PlayerInput'.static.StaticSaveConfig();
Manager.CachedProfile.SetProfileSettingValueFloat(KFID_MouseLookRightScale, NewValue);
}
function Callback_ViewSmoothingChanged(bool bActive)
{
local KFPlayerInput KFPI;
KFPI = KFPlayerInput(GetPC().PlayerInput);
KFPI.bViewSmoothingEnabled = bActive;
Manager.CachedProfile.SetProfileSettingValueInt(KFID_ViewSmoothingEnabled, bActive ? 1 : 0);
}
function Callback_ViewAccelerationChanged(bool bActive)
{
local KFPlayerInput KFPI;
KFPI = KFPlayerInput(GetPC().PlayerInput);
KFPI.bViewAccelerationEnabled = bActive;
Manager.CachedProfile.SetProfileSettingValueInt(KFID_ViewAccelerationEnabled, bActive ? 1 : 0);
}
defaultproperties
{
MinControllerLookSensitivity=.4
@ -345,6 +398,11 @@ defaultproperties
MinMouseLookZoomSensitivity=.2
MaxMouseLookZoomSensitivity=1
MinMouseLookUpScale=20
MaxMouseLookUpScale=500
MinMouseLookRightScale=20
MaxMouseLookRightScale=500
SubWidgetBindings.Add((WidgetName="keybindingsContainer",WidgetClass=class'KFGFxControlsContainer_Keybinding'))
SubWidgetBindings.Add((WidgetName="inputContainer",WidgetClass=class'KFGFxControlsContainer_Input'))
SubWidgetBindings.Add((WidgetName="controllerPresetsContainer",WidgetClass=class'KFGFxControlsContainer_ControllerPresets'))

View File

@ -0,0 +1,27 @@
class KFGFXSpecialEventObjectivesContainer_Fall2022 extends KFGFxSpecialEventObjectivesContainer;
function Initialize(KFGFxObject_Menu NewParentMenu)
{
super.Initialize(NewParentMenu);
}
DefaultProperties
{
ObjectiveIconURLs[0] = "Halloween2022_UI.UI_Objectives_Halloween2022_CreaturesInDarkness" // Kill 15 Bosses on any map or mode
ObjectiveIconURLs[1] = "Spring_UI.UI_Objectives_Spring_Weekly" // Complete the Weekly on BarmwichTown
ObjectiveIconURLs[2] = "Halloween2022_UI.UI_Objetives_Halloween2022_ElementalMedallions" // Open the Weapon Room
ObjectiveIconURLs[3] = "Halloween2022_UI.UI_Objectives_Halloween2022_ZedOnFire" // Make 50 Zeds to pass through the bonfires of Barmwitch Town
ObjectiveIconURLs[4] = "Halloween2022_UI.UI_Objetives_Halloween2022_LongNightofWitches" // Complete wave 15 on Endless Hard or higher difficulty on Barmwitch Town
//defaults
AllCompleteRewardIconURL="CHR_PlagueDoctorUniform_Item_TEX.potionbackpack.plaguedoctorbackpack_precious_large"
ChanceDropIconURLs[0]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket"
ChanceDropIconURLs[1]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket_golden"
IconURL="halloween2022_ui.KF2_Halloween_BloodandBonfires_SmallLogo"
UsesProgressList[0] = true
UsesProgressList[1] = false
UsesProgressList[2] = false
UsesProgressList[3] = true
UsesProgressList[4] = false
}

View File

@ -182,7 +182,7 @@ function FillWhatsNew()
local SWhatsNew item;
WhatsNewItems.Remove(0, WhatsNewItems.Length);
// Latest Update
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_TidalTerror", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_BloodBonfire", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/");
WhatsNewItems.AddItem(item);
// Featured Ultimate Edition
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_UltimateEdition_Upgrade", "FeaturedItemBundle", "https://store.steampowered.com/app/1914560/KF2__Ultimate_Edition_Upgrade_DLC/");
@ -194,31 +194,31 @@ function FillWhatsNew()
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_Armory_Season_Pass", "ArmorySeasonPass", "https://store.steampowered.com/app/1524820/Killing_Floor_2__Armory_Season_Pass");
WhatsNewItems.AddItem(item);
// Featured Weapon Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_Weaponsbundle", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9369");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Blodd_Bornfires_Weapon_Bundle", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9471");
WhatsNewItems.AddItem(item);
// Featured Weapon
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_ReductoRay", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9367");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Blood_Sickle_Weapon_bundle", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9469");
WhatsNewItems.AddItem(item);
// Featured Weapon
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_Sentinel","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/9368");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_G36C_Weapon_Bundle","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/9467");
WhatsNewItems.AddItem(item);
// Featured Outfit Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_DeepSea_Explorer_Uniforms", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9366");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_PlagueDoctor_Uniforms", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9465");
WhatsNewItems.AddItem(item);
// Featured Time Limited Item
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_SS_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/4928");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/5246");
WhatsNewItems.AddItem(item);
// Featured Weapon Skin Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_DeepSea_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9364");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_Plague_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9457");
WhatsNewItems.AddItem(item);
// Featured Weapon Skin Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_NeonMKVIII_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9362");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_Weapon_skins_XenoPack", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9459");
WhatsNewItems.AddItem(item);
// Featured Weapon Skin Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_Classic_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9363");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_Classic2_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9461");
WhatsNewItems.AddItem(item);
// Featured Weapon Skin Bundle
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Summer2022_Chameleon_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9365");
item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween2022_Chamaleon2_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9463");
WhatsNewItems.AddItem(item);
// Misc Community Links
item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityHub", "Jaegorhorn", "https://steamcommunity.com/app/232090");

View File

@ -447,25 +447,25 @@ DefaultProperties
XboxFilterExceptions[0]="Wasteland Bundle" // Wasteland Outfit Bundle
FeaturedItemIDs[0]=8178 //Whatsnew Gold Ticket
FeaturedItemIDs[1]=9369
FeaturedItemIDs[2]=9367
FeaturedItemIDs[3]=9368
FeaturedItemIDs[4]=9366
FeaturedItemIDs[5]=9364
FeaturedItemIDs[6]=9362
FeaturedItemIDs[7]=9363
FeaturedItemIDs[8]=9365
FeaturedItemIDs[0]=7944 //Whatsnew Gold Ticket
FeaturedItemIDs[1]=9471
FeaturedItemIDs[2]=9469
FeaturedItemIDs[3]=9467
FeaturedItemIDs[4]=9465
FeaturedItemIDs[5]=9457
FeaturedItemIDs[6]=9459
FeaturedItemIDs[7]=9461
FeaturedItemIDs[8]=9463
ConsoleFeaturedItemIDs[0]=8181 //Whatsnew Gold Ticket PSN
ConsoleFeaturedItemIDs[1]=9369
ConsoleFeaturedItemIDs[2]=9367
ConsoleFeaturedItemIDs[3]=9368
ConsoleFeaturedItemIDs[4]=9366
ConsoleFeaturedItemIDs[5]=9364
ConsoleFeaturedItemIDs[6]=9362
ConsoleFeaturedItemIDs[7]=9363
ConsoleFeaturedItemIDs[8]=9365
ConsoleFeaturedItemIDs[0]=7947 //Whatsnew Gold Ticket PSN
ConsoleFeaturedItemIDs[1]=9471
ConsoleFeaturedItemIDs[2]=9469
ConsoleFeaturedItemIDs[3]=9467
ConsoleFeaturedItemIDs[4]=9465
ConsoleFeaturedItemIDs[5]=9457
ConsoleFeaturedItemIDs[6]=9459
ConsoleFeaturedItemIDs[7]=9461
ConsoleFeaturedItemIDs[8]=9463
MaxFeaturedItems=5
}

View File

@ -70,17 +70,24 @@ function SetPerkList()
local GFxObject PerkObject;
local GFxObject DataProvider;
local KFPlayerController KFPC;
local byte i;
local byte i, counter;
local int PerkPercent;
local KFGameReplicationInfo KFGRI;
KFPC = KFPlayerController(GetPC());
if (KFPC != none)
{
DataProvider = CreateArray();
KFGRI = KFGameReplicationInfo(KFPC.WorldInfo.GRI);
counter = 0;
for (i = 0; i < KFPC.PerkList.Length; i++)
{
if (KFGRI != none && !KFGRI.IsPerkAllowed(KFPC.PerkList[i].PerkClass))
{
continue;
}
PerkObject = CreateObject( "Object" );
PerkObject.SetString("name", KFPC.PerkList[i].PerkClass.default.PerkName);
@ -91,7 +98,11 @@ function SetPerkList()
PerkObject.SetInt("perkXP", PerkPercent);
DataProvider.SetElementObject(i, PerkObject);
PerkObject.SetInt("perkIndex", i);
DataProvider.SetElementObject(counter, PerkObject);
++counter;
}
SetObject("perkList", DataProvider);

View File

@ -0,0 +1,49 @@
//=============================================================================
// KFGFxWidget_VIP
//=============================================================================
// HUD Widget that displays VIP messages to the player
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//
//=============================================================================
class KFGFxWidget_VIP extends GFxObject;
function SetVIP()
{
SetString("VIPSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPString);
SetString("VIPObjectiveSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveBString);
SetString("VIPPlayerSet", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveCString);
SetBool("VIPPlayerNameSetVisibility", true);
SetBool("VIPHideHealthBar", true);
}
function SetNOVIP(string VIPPlayerName, int VIPCurrentHealth, int VIPMaxHealth)
{
SetString("VIPSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPString);
SetString("VIPObjectiveSetLocalised", Class'KFCommon_LocalizedStrings'.default.VIPObjectiveAString);
SetString("VIPPlayerSet", VIPPlayerName);
SetBool("VIPPlayerNameSetVisibility", true);
UpdateHealth(VIPCurrentHealth, VIPMaxHealth);
}
function UpdateVIPVisibility(bool visible)
{
if (visible)
{
SetBool("VIPSetVisibility", true);
}
else
{
SetBool("VIPSetVisibility", false);
}
}
function UpdateHealth(int VIPCurrentHealth, int VIPMaxHealth)
{
SetFloat("VIPHealthBarPercentage", VIPMaxHealth != 0 ? (float(VIPCurrentHealth) / VIPMaxHealth) : 0.0f);
}

View File

@ -3902,6 +3902,11 @@ simulated function AddWeaponsFromSpawnList(KFPawn P);
simulated function OverrideHumanDefaults(KFPawn_Human P);
/***********************************************
* @name Helper for halloween 2022 barmwich bonfire seasonal objective
**********************************************/
function ClearActorFromBonfire(Actor Other);
/***********************************************
* @name Damage Modifier for Event
**********************************************/

View File

@ -484,11 +484,11 @@ auto State PendingMatch
{
local int SystemTimeMinutes;
// Update every 30 minutes using system clock for suspend mode.
// Update every minute using system clock for suspend mode.
// Originally tried using GameEnding(), but the TitleData response
// doesn't come back in time for the new map.
SystemTimeMinutes = GetSystemTimeMinutes();
if ( (SystemTimeMinutes - LastSystemTimeMinutes) >= 30 )
if ( (SystemTimeMinutes - LastSystemTimeMinutes) >= 1 )
{
class'KFGameEngine'.static.RefreshOnlineGameData();
LastSystemTimeMinutes = SystemTimeMinutes;

View File

@ -364,6 +364,28 @@ var int CurrentWeeklyIndex;
/** If true, force show skip time between waves ready button */
var bool bForceShowSkipTrader;
/** Struct with replicated information about the VIP mode */
struct native ReplicatedVIPGameInfo
{
var int CurrentHealth;
var int MaxHealth;
var KFPlayerReplicationInfo VIPPlayer;
structdefaultproperties
{
VIPPlayer = none
CurrentHealth = 0
MaxHealth = 0
}
};
var transient ReplicatedVIPGameInfo VIPModeData;
/** Structs are sent as a pack through the network. Split it in variables for optimization. */
var repnotify int VIPRepCurrentHealth;
var repnotify int VIPRepMaxHealth;
var repnotify KFPlayerReplicationInfo VIPRepPlayer;
/************************************
* Steam heartbeat
************************************/
@ -398,7 +420,7 @@ replication
TraderVolume, TraderVolumeCheckType, bTraderIsOpen, NextTrader, WaveNum, bWaveIsEndless, GunGameWavesCurrent, bWaveGunGameIsFinal, AIRemaining, WaveTotalAICount, bWaveIsActive, MaxHumanCount, bGlobalDamage,
CurrentObjective, PreviousObjective, PreviousObjectiveResult, PreviousObjectiveXPResult, PreviousObjectiveVoshResult, MusicIntensity, ReplicatedMusicTrackInfo, MusicTrackRepCount,
bIsUnrankedGame, GameSharedUnlocks, bHidePawnIcons, ConsoleGameSessionGuid, GameDifficulty, GameDifficultyModifier, BossIndex, bWaveStarted, NextObjective, bIsBrokenTrader, bIsWeeklyMode,
CurrentWeeklyIndex, bIsEndlessPaused, bForceSkipTraderUI; //@HSL - JRO - 3/21/2016 - PS4 Sessions
CurrentWeeklyIndex, bIsEndlessPaused, bForceSkipTraderUI, VIPRepCurrentHealth, VIPRepMaxHealth, VIPRepPlayer; //@HSL - JRO - 3/21/2016 - PS4 Sessions
if ( bNetInitial )
GameLength, WaveMax, bCustom, bVersusGame, TraderItems, GameAmmoCostScale, bAllowGrenadePurchase, MaxPerkLevel, bTradersEnabled, bForceShowSkipTrader;
if ( bNetInitial || bNetDirty )
@ -550,14 +572,26 @@ simulated event ReplicatedEvent(name VarName)
{
UpdatePerksAvailable();
}
else if (VarName == 'GunGameWavesCurrent')
else if (VarName == nameof(GunGameWavesCurrent))
{
UpdateHUDWaveCount();
}
else if (VarName == 'bWaveGunGameIsFinal')
else if (VarName == nameof(bWaveGunGameIsFinal))
{
UpdateHUDWaveCount();
}
else if (VarName == nameof(VIPRepCurrentHealth))
{
UpdateVIPCurrentHealth(VIPRepCurrentHealth);
}
else if (VarName == nameof(VIPRepMaxHealth))
{
UpdateVIPMaxHealth(VIPRepMaxHealth);
}
else if (VarName == nameof(VIPRepPlayer))
{
UpdateVIPPlayer(VIPRepPlayer);
}
else
{
super.ReplicatedEvent(VarName);
@ -2269,11 +2303,95 @@ simulated function NotifyWeeklyEventIndex(int EventIndex)
}
/** VIP weekly */
simulated function UpdateVIPMaxHealth(int NewMaxHealth)
{
if (NewMaxHealth != VIPModeData.MaxHealth)
{
VIPModeData.MaxHealth = NewMaxHealth;
if (Role == ROLE_Authority)
{
VIPRepMaxHealth = NewMaxHealth;
bNetDirty = true;
}
if (WorldInfo.NetMode != NM_DedicatedServer)
{
UpdateVIPUI();
}
}
}
simulated function UpdateVIPCurrentHealth(int NewCurrentHealth)
{
if (NewCurrentHealth != VIPModeData.CurrentHealth)
{
VIPModeData.CurrentHealth = NewCurrentHealth;
if (Role == ROLE_Authority)
{
VIPRepCurrentHealth = NewCurrentHealth;
bNetDirty = true;
}
if (WorldInfo.NetMode != NM_DedicatedServer)
{
UpdateVIPUI();
}
}
}
simulated function UpdateVIPPlayer(KFPlayerReplicationInfo NewVIPPlayer)
{
if (NewVIPPlayer == none)
{
return;
}
if (NewVIPPlayer != VIPModeData.VIPPlayer)
{
VIPModeData.VIPPlayer = NewVIPPlayer;
if (Role == ROLE_Authority)
{
VIPRepPlayer = NewVIPPlayer;
bNetDirty = true;
}
if (WorldInfo.NetMode != NM_DedicatedServer)
{
UpdateVIPUI();
}
}
}
simulated function UpdateVIPUI()
{
local KFPlayerController_WeeklySurvival KFPC_WS;
if( WorldInfo.NetMode == NM_DedicatedServer )
{
return;
}
KFPC_WS = KFPlayerController_WeeklySurvival(GetALocalPlayerController());
if (KFPC_WS != none)
{
KFPC_WS.UpdateVIPWidget(VIPModeData);
}
}
simulated function bool IsGunGameMode()
{
return bIsWeeklyMode && CurrentWeeklyIndex == 16;
}
simulated function bool IsVIPMode()
{
return bIsWeeklyMode && CurrentWeeklyIndex == 17;
}
defaultproperties
{
TraderItemsPath="GP_Trader_ARCH.DefaultTraderItems"
@ -2298,4 +2416,7 @@ defaultproperties
bForceSkipTraderUI=false
GunGameWavesCurrent=1
bWaveGunGameIsFinal=false
VIPRepCurrentHealth=0
VIPRepMaxHealth=0
VIPRepPlayer=none
}

View File

@ -206,7 +206,7 @@ static function class<KFGFxSpecialeventObjectivesContainer> GetSpecialEventClass
case SEI_Summer:
return class'KFGFxSpecialEventObjectivesContainer_Summer2022';
case SEI_Fall:
return class'KFGFxSpecialEventObjectivesContainer_Fall2021';
return class'KFGFxSpecialEventObjectivesContainer_Fall2022';
case SEI_Winter:
return class'KFGFXSpecialEventObjectivesContainer_Xmas2021';
}

View File

@ -126,6 +126,10 @@ var const Texture2D GenericHumanIconTexture;
/** Texture used for the generic zed icon */
var const Texture2D GenericZedIconTexture;
/** Texture used for the VIP representation over a player */
var const Texture2D VIPIconTexture;
var const float OriginalVIPIconSize;
/**
* Draw a glowing string
*/
@ -772,7 +776,7 @@ simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
local float ResModifier;
local float PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, PerkIconSize;
local color CurrentArmorColor, CurrentHealthColor;
local float VIPIconSize, VIPIconPosX, VIPIconPosY;
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
@ -812,14 +816,11 @@ simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
CurrentArmorColor = ClassicPlayerInfo ? ClassicArmorColor : ArmorColor;
DrawKFBar(Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight + (36 * FontScale * ResModifier), CurrentArmorColor);
//Draw health bar
PercentageHealth = FMin(float(KFPH.Health) / float(KFPH.HealthMax), 100);
CurrentHealthColor = ClassicPlayerInfo ? ClassicHealthColor : HealthColor;
DrawKFBar(PercentageHealth, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 2 + (36 * FontScale * ResModifier), CurrentHealthColor);
//Draw health being regenerated bar
PercentageHealthToRegen = FMin(float(KFPH.HealthToRegen) / float(KFPH.HealthMax), 100);
PercentageHealthMissing = FMin((float(KFPH.HealthMax) - float(KFPH.Health)) / float(KFPH.HealthMax), 100);
@ -827,6 +828,19 @@ simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
CurrentHealthColor = HealthBeingRegeneratedColor;
DrawKFBar(1, PercentageHealthToRegen * BarLength, BarHeight, ScreenPos.X + BarLength * (PercentageHealth - 0.5f), ScreenPos.Y + BarHeight * 2 + (36 * FontScale * ResModifier), HealthBeingRegeneratedColor);
if (KFGRI != none
&& KFGRI.IsVIPMode()
&& KFPH.PlayerReplicationInfo != none
&& KFGRI.VIPModeData.VIPPlayer != none
&& KFPH.PlayerReplicationInfo == KFGRI.VIPModeData.VIPPlayer)
{
// Draw VIP Icon
VIPIconSize = OriginalVIPIconSize * ResModifier;
VIPIconPosX = ScreenPos.X - VIPIconSize * 0.5f;
VIPIconPosY = ScreenPos.Y - 2.5f * BarHeight + (36 * FontScale * ResModifier) - 20.f * ResModifier - VIPIconSize * 0.5f - 1.f;
DrawVIPIcon(VIPIconSize , VIPIconPosX, VIPIconPosY);
}
if( KFPRI.CurrentPerkClass == none )
{
return false;
@ -862,6 +876,12 @@ simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
return true;
}
simulated function DrawVIPIcon(float VIPIconSize, float VIPIconPosX, float VIPIconPosY)
{
Canvas.SetPos(VIPIconPosX, VIPIconPosY);
Canvas.DrawTile(VIPIconTexture, VIPIconSize, VIPIconSize, 0, 0, 256, 256);
}
simulated function bool DrawScriptedPawnInfo(KFPawn_Scripted KFPS, float NormalizedAngle, bool bRendered)
{
local float Percentage;
@ -1088,7 +1108,7 @@ simulated function CheckAndDrawHiddenPlayerIcons( array<PlayerReplicationInfo> V
}
}
DrawHiddenHumanPlayerIcon( PRI, PawnLocation, Normal((PawnLocation + (class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 2))) - ViewLocation) dot ViewVector);
DrawHiddenHumanPlayerIcon(PRI, PawnLocation, ViewLocation, ViewVector);
}
}
@ -1099,13 +1119,15 @@ simulated function CheckAndDrawHiddenPlayerIcons( array<PlayerReplicationInfo> V
* @param IconWorldLocation The "player's" location in the world
* @Note:This is the one we want to clamp
*/
function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldLocation, float NormalizedAngle)
function DrawHiddenHumanPlayerIcon(PlayerReplicationInfo PRI, vector IconWorldLocation, vector ViewLocation, vector ViewVector)
{
local vector ScreenPos;
local vector ReferencePosition, UpVector, ScreenPos, VIPIconPos, ViewLeftVector;
local float IconSizeMult;
local KFPlayerReplicationInfo KFPRI;
local Texture2D PlayerIcon;
local float ResModifier;
local float VIPIconSize;
local float NormalizedAngle, NormalizedAngleWithLeftView;
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
@ -1115,7 +1137,91 @@ function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldL
return;
}
ScreenPos = Canvas.Project(IconWorldLocation + class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 2));
ReferencePosition = IconWorldLocation + (class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 2));
NormalizedAngle = Normal(ReferencePosition - ViewLocation) dot ViewVector;
ScreenPos = Canvas.Project(ReferencePosition);
if (KFGRI != none
&& KFGRI.IsVIPMode()
&& KFGRI.VIPModeData.VIPPlayer != none
&& PRI != none
&& PRI == KFGRI.VIPModeData.VIPPlayer)
{
VIPIconSize = OriginalVIPIconSize * ResModifier;
VIPIconPos = ScreenPos;
VIPIconPos.X -= VIPIconSize * 0.5f;
// If the player is on front of you
if (NormalizedAngle > 0)
{
// Adjust on X
if (ScreenPos.X < 0 || ScreenPos.X > (Canvas.ClipX - VIPIconSize))
{
if (ScreenPos.X < 0)
{
VIPIconPos.X = 0;
}
else
{
VIPIconPos.X = Canvas.ClipX - VIPIconSize;
}
}
// Adjust on Y
if (ScreenPos.Y < 0 || ScreenPos.Y > (Canvas.ClipY - VIPIconSize))
{
if (ScreenPos.Y < 0)
{
VIPIconPos.Y = 0;
}
else
{
VIPIconPos.Y = Canvas.ClipY - VIPIconSize;
}
}
}
// If the player is behind you
else
{
// New to know if Player is on your left or on your right side..
UpVector.Z = 1;
ViewLeftVector = ViewVector cross UpVector;
NormalizedAngleWithLeftView = Normal(ReferencePosition - ViewLocation) dot ViewLeftVector;
// The X position clamps between minimum and maximum, we don't interpolate in the middle as it makes more difficult for the player to understand
// Where the VIP is
// Adjust on X
if (NormalizedAngleWithLeftView > 0)
{
VIPIconPos.X = 0;
}
else
{
VipIconPos.X = Canvas.ClipX - VIPIconSize;
}
// Adjust on Y
if (ScreenPos.Y < 0 || ScreenPos.Y > (Canvas.ClipY - VIPIconSize))
{
if (ScreenPos.Y < 0)
{
VIPIconPos.Y = 0;
}
else
{
VIPIconPos.Y = Canvas.ClipY - VIPIconSize;
}
}
}
Canvas.SetDrawColorStruct(PlayerBarIconColor);
DrawVIPIcon(VIPIconSize, VIPIconPos.X, VIPIconPos.Y);
}
// Fudge by icon size
IconSizeMult = (PlayerStatusIconSize * 0.8) * ResModifier;
ScreenPos.X -= IconSizeMult;
@ -1135,6 +1241,7 @@ function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldL
{
CurrentAlphaDelta = 5;
}
ScreenPos.X = Canvas.ClipX - ScreenPos.x;
ScreenPos = GetClampedScreenPosition(ScreenPos);
CurrentVoiceCommsHighlightAlpha += CurrentAlphaDelta;
@ -1142,7 +1249,6 @@ function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldL
Canvas.SetDrawColor(255, 255, 255, CurrentVoiceCommsHighlightAlpha);
Canvas.SetPos(ScreenPos.X - (IconSizeMult * VoiceCommsIconHighlightScale / 2), ScreenPos.Y - (IconSizeMult * VoiceCommsIconHighlightScale / 2));
Canvas.DrawTile(IconHighLightTexture, IconSizeMult + (IconSizeMult * VoiceCommsIconHighlightScale), IconSizeMult + (IconSizeMult * VoiceCommsIconHighlightScale), 0, 0, 128, 128);
}
else
{
@ -1372,6 +1478,9 @@ defaultproperties
GenericHumanIconTexture = Texture2D'UI_PerkIcons_TEX.UI_Horzine_H_Logo'
GenericZedIconTexture = Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_ZED'
VIPIConTexture = Texture2D'UI_PerkIcons_TEX.UI_Overscreen_vip_icon_'
OriginalVIPIconSize = 64;
IconHighLightTexture = Texture2D'UI_World_TEX.VoicCommsCircleHighlight'
VoiceCommsIconHighlightScale = 0.5f
CurrentVoiceCommsHighlightAlpha=255

View File

@ -21,6 +21,7 @@ var transient KFWeap_HealerBase HealerWeapon;
/** Localized message for quick heal */
var localized string FullHealthMsg;
var localized string CannotHealthMsg;
/** The number of grenades the character is carrying */
var byte GrenadeCount;
@ -1270,6 +1271,20 @@ simulated function AttemptQuickHeal()
{
local KFWeap_HealerBase W;
local KFPlayerController KFPC;
local KFPlayerController_WeeklySurvival KFPCWS;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
KFPCWS = KFPlayerController_WeeklySurvival(Instigator.Owner);
// VIP cannot heal
if (KFGRI != none
&& KFGRI.VIPRepPlayer != none
&& KFGRI.VIPRepPlayer == KFPlayerReplicationInfo(KFPCWS.PlayerReplicationInfo))
{
KFPCWS.MyGFxHUD.ShowNonCriticalMessage(CannotHealthMsg);
return;
}
// Do not heal if we have full health
if ( Instigator.Health >= Instigator.HealthMax )

View File

@ -57,6 +57,8 @@ var() float AnimBlendRate;
var transient float LaserSightAimStrength;
var transient float DesiredAimStrength;
var transient bool IsVisible;
/** Create/Attach lasersight components */
function AttachLaserSight(SkeletalMeshComponent OwnerMesh, bool bFirstPerson, optional name SocketNameOverride)
{
@ -135,6 +137,8 @@ simulated function SetMeshLightingChannels(LightingChannelContainer NewLightingC
simulated event ChangeVisibility(bool bVisible)
{
IsVisible = bVisible;
LaserDotMeshComp.SetHidden(!bVisible);
LaserSightMeshComp.SetHidden(!bVisible);
LaserBeamMeshComp.SetHidden(!bVisible);
@ -159,6 +163,11 @@ simulated function Update(float DeltaTime, KFWeapon OwningWeapon)
local Quat Q;
local TraceHitInfo HitInfo;
if (IsVisible == false)
{
return;
}
if( OwningWeapon != None &&
OwningWeapon.Instigator != None &&
OwningWeapon.Instigator.Weapon == OwningWeapon &&
@ -409,4 +418,6 @@ defaultproperties
LaserDotLerpEndDistance=6000.f
LaserDotMaxScale=10.f
LaserDotDepthBias=0.95f
IsVisible=true
}

View File

@ -17,6 +17,7 @@ var localized string ScavengeMessage;
var localized string YouLostMessage;
var localized string YouWonMessage;
var localized string SquadWipedOutMessage;
var localized string SquadWipedOutVIPMessage;
var localized string SquadSurvivedMessage;
var localized string ObjectiveStartMessage;
var localized string ObjectiveWonMessage;
@ -231,6 +232,8 @@ static function ClientReceive(
static function string GetMessageString(int Switch, optional out String SecondaryString, optional byte TeamIndex)
{
local KFGameReplicationInfo KFGRI;
SecondaryString = "";
switch ( Switch )
@ -281,7 +284,16 @@ static function string GetMessageString(int Switch, optional out String Secondar
case GMT_MatchLost:
if(class'WorldInfo'.static.GetWorldInfo().NetMode != NM_Standalone)
{
SecondaryString = default.SquadWipedOutMessage;
KFGRI = KFGameReplicationInfo(class'WorldInfo'.static.GetWorldInfo().GRI);
if (KFGRI != none && KFGRI.bIsWeeklyMode && KFGRI.CurrentWeeklyIndex == 17)
{
SecondaryString = default.SquadWipedOutVIPMessage;
}
else
{
SecondaryString = default.SquadWipedOutMessage;
}
}
return default.YouLostMessage;

View File

@ -71,6 +71,7 @@ defaultproperties
ColumnIds.Add(STATID_ACHIEVE_NetherholdCollectibles)
ColumnIds.Add(STATID_ACHIEVE_CarillonHamletCollectibles)
ColumnIds.Add(STATID_ACHIEVE_RigCollectibles)
ColumnIds.Add(STATID_ACHIEVE_BarmwichCollectibles)
ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky5, Name="AchievementMrPerky5"))
ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky10, Name = "AchievementMrPerky10"))
@ -130,4 +131,5 @@ defaultproperties
ColumnMappings.Add((Id=STATID_ACHIEVE_NetherholdCollectibles,Name="AchievementCollectNetherhold"))
ColumnMappings.Add((Id=STATID_ACHIEVE_CarillonHamletCollectibles,Name="AchievementCollectCarillonHamlet"))
ColumnMappings.Add((Id=STATID_ACHIEVE_RigCollectibles,Name="AchievementCollectRig"))
ColumnMappings.Add((Id=STATID_ACHIEVE_BarmwichCollectibles,Name="AchievementCollectBarmwichTown"))
}

View File

@ -445,6 +445,10 @@ const KFACHID_RigHard = 292;
const KFACHID_RigHellOnEarth = 293;
const KFACHID_RigCollectibles = 294;
const KFACHID_BarmwichHard = 295;
const KFACHID_BarmwichHellOnEarth = 296;
const KFACHID_BarmwichCollectibles = 297;
/* __TW_ANALYTICS_ */
var int PerRoundWeldXP;
var int PerRoundHealXP;
@ -2093,13 +2097,14 @@ defaultproperties
//Firebug Weapons
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Flame_CaulkBurn, KFDT_Bludgeon_CaulkBurn,KFDT_Fire_CaulkBurn,KFDT_Fire_Ground_CaulkNBurn),CompletionAmount=5000)) //3000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Pistol_Flare, KFDT_Bludgeon_FlareGun,KFDT_Fire_FlareGun,KFDT_Fire_FlareGun_Dual,KFDT_Fire_FlareGunDoT),CompletionAmount=7000)) //5000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_DragonsBreath, KFDT_Ballistic_DragonsBreath,KFDT_Bludgeon_DragonsBreath,KFDT_Fire_DragonsBreathDoT),CompletionAmount=7000)) //5000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_DragonsBreath, KFDT_Ballistic_DragonsBreath,KFDT_Bludgeon_DragonsBreath,KFDT_Fire_DragonsBreathDoT, KFDT_Fire_Ground_DragonsBreath),CompletionAmount=7000)) //5000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_SMG_Mac10, KFDT_Bludgeon_Mac10,KFDT_Fire_Mac10,KFDT_Fire_Mac10DoT),CompletionAmount=9000)) //7000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Flame_Flamethrower, KFDT_Bludgeon_Flamethrower,KFDT_Fire_FlameThrower,KFDT_Fire_Ground_FlameThrower),CompletionAmount=9000)) //7000
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_HRGIncendiaryRifle, KFDT_Bludgeon_HRGIncendiaryRifle,KFDT_Ballistic_HRGIncendiaryRifle,KFDT_Explosive_HRGIncendiaryRifle,KFDT_Ballistic_HRGIncendiaryRifleGrenadeImpact,KFDT_Fire_HRGIncendiaryRifleBulletDoT,KFDT_Fire_HRGIncendiaryRifleGrenadeDoT,KFDT_Fire_Ground_HRGIncendiaryRifle),CompletionAmount=9000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Pistol_HRGScorcher, KFDT_Bludgeon_HRGScorcher,KFDT_Ballistic_HRGScorcherLightingImpact,KFDT_Fire_HRGScorcherDoT,KFDT_Ballistic_HRGScorcherBrokenImpact,KFDT_Fire_Ground_HRGScorcher),CompletionAmount=9000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Beam_Microwave, KFDT_Bludgeon_MicrowaveGun,KFDT_Fire_Ground_MicrowaveGun,KFDT_Microwave,KFDT_Microwave_Beam,KFDT_Microwave_Blast),CompletionAmount=10000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HuskCannon, KFDT_Bludgeon_HuskCannon, KFDT_Explosive_HuskCannon, KFDT_HuskCannonDot, KFDT_Explosive_HuskCannonImpact),CompletionAmount=10000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Dragonbreath, KFDT_Ballistic_HRG_Dragonbreath, KFDT_Bludgeon_HRG_Dragonbreath, KFDT_Fire_HRG_DragonsBreathDoT, KFDT_Fire_HRG_DragonsBreathDoT, KFDT_Fire_Ground_HRG_DragonBreath),CompletionAmount=10000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_Microwave, KFDT_Ballistic_MicrowaveRifle, KFDT_Fire_MicrowaveRifleDoT, KFDT_Bludgeon_MicrowaveRifle),CompletionAmount=10000))
//Berserker Weapons
@ -2136,6 +2141,7 @@ defaultproperties
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_FNFal, KFDT_Ballistic_FNFal,KFDT_Bludgeon_FNFal),CompletionAmount=10000))
//Survivalist Weapons
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Locust, KFDT_Bludgeon_HRG_Locust, KFDT_Toxic_HRG_Locust, KFDT_Ballistic_HRG_Locust),CompletionAmount=7000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Ice_FreezeThrower, KFDT_Bludgeon_Freezethrower, KFDT_Freeze_FreezeThrower, KFDT_Freeze_FreezeThrower_IceShards, KFDT_Freeze_Ground_FreezeThrower),CompletionAmount=7000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_EMP_ArcGenerator, KFDT_Bludgeon_ArcGenerator, KFDT_EMP_ArcGenerator_Beam, KFDT_EMP_ArcGeneratorSphereImpact, KFDT_EMP_ArcGenerator_DefaultFiremodeZapDamage, KFDT_EMP_ArcGenerator_AltFiremodeZapDamage),CompletionAmount=9000))
DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_LazerCutter, KFDT_Ballistic_LazerCutter, KFDT_LazerCutter_Beam, KFDT_Bludgeon_LazerCutter),CompletionAmount=10000))
@ -2286,6 +2292,9 @@ defaultproperties
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-RIG),CompletionAmount=1))
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-RIG),CompletionAmount=2))
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-RIG),CompletionAmount=3))
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-BARMWICHTOWN),CompletionAmount=1))
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-BARMWICHTOWN),CompletionAmount=2))
DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-BARMWICHTOWN),CompletionAmount=3))
//Versus Damage
// Per design doc that I have right now, these are x class damage y players, not damage y amount

View File

@ -73,4 +73,6 @@ defaultproperties
Properties.Add((PropertyId = STATID_ACHIEVE_NetherholdCollectibles, Data = (Type = SDT_Int32, Value1 = 0)))
Properties.Add((PropertyId = STATID_ACHIEVE_CarillonHamletCollectibles, Data = (Type = SDT_Int32, Value1 = 0)))
Properties.Add((PropertyId = STATID_ACHIEVE_RigCollectibles, Data = (Type = SDT_Int32, Value1 = 0)))
Properties.Add((PropertyId = STATID_ACHIEVE_BarmwichCollectibles, Data = (Type = SDT_Int32, Value1 = 0)))
}

View File

@ -450,6 +450,11 @@ struct WeeklyOverrides
/** Information about each level in Gun Game Mode */
var() GunGamePerkData GunGamePerksData;
/** VIP targetting */
var() const array< class<KFPawn_Monster> > VIPTargetting;
var() bool bVIPGameMode;
/** Ignores damage caused by headshots. */
var() bool bInvulnerableHeads;
@ -459,9 +464,6 @@ struct WeeklyOverrides
/** Time between waves override. */
var() float TimeBetweenWaves;
/** Wether or not we only can spawn Armor on the Item pickups */
var() bool bOnlyArmorItemPickup;
structdefaultproperties
{
GameLength = GL_Short
@ -522,10 +524,10 @@ struct WeeklyOverrides
bDisableAddDosh = false;
bDisableThrowWeapon = false;
bGunGameMode = false;
bVIPGameMode = false;
bInvulnerableHeads = false;
TraderTimeModifier = 1.f;
TimeBetweenWaves = -1.f;
bOnlyArmorItemPickup=false;
bForceShowSkipTrader = false;
}
};

View File

@ -178,6 +178,10 @@ struct native DamageInfo
var array<class<KFDamageType> > DamageTypes;
};
// VFX that need to linger when a specific DamageType starts (those should loop), we stop them when the DamageType ends affecting
var() ParticleSystem Toxic_HRG_Locust_LoopingParticleEffect;
var transient ParticleSystemComponent Toxic_HRG_Locust_LoopingPSC;
/** List of PRIs who damaged the specimen */
var array<DamageInfo> DamageHistory;
@ -885,6 +889,7 @@ var transient byte LastHitZoneIndex;
*/
var const bool bIsTurret;
var repnotify bool bEnableSwarmVFX;
replication
{
@ -893,7 +898,8 @@ replication
AmbientSound, WeaponClassForAttachmentTemplate, bIsSprinting, InjuredHitZones,
KnockdownImpulse, ReplicatedSpecialMove, bEmpDisrupted, bEmpPanicked, bFirePanicked,
RepFireBurnedAmount, bUnaffectedByZedTime, bMovesFastInZedTime, IntendedBodyScale,
IntendedHeadScale, AttackSpeedModifier, bHasStartedFire, PowerUpAmbientSound, BodyScaleChangePerSecond;
IntendedHeadScale, AttackSpeedModifier, bHasStartedFire, PowerUpAmbientSound, BodyScaleChangePerSecond,
bEnableSwarmVFX;
if ( bNetDirty && WorldInfo.TimeSeconds < LastTakeHitTimeout )
HitFxInfo, HitFxRadialInfo, HitFxInstigator, HitFxAddedRelativeLocs, HitFxAddedHitCount;
if ( Physics == PHYS_RigidBody && !bTearOff )
@ -1171,6 +1177,18 @@ simulated event ReplicatedEvent(name VarName)
break;
case nameof(WeaponSpecialAction):
OnWeaponSpecialAction(WeaponSpecialAction);
break;
case nameof(bEnableSwarmVFX):
if (bEnableSwarmVFX)
{
StartLocustVFX();
}
else
{
StopLocustVFX();
}
break;
}
Super.ReplicatedEvent(VarName);
@ -2709,7 +2727,7 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector
Super.TakeDamage(Damage, InstigatedBy, HitLocation, Momentum, DamageType, HitInfo, DamageCauser);
// using the passed in damage type instead of the hitfxinfo since that doesn't get updated when zero damage is done
// HandleAfflictionsOnHit(InstigatedBy, Normal(Momentum), class<KFDamageType>(DamageType), DamageCauser);
HandleAfflictionsOnHit(InstigatedBy, Normal(Momentum), class<KFDamageType>(DamageType), DamageCauser);
ActualDamage = OldHealth - Health;
if( ActualDamage > 0 )
@ -2811,6 +2829,15 @@ function AdjustDamage(out int InDamage, out vector Momentum, Controller Instigat
InDamage *= VolumeDamageScale;
if (KFPlayerController(Controller) != none)
{
KFPlayerController(Controller).AdjustDamage(InDamage, InstigatedBy, DamageType, DamageCauser, self);
}
else if (KFPlayerController(InstigatedBy) != none)
{
KFPlayerController(InstigatedBy).AdjustDamage(InDamage, InstigatedBy, DamageType, DamageCauser, self);
}
// Check non lethal damage
KFDT = class<KFDamageType>(DamageType);
if ( InDamage >= Health && KFDT != none && KFDT.default.bNonLethalDamage )
@ -2915,6 +2942,30 @@ function AddTakenDamage( Controller DamagerController, int Damage, Actor DamageC
}
}
function TimerRestartForceEnemy()
{
local KFAIController KFAIC;
local Pawn ForcedEnemy;
if (Controller != none)
{
KFAIC = KFAIController( Controller );
if (KFAIC != none)
{
// Forces the ForcedEnemy again
KFAIC.CanForceEnemy = true;
ForcedEnemy = KFAIC.FindForcedEnemy();
if (ForcedEnemy != none)
{
KFAIC.ChangeEnemy(ForcedEnemy);
}
}
}
}
function UpdateDamageHistory( Controller DamagerController, int Damage, Actor DamageCauser, class<KFDamageType> DamageType )
{
local DamageInfo Info;
@ -2943,19 +2994,40 @@ function UpdateDamageHistory( Controller DamagerController, int Damage, Actor Da
DamageHistory[KFAIC.CurrentEnemysHistoryIndex].Damage = 0;
}
if( KFAIC.IsAggroEnemySwitchAllowed()
&& DamagerController.Pawn != KFAIC.Enemy
&& Info.Damage >= DamageThreshold
&& Info.Damage > DamageHistory[KFAIC.CurrentEnemysHistoryIndex].Damage )
// If we have a forced Enemy break it only if we fulfill the minimum health value
if (KFAIC.ForcedEnemy != none)
{
BlockerPawn = KFAIC.GetPawnBlockingPathTo( DamagerController.Pawn, true );
if( BlockerPawn == none )
if (GetHealthPercentage() < KFAIC.DamageRatioToChangeForcedEnemy)
{
bChangedEnemies = KFAIC.SetEnemy(DamagerController.Pawn);
// Only if X seconds passed since last time we choose the ForcedEnemy
if ((WorldInfo.TimeSeconds - KFAIC.ForcedEnemyLastTime) > KFAIC.TimeCannotChangeFromForcedEnemy)
{
KFAIC.CanForceEnemy = false; // The timer we will reenable this to allow selection again
// If we have forced enemy, reactivate ForcedEnemy after X seconds, so it can default to the ForcedEnemy again
ClearTimer('TimerRestartForceEnemy');
SetTimer(KFAIC.TimeCanRestartForcedEnemy, false, 'TimerRestartForceEnemy');
KFAIC.ChangeEnemy(DamagerController.Pawn);
}
}
else
}
else
{
if (KFAIC.IsAggroEnemySwitchAllowed()
&& DamagerController.Pawn != KFAIC.Enemy
&& Info.Damage >= DamageThreshold
&& Info.Damage > DamageHistory[KFAIC.CurrentEnemysHistoryIndex].Damage)
{
bChangedEnemies = KFAIC.SetEnemy( BlockerPawn );
BlockerPawn = KFAIC.GetPawnBlockingPathTo( DamagerController.Pawn, true );
if( BlockerPawn == none )
{
bChangedEnemies = KFAIC.SetEnemy(DamagerController.Pawn);
}
else
{
bChangedEnemies = KFAIC.SetEnemy( BlockerPawn );
}
}
}
}
@ -3403,6 +3475,8 @@ simulated function bool IsHeadless();
/** Clean up function to terminate any effects on death */
simulated function TerminateEffectsOnDeath()
{
local int i;
// Destroy our weapon attachment
if( WeaponAttachment != None && !WeaponAttachment.bPendingDelete )
{
@ -3420,11 +3494,18 @@ simulated function TerminateEffectsOnDeath()
AfflictionHandler.Shutdown();
StopLocustVFX();
// send a special stop event to the audio system
if ( SoundGroupArch.OnDeathStopEvent != None )
{
PostAkEvent( SoundGroupArch.OnDeathStopEvent );
}
for (i = 0 ; i < DamageOverTimeArray.Length; i++)
{
OnEndDamageType(DamageOverTimeArray[i].DamageType);
}
}
/*********************************************************************************************
@ -4043,12 +4124,12 @@ simulated function KFSkinTypeEffects GetHitZoneSkinTypeEffects( int HitZoneIdx )
*/
simulated function AdjustAffliction(out float AfflictionPower);
function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class<DamageType> DamageType, Actor DamageCauser)
function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class<KFDamageType> DamageType, Actor DamageCauser)
{
//Handle afflictions
if (AfflictionHandler != None)
{
AfflictionHandler.NotifyTakeHit(DamageInstigator, HitDir, class<KFDamageType>(DamageType), DamageCauser);
AfflictionHandler.NotifyTakeHit(DamageInstigator, HitDir, DamageType, DamageCauser);
}
}
@ -4084,6 +4165,8 @@ function ApplyDamageOverTime(int Damage, Controller InstigatedBy, class<KFDamage
DoTInfo.InstigatedBy = InstigatedBy;
DoTInfo.TimeUntilNextDamage = KFDT.default.DoT_Interval;
OnStartDamageType(KFDT);
DamageOverTimeArray[DamageOverTimeArray.Length] = DoTInfo;
}
}
@ -4129,12 +4212,34 @@ function TickDamageOverTime(float DeltaTime)
// Remove damage over time elements from the array when they have timed out
if( DamageOverTimeArray[i].Duration <= 0 || DamageOverTimeArray[i].Duration < DamageOverTimeArray[i].Interval )
{
OnEndDamageType(DamageOverTimeArray[i].DamageType);
DamageOverTimeArray.Remove(i,1);
continue;
}
}
}
simulated function OnStartDamageType(class<KFDamageType> DamageType)
{
switch (DamageType.Name)
{
case 'KFDT_Toxic_HRG_Locust':
StartLocustVFX();
break;
}
}
simulated function OnEndDamageType(class<KFDamageType> DamageType)
{
switch (DamageType.Name)
{
case 'KFDT_Toxic_HRG_Locust':
StopLocustVFX();
break;
}
}
/*********************************************************************************************
* @name Animation
********************************************************************************************* */
@ -5408,6 +5513,43 @@ simulated function StopExtraVFX(Name FXLabel)
simulated function SetTurretWeaponAttachment(class<KFWeapon> WeaponClass) {}
simulated function StartLocustVFX()
{
if ( WorldInfo.NetMode == NM_DedicatedServer )
{
bEnableSwarmVFX=true;
bNetDirty = true;
return;
}
if (Toxic_HRG_Locust_LoopingParticleEffect != none)
{
if (Toxic_HRG_Locust_LoopingPSC == none)
{
Toxic_HRG_Locust_LoopingPSC = WorldInfo.MyEmitterPool.SpawnEmitter(Toxic_HRG_Locust_LoopingParticleEffect, Location, Rotation, self);
}
else
{
Toxic_HRG_Locust_LoopingPSC.SetStopSpawning(-1, false);
}
}
}
simulated function StopLocustVFX()
{
if ( WorldInfo.NetMode == NM_DedicatedServer )
{
bEnableSwarmVFX=false;
bForceNetUpdate = true;
return;
}
if (Toxic_HRG_Locust_LoopingPSC != none)
{
Toxic_HRG_Locust_LoopingPSC.SetStopSpawning(-1, true);
}
}
defaultproperties
{
InventoryManagerClass=class'KFInventoryManager'
@ -5674,4 +5816,8 @@ defaultproperties
// ---------------------------------------------
// AutoTurret
bIsTurret=false
Toxic_HRG_Locust_LoopingParticleEffect=ParticleSystem'WEP_HRG_Locust_EMIT.FX_Flying_Bugs_attacking'
Toxic_HRG_Locust_LoopingPSC=none
bEnableSwarmVFX=false
}

View File

@ -157,7 +157,16 @@ var float MinHealthPctToTriggerSurrounded;
/*********************************************************************************************
* @name Perk @ToDo: Move stuff to PRI and combine in a byte/INT
********************************************************************************************* */
var array<string> ActiveSkillIconPaths;
struct native ActiveSkill
{
var string IconPath;
var int Multiplier;
var float MaxDuration;
var float Duration;
};
var private array<ActiveSkill> ActiveSkills;
var repnotify private byte HealingSpeedBoost;
var repnotify private byte HealingDamageBoost;
@ -632,6 +641,7 @@ function float GetHealthMod()
simulated function WeaponStateChanged(byte NewState, optional bool bViaReplication)
{
CurrentWeaponState = NewState;
bForceNetUpdate=true;
// skip if this pawn was recently spawned, so we don't play out-of-date anims when pawns become relevant
if( `TimeSince(CreationTime) < 1.f )
@ -711,6 +721,18 @@ event bool HealDamage(int Amount, Controller Healer, class<DamageType> DamageTyp
local KFPlayerController KFPC;
local KFPowerUp KFPowerUp;
local KFGameInfo GameInfo;
local KFPlayerController_WeeklySurvival KFPCWS;
KFPCWS = KFPlayerController_WeeklySurvival(Healer);
if (Controller != none && KFPCWS != none && KFPCWS.VIPGameData.IsVIP)
{
// VIP can't heal itself
if (Controller == KFPCWS)
{
return false;
}
}
KFPC = KFPlayerController(Controller);
if ( KFPC != none )
@ -896,6 +918,11 @@ function GiveHealthOverTime()
KFPRI.PlayerHealth = Health;
KFPRI.PlayerHealthPercent = FloatToByte( float(Health) / float(HealthMax) );
}
if (KFPlayerController_WeeklySurvival(Controller) != none)
{
KFPlayerController_WeeklySurvival(Controller).UpdateVIPDamage();
}
}
else
{
@ -1272,6 +1299,15 @@ function AdjustDamage(out int InDamage, out vector Momentum, Controller Instigat
}
}
if (KFPlayerController_WeeklySurvival(Controller) != none)
{
KFPlayerController_WeeklySurvival(Controller).AdjustVIPDamage(InDamage, InstigatedBy);
}
else if (KFPlayerController_WeeklySurvival(InstigatedBy) != none)
{
KFPlayerController_WeeklySurvival(InstigatedBy).AdjustVIPDamage(InDamage, InstigatedBy);
}
if( bHasSacrificeSkill && Health >= 5 && Health - InDamage < 5 )
{
Health = InDamage + 5;
@ -1302,8 +1338,14 @@ function AdjustDamage(out int InDamage, out vector Momentum, Controller Instigat
}
}
`endif
if (KFPlayerController_WeeklySurvival(Controller) != none)
{
KFPlayerController_WeeklySurvival(Controller).UpdateVIPDamage();
}
}
event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
{
local int ActualDamageTaken, OldHealth, OldArmor;
@ -1451,12 +1493,17 @@ function StartAirBorneAgentEvent()
simulated function UpdateHealingSpeedBoost()
{
HealingSpeedBoost = Min( HealingSpeedBoost + class'KFPerk_FieldMedic'.static.GetHealingSpeedBoost(), class'KFPerk_FieldMedic'.static.GetMaxHealingSpeedBoost() );
SetTimer( class'KFPerk_FieldMedic'.static.GetHealingSpeedBoostDuration(),, nameOf(ResetHealingSpeedBoost) );
if ( WorldInfo.NetMode == NM_STANDALONE)
if (WorldInfo.NetMode == NM_STANDALONE)
{
NotifyHealingSpeedBoostBuff(HealingSpeedBoost);
}
else
{
ClientNotifyHealingSpeedBoostBuff(HealingSpeedBoost);
}
}
simulated function ResetHealingSpeedBoost()
@ -1482,12 +1529,17 @@ simulated function float GetHealingDamageBoostModifier()
simulated function UpdateHealingDamageBoost()
{
HealingDamageBoost = Min( HealingDamageBoost + class'KFPerk_FieldMedic'.static.GetHealingDamageBoost(), class'KFPerk_FieldMedic'.static.GetMaxHealingDamageBoost() );
SetTimer( class'KFPerk_FieldMedic'.static.GetHealingDamageBoostDuration(),, nameOf(ResetHealingDamageBoost) );
if ( WorldInfo.NetMode == NM_STANDALONE)
if (WorldInfo.NetMode == NM_STANDALONE)
{
NotifyHealingDamageBoostBuff(HealingDamageBoost);
}
else
{
ClientNotifyHealingDamageBoostBuff(HealingDamageBoost);
}
}
simulated function ResetHealingDamageBoost()
@ -1513,12 +1565,17 @@ simulated function float GetHealingShieldModifier()
simulated function UpdateHealingShield()
{
HealingShield = Min( HealingShield + class'KFPerk_FieldMedic'.static.GetHealingShield(), class'KFPerk_FieldMedic'.static.GetMaxHealingShield() );
SetTimer( class'KFPerk_FieldMedic'.static.GetHealingShieldDuration(),, nameOf(ResetHealingShield) );
if ( WorldInfo.NetMode == NM_STANDALONE)
if (WorldInfo.NetMode == NM_STANDALONE)
{
NotifyHealingShieldBoostBuff(HealingShield);
}
else
{
ClientNotifyHealingShieldBoostBuff(HealingShield);
}
}
simulated function ResetHealingShield()
@ -1574,11 +1631,6 @@ function float GetPerkDoTScaler( optional Controller InstigatedBy, optional clas
return DoTScaler;
}
function array<string> GetUpdatedSkillIndicators()
{
return ActiveSkillIconPaths;
}
/*********************************************************************************************
* @name Dialog
********************************************************************************************* */
@ -2060,10 +2112,30 @@ simulated function NotifyHealingSpeedBoostBuff(byte Speed)
if( IsLocallyControlled() )
{
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingSpeedBoost].IconPath, Speed > 0.0f);
UpdateHealingSpeedBoostBuff(Speed);
}
}
reliable client function ClientNotifyHealingSpeedBoostBuff(byte Speed)
{
UpdateHealingSpeedBoostBuff(Speed);
}
simulated function UpdateHealingSpeedBoostBuff(byte Speed)
{
local float TotalTimes, Multiplier;
TotalTimes = class'KFPerk_FieldMedic'.static.GetMaxHealingSpeedBoost() / float(class'KFPerk_FieldMedic'.static.GetHealingSpeedBoost());
Multiplier = Speed / float(class'KFPerk_FieldMedic'.static.GetMaxHealingSpeedBoost());
Multiplier *= TotalTimes;
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingSpeedBoost].IconPath
, Multiplier
, Speed > 0
, class'KFPerk_FieldMedic'.static.GetHealingSpeedBoostDuration());
}
simulated function NotifyHealingDamageBoostBuff(byte Damage)
{
if( Role == ROLE_Authority )
@ -2074,10 +2146,30 @@ simulated function NotifyHealingDamageBoostBuff(byte Damage)
if( IsLocallyControlled() )
{
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingDamageBoost].IconPath, Damage > 0.0f);
UpdateHealingDamageBoostBuff(Damage);
}
}
reliable client function ClientNotifyHealingDamageBoostBuff(byte Damage)
{
UpdateHealingDamageBoostBuff(Damage);
}
simulated function UpdateHealingDamageBoostBuff(byte Damage)
{
local float TotalTimes, Multiplier;
TotalTimes = class'KFPerk_FieldMedic'.static.GetMaxHealingDamageBoost() / float(class'KFPerk_FieldMedic'.static.GetHealingDamageBoost());
Multiplier = Damage / float(class'KFPerk_FieldMedic'.static.GetMaxHealingDamageBoost());
Multiplier *= TotalTimes;
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingDamageBoost].IconPath
, Multiplier
, Damage > 0
, class'KFPerk_FieldMedic'.static.GetHealingDamageBoostDuration());
}
simulated function NotifyHealingShieldBoostBuff(byte Shield)
{
if( Role == ROLE_Authority )
@ -2088,28 +2180,70 @@ simulated function NotifyHealingShieldBoostBuff(byte Shield)
if( IsLocallyControlled() )
{
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingShield].IconPath, Shield > 0.0f);
UpdateHealingShieldBoostBuff(Shield);
}
}
function UpdateActiveSkillsPath(string IconPath, bool Active)
reliable client function ClientNotifyHealingShieldBoostBuff(byte Shield)
{
UpdateHealingShieldBoostBuff(Shield);
}
simulated function UpdateHealingShieldBoostBuff(byte Shield)
{
local float TotalTimes, Multiplier;
TotalTimes = class'KFPerk_FieldMedic'.static.GetMaxHealingShield() / float(class'KFPerk_FieldMedic'.static.GetHealingShield());
Multiplier = Shield / float(class'KFPerk_FieldMedic'.static.GetMaxHealingShield());
Multiplier *= TotalTimes;
UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingShield].IconPath
, Multiplier
, Shield > 0
, class'KFPerk_FieldMedic'.static.GetHealingShieldDuration());
}
function UpdateActiveSkillsPath(string IconPath, int Multiplier, bool Active, float MaxDuration)
{
local KFPlayerController KFPC;
local int i, IndexSearch;
local ActiveSkill active_Skill;
if(Active)
if (Active)
{
if (ActiveSkillIconPaths.Find(IconPath) == INDEX_NONE)
IndexSearch = ActiveSkills.Find('IconPath', IconPath);
if (IndexSearch == INDEX_NONE)
{
ActiveSkillIconPaths.AddItem(IconPath);
active_Skill.IconPath = IconPath;
active_Skill.Multiplier = Multiplier;
active_Skill.MaxDuration = MaxDuration;
active_Skill.Duration = MaxDuration;
ActiveSkills.AddItem(active_Skill);
}
else
{
ActiveSkills[IndexSearch].Multiplier = Multiplier;
ActiveSkills[IndexSearch].MaxDuration = MaxDuration;
ActiveSkills[IndexSearch].Duration = MaxDuration;
}
}
else
{
ActiveSkillIconPaths.RemoveItem(IconPath);
for (i=0; i < ActiveSkills.Length; ++i)
{
if (ActiveSkills[i].IconPath == IconPath)
{
ActiveSkills.Remove(i, 1);
break;
}
}
}
KFPC = KFPlayerController(Controller);
KFPC.MyGFxHUD.PlayerStatusContainer.ShowActiveIndicators(ActiveSkillIconPaths);
KFPC.MyGFxHUD.PlayerStatusContainer.ShowActiveIndicators(ActiveSkills);
}
event Landed(vector HitNormal, actor FloorActor)

View File

@ -1170,11 +1170,18 @@ simulated event Bump( Actor Other, PrimitiveComponent OtherComp, Vector HitNorma
function HandleMonsterBump( KFPawn_Monster Other, Vector HitNormal )
{
local KFPlayerController KFPC;
local int LocustDoTIndex;
local int IgnoredIndex;
if( !Other.IsNapalmInfected() && CanNapalmInfect(KFPC) )
{
InfectWithNapalm( Other, KFPC );
}
if (IsLocustInfected(LocustDoTIndex) && !Other.IsLocustInfected(IgnoredIndex))
{
InfectWithLocust(Other, KFPlayerController(DamageOverTimeArray[LocustDoTIndex].InstigatedBy));
}
}
/** Override to handle special berserker functionality */
@ -2648,12 +2655,19 @@ simulated function int GetRallyBoostResistance( int NewDamage )
function bool Died(Controller Killer, class<DamageType> DamageType, vector HitLocation)
{
local KFGameInfo KFGI;
local KFPlayerController KFPC;
local KFPerk InstigatorPerk;
local int i;
if ( super.Died(Killer, damageType, HitLocation) )
{
KFGI = KFGameInfo(WorldInfo.Game);
if (KFGI != none)
{
KFGI.ClearActorFromBonfire(self);
}
if( Killer != none && Killer.Pawn != none && KFPawn_Human(Killer.Pawn) != none )
{
`DialogManager.PlayKilledZedDialog( KFPawn_Human(Killer.Pawn), self, DamageType, IsDoingSpecialMove(SM_Knockdown) || IsDoingSpecialMove(SM_RecoverFromRagdoll) );
@ -2761,6 +2775,12 @@ simulated function bool IsNapalmInfected()
return DamageOverTimeArray.Find('DamageType', class'KFDT_Fire_Napalm') != INDEX_NONE;
}
simulated function bool IsLocustInfected(out int OutDoTIndex)
{
OutDoTIndex = DamageOverTimeArray.Find('DamageType', class'KFDT_Toxic_HRG_Locust');
return OutDoTIndex != INDEX_NONE;
}
function bool CanNapalmInfect( out KFPlayerController NapalmInstigator )
{
local int DoTIndex;
@ -2802,6 +2822,19 @@ function InfectWithNapalm( KFPawn_Monster KFPM, KFPlayerController KFPC )
}
}
function InfectWithLocust( KFPawn_Monster KFPM, KFPlayerController KFPC )
{
if( KFPC != none )
{
KFPM.TakeDamage( class'KFDT_Toxic_HRG_Locust'.static.GetSpreadOnTouchDamage(),
KFPC,
vect(0,0,0),
vect(0,0,0),
class'KFDT_Toxic_HRG_Locust',,
KFPC );
}
}
/**
* @brief Spawns a radioactive cloud that hurts other Zeds
*
@ -3287,7 +3320,10 @@ simulated function PlayTakeHitEffects( vector HitDirection, vector HitLocation,
if ( bPlayedDeath )
{
PlayDeadHitEffects(HitLocation, HitDirection, HitZoneIndex, HitZoneName, HitBoneName, DmgType, bUseHitImpulse);
if (DmgType.static.CanPlayDeadHitEffects())
{
PlayDeadHitEffects(HitLocation, HitDirection, HitZoneIndex, HitZoneName, HitBoneName, DmgType, bUseHitImpulse);
}
}
else
{

View File

@ -889,7 +889,7 @@ event NotifyPerkModified()
PostLevelUp();
}
private simulated final function PerkSetOwnerHealthAndArmor( optional bool bModifyHealth )
simulated final function PerkSetOwnerHealthAndArmor( optional bool bModifyHealth )
{
// don't allow clients to set health, since health/healthmax/playerhealth/playerhealthpercent is replicated
if( Role != ROLE_Authority )
@ -906,7 +906,15 @@ private simulated final function PerkSetOwnerHealthAndArmor( optional bool bModi
}
OwnerPawn.HealthMax = OwnerPawn.default.Health;
ModifyHealth( OwnerPawn.HealthMax );
if (ModifyHealthMaxWeekly(OwnerPawn.HealthMax))
{
// Change current health directly, Pawn.HealDamage does a lot of other stuff that can block the healing
OwnerPawn.Health = OwnerPawn.HealthMax;
}
OwnerPawn.Health = Min( OwnerPawn.Health, OwnerPawn.HealthMax );
if( OwnerPC == none )
@ -927,6 +935,49 @@ private simulated final function PerkSetOwnerHealthAndArmor( optional bool bModi
}
}
function bool ModifyHealthMaxWeekly(out int InHealth)
{
local KFGameReplicationInfo KFGRI;
local KFPlayerController_WeeklySurvival KFPC_WS;
local bool bNeedToFullyHeal;
KFGRI = KFGameReplicationInfo(Owner.WorldInfo.GRI);
bNeedToFullyHeal = false;
//`Log("PerkSetOwnerHealthAndArmor: Max Health Before Weekly " $OwnerPawn.HealthMax);
if (KFGRI.IsVIPMode())
{
KFPC_WS = KFPlayerController_WeeklySurvival(Owner);
if (KFPC_WS != none && OwnerPawn != none)
{
if (KFPC_WS.VIPGameData.isVIP)
{
// We don't need to check if already applied as this function resets the HealthMax to the value the Perk says
InHealth += KFPC_WS.VIPGameData.ExtraHealth;
// Heal if we are on trader time
if (KFGRI != none && KFGRI.bWaveIsActive == false)
{
bNeedToFullyHeal = true;
}
}
else
{
// We don't need to check if already applied as this function resets the HealthMax to the value the Perk says
// So no need to further reduce
}
}
}
//`Log("PerkSetOwnerHealthAndArmor: Max Health " $OwnerPawn.HealthMax);
return bNeedToFullyHeal;
}
/** (Server) Modify Instigator settings based on selected perk */
function ApplySkillsToPawn()
{
@ -1419,6 +1470,7 @@ function TickRegen( float DeltaTime )
local int OldHealth;
local KFPlayerReplicationInfo KFPRI;
local KFPlayerController KFPC;
local KFPlayerController_WeeklySurvival KFPCWS;
local KFPowerUp PowerUp;
local bool bCannotBeHealed;
local KFGameInfo GameInfo;
@ -1438,6 +1490,13 @@ function TickRegen( float DeltaTime )
GameInfo = KFGameInfo(WorldInfo.Game);
bCannotBeHealed = bCannotBeHealed || (GameInfo.OutbreakEvent != none && GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed);
// VIP cannot heal
KFPCWS = KFPlayerController_WeeklySurvival(OwnerPawn.Controller);
if (KFPCWS != none && KFPCWS.VIPGameData.IsVIP)
{
bCannotBeHealed = true;
}
// If the Pawn cannot be healed return...
if( bCannotBeHealed )
{

View File

@ -552,10 +552,12 @@ function NotifyZedTimeStarted()
local KFGameInfo GameInfo;
local bool bScaredAI;
local bool bCannotBeHealed;
local KFGameReplicationInfo KFGRI;
if( IsRageActive() && OwnerPawn != none )
{
KFPC = KFPlayerController(OwnerPawn.Controller);
if( KFPC != none )
{
PowerUp = KFPC.GetPowerUp();
@ -566,6 +568,15 @@ function NotifyZedTimeStarted()
{
bCannotBeHealed = bCannotBeHealed ||(GameInfo.OutbreakEvent != none && GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed);
}
// VIP cannot heal
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none
&& KFGRI.VIPRepPlayer != none
&& KFGRI.VIPRepPlayer == KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo))
{
bCannotBeHealed = true;
}
}
if( bCannotBeHealed == false )

View File

@ -504,7 +504,7 @@ final private function bool IsHealthIncreaseActive()
*
* @return true/false
*/
final private function bool IsEatLeadActive()
simulated final private function bool IsEatLeadActive()
{
return PerkSkills[ECommandoEatLead].bActive && IsPerkLevelAllowed(ECommandoEatLead);
}

View File

@ -380,7 +380,7 @@ static function PrepareExplosive( Pawn ProjOwner, KFProjectile Proj, optional fl
Proj.ExplosionTemplate.DamageRadius = Proj.default.ExplosionTemplate.DamageRadius * class'KFPerk_Demolitionist'.static.GetNukeRadiusModifier() * AuxRadiusMod;
Proj.ExplosionTemplate.DamageFalloffExponent = Proj.default.ExplosionTemplate.DamageFalloffExponent;
}
else if( InstigatorPRI.bConcussiveActive && Proj.AltExploEffects != none )
else if( InstigatorPRI.bConcussiveActive && Proj.AltExploEffects != none && class'KFPerk_Demolitionist'.static.ProjectileShouldConcussive(Proj) )
{
Proj.ExplosionTemplate.ExplosionEffects = Proj.AltExploEffects;
Proj.ExplosionTemplate.ExplosionSound = class'KFPerk_Demolitionist'.static.GetConcussiveExplosionSound();
@ -394,8 +394,13 @@ static function PrepareExplosive( Pawn ProjOwner, KFProjectile Proj, optional fl
KFPC = KFPlayerController( ProjOwner.Controller );
if( KFPC != none )
{
InstigatorPerk = KFPC.GetPerk();
Proj.ExplosionTemplate.DamageRadius *= InstigatorPerk.GetAoERadiusModifier() * AuxRadiusMod;
Proj.ExplosionTemplate.DamageRadius *= AuxRadiusMod;
if (class'KFPerk_Demolitionist'.static.ProjectileShouldExplosionChangeRadius(Proj))
{
InstigatorPerk = KFPC.GetPerk();
Proj.ExplosionTemplate.DamageRadius *= InstigatorPerk.GetAoERadiusModifier();
}
}
}
}
@ -686,6 +691,16 @@ simulated static function bool ProjectileShouldNuke( KFProjectile Proj )
return Proj.AllowNuke();
}
simulated static function bool ProjectileShouldConcussive( KFProjectile Proj )
{
return Proj.AllowDemolitionistConcussive();
}
simulated static function bool ProjectileShouldExplosionChangeRadius( KFProjectile Proj )
{
return Proj.AllowDemolitionistExplosionChangeRadius();
}
simulated function bool DoorShouldNuke()
{
return IsNukeActive() && WorldInfo.TimeDilation < 1.f;

View File

@ -213,11 +213,15 @@ simulated function ModifyMagSizeAndNumber( KFWeapon KFW, out int MagazineCapacit
TempCapacity = MagazineCapacity;
if( IsWeaponOnPerk( KFW, WeaponPerkClass, self.class ) && (KFW == none || !KFW.bNoMagazine) && !bSecondary )
// Fix this function on the trader because KFW is None and the check cannot look for bNoMagazine = true
if(WeaponClassname != 'KFWeap_Rifle_HRGIncision')
{
if( IsCombatantActive() )
if( IsWeaponOnPerk( KFW, WeaponPerkClass, self.class ) && (KFW == none || !KFW.bNoMagazine) && !bSecondary )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[EMedicCombatant] );
if( IsCombatantActive() )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[EMedicCombatant] );
}
}
}

View File

@ -273,13 +273,12 @@ simulated function ModifyMagSizeAndNumber( KFWeapon KFW, out int MagazineCapacit
TempCapacity = MagazineCapacity;
// Fix this function on the trader because KFW is None and the check cannot look for bNoMagazine = true
if(WeaponClassname == 'KFWeap_Pistol_HRGScorcher')
if(WeaponClassname != 'KFWeap_Pistol_HRGScorcher' && WeaponClassname != 'KFWeap_HRG_Dragonbreath')
{
TempCapacity = TempCapacity;
}
else if( IsWeaponOnPerk( KFW, WeaponPerkClass, self.class ) && IsHighCapFuelTankActive() && (KFW == none || !KFW.bNoMagazine) )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[EFirebugHighCapFuelTank] );
if( IsWeaponOnPerk( KFW, WeaponPerkClass, self.class ) && IsHighCapFuelTankActive() && (KFW == none || !KFW.bNoMagazine) )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[EFirebugHighCapFuelTank] );
}
}
MagazineCapacity = Round(TempCapacity);

View File

@ -1631,6 +1631,13 @@ function OnReadProfileSettingsComplete(byte LocalUserNum,bool bWasSuccessful)
KFInput.SetGamepadLayout(Profile.GetProfileInt(KFID_CurrentLayoutIndex));
KFInput.bToggleToRun = Profile.GetProfileBool(KFID_ToggleToRun);
KFInput.bAllowSwapTo9mm = Profile.GetProfileBool(KFID_AllowSwapTo9mm);
// Console?? PC??
KFInput.MouseLookUpScale = Profile.GetProfileFloat(KFID_MouseLookUpScale);
KFInput.MouseLookRightScale = Profile.GetProfileFloat(KFID_MouseLookRightScale);
KFInput.bViewSmoothingEnabled = Profile.GetProfileBool(KFID_ViewSmoothingEnabled);
KFInput.bViewAccelerationEnabled = Profile.GetProfileBool(KFID_ViewAccelerationEnabled);
KFInput.ReInitializeControlsUI();
}
@ -2758,6 +2765,30 @@ public function bool CanUseGunGame()
return false;
}
public function bool CanUseVIP()
{
/** If this is run in Server or Standalone, GameInfo exists so can access to the OutbreakEvent */
if (Role == Role_Authority)
{
return KFGameInfo(WorldInfo.Game).OutbreakEvent != none
&& KFGameInfo(WorldInfo.Game).OutbreakEvent.ActiveEvent.bVIPGameMode;
}
/** But in client, GameInfo doesn't exist, so needs to be checked in a different way. */
else
{
/**
In client there's a kfgame replication info that contains if the mode is a weekly, and the index.
This way would also work in server, but will need to be in code rather than using the weekly variables.
*/
/** Another option is to use instead a variable replicated just with that value */
return KFGameReplicationInfo(WorldInfo.GRI) != none
&& KFGameReplicationInfo(WorldInfo.GRI).bIsWeeklyMode
&& KFGameReplicationInfo(WorldInfo.GRI).CurrentWeeklyIndex == 17;
}
return false;
}
/*********************************************************************************************
* @name Skill Tracking
********************************************************************************************* */
@ -10516,6 +10547,10 @@ protected function MotivatePlayerToMove()
SetTimer( class'KFVersusNoGoVolume'.static.GetNoGoHurtInterval(), true, nameOf(MotivatePlayerToMove) );
}
function AdjustDamage(out int InDamage, Controller InstigatedBy, class<DamageType> DamageType, Actor DamageCauser, Actor DamageReceiver)
{
}
exec function GCF()
{
if ( MyGFxManager != None )

View File

@ -41,6 +41,10 @@ var protected const AkEvent AracnoStompSoundEvent;
var protected const AKEvent GunGameLevelUpSoundEvent;
var protected const AKEvent GunGameLevelUpFinalWeaponSoundEvent;
var protected const AKEvent VIPChosenSoundEvent;
var protected const AKEvent VIPLowHealthSoundEvent;
var protected float VIPLowHealthLastTimePlayed;
struct native GunGameInfo
{
var transient byte Level;
@ -59,6 +63,49 @@ structdefaultproperties
};
var transient GunGameInfo GunGameData;
struct native VIPGameInfo
{
var bool IsVIP;
var bool WasVIP;
var bool PendingHealthReset;
var int ExtraHealth;
var int DamageHealthLimit;
var int DamageHealthTop;
var int DamageHealthBottom;
var float DamageLimitModifier;
var float OutputDamageTopModifier;
var float InputDamageTopModifier;
var float OutputDamageBottomModifier;
var float InputDamageBottomModifier;
structdefaultproperties
{
IsVIP = false
WasVIP = false
PendingHealthReset = false
ExtraHealth = 100
DamageHealthLimit = 100
DamageHealthTop = 50
DamageHealthBottom = 25
DamageLimitModifier = 1.0
OutputDamageTopModifier = 1.5
InputDamageTopModifier = 0.75
OutputDamageBottomModifier = 1.75
InputDamageBottomModifier = 0.5
}
};
var transient VIPGameInfo VIPGameData;
cpptext
{
virtual UBOOL TestZedTimeVisibility(APawn* P, UNetConnection* Connection, UBOOL bLocalPlayerTest) override;
@ -148,6 +195,31 @@ reliable client function UpdateGunGameWidget(int score, int max_score, int level
}
}
simulated function UpdateVIPWidget(ReplicatedVIPGameInfo VIPInfo)
{
if (MyGFxHUD != none)
{
MyGFxHUD.UpdateVIP(VIPInfo, VIPInfo.VIPPlayer == PlayerReplicationInfo);
}
}
function bool CanUseHealObject()
{
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
// VIP cannot heal
if (KFGRI != none
&& KFGRI.VIPRepPlayer != none
&& KFGRI.VIPRepPlayer == KFPlayerReplicationInfo(PlayerReplicationInfo))
{
return false;
}
return super.CanUseHealObject();
}
/**
Arachnophobia Goompa Stomp Streak functions
*/
@ -247,6 +319,34 @@ reliable client function PlayGunGameMessage(bool isLastLevel)
}
}
reliable client function PlayVIPSound_ChosenInternal()
{
if (VIPChosenSoundEvent != none)
{
PlaySoundBase(VIPChosenSoundEvent);
}
}
reliable client function PlayVIPGameChosenSound(float delay)
{
// Put a timer because the sound happens at the same time as end wave and it's difficult to distinguish
SetTimer(delay, false, nameof(PlayVIPSound_ChosenInternal));
}
reliable client function PlayVIPGameLowHealthSound()
{
if (VIPLowHealthSoundEvent != none)
{
if (WorldInfo.TimeSeconds - VIPLowHealthLastTimePlayed > 8.f)
{
VIPLowHealthLastTimePlayed = WorldInfo.TimeSeconds;
PlaySoundBase(VIPLowHealthSoundEvent);
}
}
}
/** Resets all gameplay FX to initial state.
Append to this list if additional effects are added. */
function ResetGameplayPostProcessFX()
@ -333,6 +433,174 @@ function UpdateInitialHeldWeapon()
}
}
function AdjustDamage(out int InDamage, Controller InstigatedBy, class<DamageType> DamageType, Actor DamageCauser, Actor DamageReceiver)
{
local KFGameInfo KFGI;
local float Multiplier, ModifierRange, HealthTop, HealthRange;
local KFGameReplicationInfo KFGRI;
super.AdjustDamage(InDamage, InstigatedBy, DamageType, DamageCauser, DamageReceiver);
KFGI = KFGameInfo(WorldInfo.Game);
if (Pawn != None && KFGI != none && KFGI.OutbreakEvent != none && KFGI.OutbreakEvent.ActiveEvent.bVIPGameMode)
{
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
// If I am the VIP doing the damage, and I am NOT doing damage to myself
if (KFGRI != none
&& KFGRI.VIPRepPlayer != none
&& KFGRI.VIPRepPlayer == KFPlayerReplicationInfo(PlayerReplicationInfo)
&& InstigatedBy == self
&& DamageReceiver != self.Pawn)
{
Multiplier = 1.0;
//`Log("Current health for VIP OUTPUT DAMAGE: " $Pawn.Health);
if (Pawn.Health < VIPGameData.DamageHealthLimit)
{
if (Pawn.Health <= VIPGameData.DamageHealthBottom)
{
Multiplier = VIPGameData.OutputDamageBottomModifier;
}
else
{
if (Pawn.Health > VIPGameData.DamageHealthTop)
{
Multiplier = VIPGameData.DamageLimitModifier;
// From 1.0 to 1.5 on the range of 100 - 50
ModifierRange = VIPGameData.OutputDamageTopModifier - VIPGameData.DamageLimitModifier;
HealthTop = VIPGameData.DamageHealthLimit;
HealthRange = Abs(HealthTop - VIPGameData.DamageHealthTop);
}
else
{
// From 1.5 to 1.75 on the range of 50 - 25
Multiplier = VIPGameData.OutputDamageTopModifier;
ModifierRange = VIPGameData.OutputDamageBottomModifier - VIPGameData.OutputDamageTopModifier;
HealthTop = VIPGameData.DamageHealthTop;
HealthRange = Abs(HealthTop - VIPGameData.DamageHealthBottom);
}
Multiplier += ModifierRange * ((HealthTop - Pawn.Health) / HealthRange);
}
}
else
{
Multiplier = VIPGameData.DamageLimitModifier;
}
//`Log("Multiplier for VIP OUTPUT DAMAGE: Output: " $Multiplier);
InDamage = int(float(InDamage) * Multiplier);
}
}
}
function AdjustVIPDamage(out int InDamage, Controller InstigatedBy)
{
local KFGameInfo KFGI;
local float Multiplier, ModifierRange, HealthTop, HealthRange;
local KFGameReplicationInfo KFGRI;
KFGI = KFGameInfo(WorldInfo.Game);
if (Pawn != None && KFGI != none && KFGI.OutbreakEvent != none && KFGI.OutbreakEvent.ActiveEvent.bVIPGameMode)
{
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
// If I am the VIP
// We do it on a different step as don't want to scale InDamage to VIP Armour when receiving damage
if (KFGRI != none
&& KFGRI.VIPRepPlayer != none
&& KFGRI.VIPRepPlayer == KFPlayerReplicationInfo(PlayerReplicationInfo))
{
Multiplier = 1.0;
//`Log("Current health for VIP INPUT DAMAGE: " $Pawn.Health);
if (Pawn.Health < VIPGameData.DamageHealthLimit)
{
if (Pawn.Health <= VIPGameData.DamageHealthBottom)
{
Multiplier = VIPGameData.InputDamageBottomModifier;
}
else
{
if (Pawn.Health > VIPGameData.DamageHealthTop)
{
Multiplier = VIPGameData.DamageLimitModifier;
// From 1.0 to 0.5 on the range of 100 - 50
ModifierRange = VIPGameData.InputDamageTopModifier - VIPGameData.DamageLimitModifier;
HealthTop = VIPGameData.DamageHealthLimit;
HealthRange = Abs(HealthTop - VIPGameData.DamageHealthTop);
}
else
{
// From 0.5 to 0.25 on the range of 50 - 25
Multiplier = VIPGameData.InputDamageTopModifier;
ModifierRange = VIPGameData.InputDamageBottomModifier - VIPGameData.InputDamageTopModifier;
HealthTop = VIPGameData.DamageHealthTop;
HealthRange = Abs(HealthTop - VIPGameData.DamageHealthBottom);
}
Multiplier += ModifierRange * ((HealthTop - Pawn.Health) / HealthRange);
}
}
else
{
Multiplier = VIPGameData.DamageLimitModifier;
}
//`Log("Multiplier for VIP INPUT DAMAGE: Output: " $Multiplier);
InDamage = int(float(InDamage) * Multiplier);
}
}
}
function NotifyTakeHit(Controller InstigatedBy, vector HitLocation, int Damage, class<DamageType> damageType, vector Momentum)
{
local KFPlayerController_WeeklySurvival KFPC_WS;
Super.NotifyTakeHit(InstigatedBy,HitLocation,Damage,damageType,Momentum);
if (VIPGameData.IsVIP)
{
// Only sound once we pass down 50, sound again if recovered health and go down again
if (Pawn.Health < 50 && Pawn.Health + Damage >= 50)
{
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
{
KFPC_WS.PlayVIPGameLowHealthSound();
}
}
}
}
function UpdateVIPDamage()
{
local KFGameReplicationInfo KFGRI;
if (VIPGameData.IsVIP)
{
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
KFGRI.UpdateVIPCurrentHealth(Pawn.Health);
}
}
}
//
defaultProperties
{
@ -346,4 +614,7 @@ defaultProperties
AracnoStompSoundEvent =AkEvent'WW_GLO_Runtime.WeeklyArcno'
GunGameLevelUpSoundEvent=AkEvent'WW_GLO_Runtime.WeeklyAALevelUp'
GunGameLevelUpFinalWeaponSoundEvent=AkEvent'WW_GLO_Runtime.WeeklyAALevelFinal'
VIPChosenSoundEvent=AkEvent'WW_UI_Menu.Play_AAR_TOPWEAPON_SLIDEIN_B'
VIPLowHealthSoundEvent=AkEvent'WW_GLO_Runtime.WeeklyVIPAlarm'
VIPLowHealthLastTimePlayed = 0.f
}

View File

@ -241,6 +241,12 @@ var bool bVersusInput;
/** Cached value of bUsingGamepad so we can handle button releases across devices */
var bool bUsingVersusGamepadScheme;
/*********************************************************************************************
* @name QoL: Mouse input options
********************************************************************************************* */
var float MouseLookUpScale;
var float MouseLookRightScale;
cpptext
{
/** Searches the bind and skips the mainCommand */
@ -405,6 +411,7 @@ function EDoubleClickDir CheckForDoubleClickMove(float DeltaTime)
event PlayerInput( float DeltaTime )
{
local float FOVScale, TimeScale;
local float MouseYScale, MouseXScale;
local vector RawJoyVector;
// Save Raw values
@ -437,8 +444,12 @@ event PlayerInput( float DeltaTime )
aBaseY *= TimeScale * MoveForwardSpeed;
aStrafe *= TimeScale * MoveStrafeSpeed;
aUp *= TimeScale * MoveStrafeSpeed;
aTurn *= TimeScale * LookRightScale;
aLookUp *= TimeScale * LookUpScale;
if (class'WorldInfo'.static.IsConsoleBuild() || bUsingGamepad)
{
aTurn *= TimeScale * LookRightScale;
aLookUp *= TimeScale * LookUpScale;
}
PostProcessInput( DeltaTime );
@ -462,14 +473,16 @@ event PlayerInput( float DeltaTime )
aLookUp *= FOVScale;
aTurn *= FOVScale;
MouseXScale = (TimeScale * -MouseLookUpScale / 100.0f);
// Turning and strafing share the same axis.
if( bStrafe > 0 )
aStrafe += aBaseX + aMouseX;
aStrafe += aBaseX + aMouseX * ( MouseXScale > 0.0f ? MouseXScale : 1.0f);
else
aTurn += aBaseX + aMouseX;
aTurn += aBaseX + aMouseX * ( MouseXScale > 0.0f ? MouseXScale : 1.0f);
// Look up/down.
aLookup += aMouseY;
MouseYScale = (TimeScale * -MouseLookUpScale / 100.0f);
aLookup += aMouseY * ( MouseYScale > 0.0f ? MouseYScale : 1.0f);
if ( (!bUsingGamepad && bInvertMouse) || (bInvertController && bUsingGamepad) )
{
aLookup *= -1.f;

View File

@ -113,7 +113,7 @@ var private byte ActivePerkLevel;
var private byte ActivePerkPrestigeLevel;
/** Kill assists. Need an integer here because it is very easy to exceed 255 assists. */
var int Assists;
var byte PlayerHealth; //represented as a percentage
var int PlayerHealth;
var byte PlayerHealthPercent; //represented as a percentage
/** The firebug range skill increases the range of fire weapons we need to tell other clients if it is on */
var bool bExtraFireRange;

View File

@ -386,4 +386,17 @@ defaultproperties
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_SurvivalStartingWeapIdx,Data=(Type=SDT_Int32,Value1=0))))
ProfileMappings.Add((Id=KFID_SurvivalStartingGrenIdx, Name="Survival Starting Grenade Index", MappingType=PVMT_RawValue))
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_SurvivalStartingGrenIdx,Data=(Type=SDT_Int32,Value1=0))))
// Added 07/06/2022 - QoL: Add mouse options to menu
ProfileMappings.Add((Id=KFID_MouseLookUpScale, Name="Mouse_Look_Up_Scale", MappingType=PVMT_RawValue))
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_MouseLookUpScale,Data=(Type=SDT_Float,Value1=0xc2c80000)))) // -100
ProfileMappings.Add((Id=KFID_MouseLookRightScale, Name="Mouse_Look_Right_Scale", MappingType=PVMT_RawValue))
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_MouseLookRightScale,Data=(Type=SDT_Float,Value1=0x42c80000)))) //100
ProfileMappings.Add((Id=KFID_ViewSmoothingEnabled, Name="View_Smoothing_Enabled", MappingType=PVMT_RawValue))
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_ViewSmoothingEnabled,Data=(Type=SDT_Int32,Value1=0))))
ProfileMappings.Add((Id=KFID_ViewAccelerationEnabled, Name="View_Acceleration_Enabled", MappingType=PVMT_RawValue))
DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_ViewAccelerationEnabled,Data=(Type=SDT_Int32,Value1=1))))
}

View File

@ -254,6 +254,9 @@ simulated event GrenadeIsAtRest()
/** Overriding so that the grenade doesn't take on the */
simulated protected function PrepareExplosionTemplate()
{
local Weapon OwnerWeapon;
local KFPawn_Human OwnerPawn;
if (bUpgradable)
{
super.PrepareExplosionTemplate();
@ -261,6 +264,16 @@ simulated protected function PrepareExplosionTemplate()
else
{
GetRadialDamageValues(ExplosionTemplate.Damage, ExplosionTemplate.DamageRadius, ExplosionTemplate.DamageFalloffExponent);
OwnerWeapon = Weapon(Owner);
if (OwnerWeapon != none)
{
OwnerPawn = KFPawn_Human(OwnerWeapon.Owner);
if (OwnerPawn != none)
{
ExplosionTemplate.DamageRadius *= OwnerPawn.GetPerk().GetAoERadiusModifier();
}
}
}
}

View File

@ -1117,6 +1117,18 @@ simulated function bool AllowNuke()
return true;
}
/** Can be overridden in subclasses to exclude specific projectiles from using changing explosion radius */
simulated function bool AllowDemolitionistExplosionChangeRadius()
{
return true;
}
/** Can be overridden in subclasses to exclude specific projectiles from using concussive */
simulated function bool AllowDemolitionistConcussive()
{
return true;
}
/**
* Give the projectiles a chance to situationally customize/tweak any explosion parameters.
* We will also copy in any data we exposed here for .ini file access.

View File

@ -85,13 +85,20 @@ cpptext
virtual void PostLoad();
}
function PlayImpactParticleEffect(
KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, EEffectDamageGroup EffectGroup)
function PlayImpactParticleEffect(KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, EEffectDamageGroup EffectGroup, optional ParticleSystem ForceParticleTemplate)
{
local ParticleSystem ParticleTemplate;
local name HitBoneName;
ParticleTemplate = GetImpactParticleEffect(EffectGroup);
if (ForceParticleTemplate != none)
{
ParticleTemplate = ForceParticleTemplate;
}
else
{
ParticleTemplate = GetImpactParticleEffect(EffectGroup);
}
if (ParticleTemplate == None)
{
return;
@ -212,7 +219,7 @@ function ParticleSystem GetImpactParticleEffect(EEffectDamageGroup EffectGroup)
}
/** Play an impact sound on taking damage */
function PlayTakeHitSound(KFPawn P, vector HitLocation, Pawn DamageCauser, EEffectDamageGroup EffectGroup)
function PlayTakeHitSound(KFPawn P, vector HitLocation, Pawn DamageCauser, EEffectDamageGroup EffectGroup, optional AKEvent ForceImpactSound)
{
local AKEvent ImpactSound;
local float ArmorPct;
@ -225,7 +232,14 @@ function PlayTakeHitSound(KFPawn P, vector HitLocation, Pawn DamageCauser, EEffe
return;
}
ImpactSound = GetImpactSound(EffectGroup, DamageCauser, P);
if (ForceImpactSound != none)
{
ImpactSound = ForceImpactSound;
}
else
{
ImpactSound = GetImpactSound(EffectGroup, DamageCauser, P);
}
if (ShouldSetArmorValue(P, ArmorPct))
{

View File

@ -129,7 +129,7 @@ var() float MaxDistanceToPlayer;
var() bool bOutOfSight;
/** Result of last time this volume was rated & sorted */
var const transient float CurrentRating;
var transient float CurrentRating;
/** Cached visibility for performance */
var const transient bool bCachedVisibility;

View File

@ -34,7 +34,9 @@ enum ESharedContentUnlock
SCU_ParasiteImplanter,
SCU_Doshinegun,
SCU_AutoTurret,
SCU_ShrinkRayGun
SCU_ShrinkRayGun,
SCU_Scythe,
SCU_G36C
};
@ -373,4 +375,12 @@ defaultproperties
Name=KFWeap_ShrinkRayGun,
IconPath="WEP_UI_ShrinkRay_Gun_TEX.UI_Weapon_Select_Shrink_Ray_Gun",
ID=9290)}
SharedContentList(SCU_Scythe)={(
Name=KFWeap_Edged_Scythe,
IconPath="WEP_UI_Scythe_TEX.UI_WeaponSelect_Scythe",
ID=9478)}
SharedContentList(SCU_G36C)={(
Name=KFWeap_AssaultRifle_G36C,
IconPath="WEP_UI_G36C_TEX.UI_WeaponSelect_G36C",
ID=9484)}
}

View File

@ -0,0 +1,29 @@
//=============================================================================
// KFWeaponDefintion
//=============================================================================
// A lightweight container for basic weapon properties that can be safely
// accessed without a weapon actor (UI, remote clients).
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeapDef_G36C extends KFWeaponDefinition
abstract;
DefaultProperties
{
WeaponClassPath="KFGameContent.KFWeap_AssaultRifle_G36C"
BuyPrice=1600
AmmoPricePerMag=36
ImagePath="wep_ui_g36c_tex.UI_WeaponSelect_G36C"
EffectiveRange=70
UpgradePrice[0]=1500
UpgradeSellPrice[0]=1125
SharedUnlockId=SCU_G36C
}

View File

@ -0,0 +1,24 @@
//=============================================================================
// KFWeapDef_Dragonbreath
// This is the Doomstick
//=============================================================================
// Killing Floor 2
// Copyright (C) 2017 Tripwire Interactive LLC
//=============================================================================
class KFWeapDef_HRG_Dragonbreath extends KFWeaponDefinition
abstract;
DefaultProperties
{
WeaponClassPath="KFGameContent.KFWeap_HRG_Dragonbreath"
BuyPrice=1400
AmmoPricePerMag=25
ImagePath="WEP_UI_Quad_Barrel_TEX.UI_WeaponSelect_QuadBarrel"
EffectiveRange=25
UpgradePrice[0]=1500
UpgradeSellPrice[0]=1125
}

View File

@ -0,0 +1,28 @@
//=============================================================================
// KFWeapDef_HRG_Locust
//=============================================================================
// A lightweight container for basic weapon properties that can be safely
// accessed without a weapon actor (UI, remote clients).
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeapDef_HRG_Locust extends KFWeaponDefinition
abstract;
DefaultProperties
{
WeaponClassPath="KFGameContent.KFWeap_HRG_Locust"
BuyPrice=900
AmmoPricePerMag=40
ImagePath="wep_ui_hrg_locust_tex.UI_WeaponSelect_HRG_Locust"
EffectiveRange=100
UpgradePrice[0]=700
UpgradePrice[1]=1500
UpgradeSellPrice[0]=525
UpgradeSellPrice[1]=1650
}

View File

@ -0,0 +1,26 @@
//=============================================================================
// KFWeapDef_Scythe
//=============================================================================
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeapDef_Scythe extends KFWeaponDefinition
abstract;
DefaultProperties
{
WeaponClassPath="KFGameContent.KFWeap_Edged_Scythe"
BuyPrice=1500
ImagePath="WEP_UI_Scythe_TEX.UI_WeaponSelect_Scythe"
EffectiveRange=5
UpgradePrice[0]=1500
UpgradeSellPrice[0]=1125
SharedUnlockId=SCU_Scythe
}

View File

@ -228,11 +228,21 @@ simulated function bool CanReload(optional byte FireModeNum);
/** Instead of switch fire mode use as immediate alt fire */
simulated function AltFireMode()
{
local KFPlayerController_WeeklySurvival Instigator_KFPC_WS;
if ( !Instigator.IsLocallyControlled() )
{
return;
}
Instigator_KFPC_WS = KFPlayerController_WeeklySurvival(Instigator.Controller);
if (Instigator_KFPC_WS != none && Instigator_KFPC_WS.VIPGameData.IsVIP)
{
// VIP can't heal himself
return;
}
// StartFire - StopFire called from KFPlayerInput
StartFire(ALTFIRE_FIREMODE);
}

View File

@ -1618,7 +1618,7 @@ simulated function AttachLaserSight()
}
}
function GunGameRemove()
function RemoveGun()
{
if (Instigator != none && Instigator.InvManager != none)
{

View File

@ -3675,6 +3675,42 @@ defaultproperties
//Reducto Ray Lucky Strike
Skins.Add((Id=9295, Weapondef=class'KFWeapDef_ShrinkRayGun', MIC_1P=("wep_skinset55_mat.Wep_1P_LuckyStrike_ShrinkRay_Gun_MIC","WEP_1P_ShrinkRay_Gun_MAT.WEP_ShrinkRay_Glass_MIC"), MIC_3P="wep_skinset55_mat.Wep_3P_LuckyStrike_ShrinkRay_Gun_MIC", MIC_Pickup="wep_skinset55_mat.Wep_3P_LuckyStrike_ShrinkRay_Pickup_MIC"))
//Blood Sickle Standard
Skins.Add((Id=9478, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("wep_1p_scythe_mat.Wep_1stP_Scythe_MIC"), MIC_3P="WEP_3P_Scythe_MAT.WEP_3P_Scythe_MIC", MIC_Pickup="wep_3p_scythe_mat.WEP_3P_ScythePickup_MIC"))
//Blood Sickle Bloodbath
Skins.Add((Id=9473, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("WEP_SkinSet65_MAT.Wep_1P_Bloodbath_Scythe_MIC"), MIC_3P="WEP_SkinSet65_MAT.Wep_3P_Bloodbath_Scythe_MIC", MIC_Pickup="WEP_SkinSet65_MAT.Wep_3P_Bloodbath_Scythe_Pickup_MIC"))
//Blood Sickle Butchery
Skins.Add((Id=9474, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("WEP_SkinSet65_MAT.Wep_1P_Butchery_Scythe_MIC"), MIC_3P="WEP_SkinSet65_MAT.Wep_3P_Butchery_Scythe_MIC", MIC_Pickup="WEP_SkinSet65_MAT.Wep_3P_Butchery_Scythe_Pickup_MIC"))
//Blood Sickle Carousel
Skins.Add((Id=9475, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("WEP_SkinSet65_MAT.Wep_1P_Carousel_Scythe_MIC"), MIC_3P="WEP_SkinSet65_MAT.Wep_3P_Carousel_Scythe_MIC", MIC_Pickup="WEP_SkinSet65_MAT.Wep_3P_Caurel_Scythe_Pickup_MIC"))
//Blood Sickle Hunter
Skins.Add((Id=9477, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("WEP_SkinSet65_MAT.Wep_1P_Hunter_Scythe_MIC"), MIC_3P="WEP_SkinSet65_MAT.Wep_3P_Hunter_Scythe_MIC", MIC_Pickup="WEP_SkinSet65_MAT.Wep_3P_Hunter_Scythe_Pickup_MIC"))
//Blood Sickle Reaper
Skins.Add((Id=9476, Weapondef=class'KFWeapDef_Scythe', MIC_1P=("WEP_SkinSet65_MAT.Wep_1P_Reaper_Scythe_MIC"), MIC_3P="WEP_SkinSet65_MAT.Wep_3P_Reaper_Scythe_MIC", MIC_Pickup="WEP_SkinSet65_MAT.Wep_3P_Reaper_Scythe_Pickup_MIC"))
//G36C Standard
Skins.Add((Id=9484, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_1p_g36c_mat.Wep_1stP_G36C_MIC","wep_1p_g36c_mat.Wep_1stP_G36C_Scope_MIC"), MIC_3P="wep_3p_g36c_mat.Wep_3rdP_G36C_MIC", MIC_Pickup="wep_3p_g36c_mat.3P_Pickup_G36C_MIC"))
//G36C Aftermath
Skins.Add((Id=9481, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_skinset64_mat.Wep_1P_Aftermatch_G36C_MIC","wep_skinset64_mat.Wep_1P_Aftermatch_Scope_G36C_MIC"), MIC_3P="wep_skinset64_mat.Wep_3P_Aftermatch_G36C_MIC", MIC_Pickup="wep_skinset64_mat.Wep_3P_Aftermatch_G36C_Pickup_MIC"))
//G36C Dazzle
Skins.Add((Id=9483, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_skinset64_mat.Wep_1P_Dazzle_G36C_MIC","wep_skinset64_mat.Wep_1P_Dazzle_Scope_G36C_MIC"), MIC_3P="wep_skinset64_mat.Wep_3P_Dazzle_G36C_MIC", MIC_Pickup="wep_skinset64_mat.Wep_3P_Dazzle_G36C_Pickup_MIC"))
//G36C Icepack
Skins.Add((Id=9480, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_skinset64_mat.Wep_1P_Icepack_G36C_MIC","wep_skinset64_mat.Wep_1P_Icepack_Scope_G36C_MIC"), MIC_3P="wep_skinset64_mat.Wep_3P_Icepack_G36C_MIC", MIC_Pickup="wep_skinset64_mat.Wep_3P_Icepack_G36C_Pickup_MIC"))
//G36C Jungle
Skins.Add((Id=9482, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_skinset64_mat.Wep_1P_Jungle_G36C_MIC","wep_skinset64_mat.Wep_1P_Jungle_Scope_G36C_MIC"), MIC_3P="wep_skinset64_mat.Wep_3P_Jungle_G36C_MIC", MIC_Pickup="wep_skinset64_mat.Wep_3P_Jungle_G36C_Pickup_MIC"))
//G36C Sahara
Skins.Add((Id=9479, Weapondef=class'KFWeapDef_G36C', MIC_1P=("wep_skinset64_mat.Wep_1P_Sahara_G36C_MIC","wep_skinset64_mat.Wep_1P_Sahara_Scope_G36C_MIC"), MIC_3P="wep_skinset64_mat.Wep_3P_Sahara_G36C_MIC", MIC_Pickup="wep_skinset64_mat.Wep_3P_Sahara_G36C_Pickup_MIC"))
//BeyondHorizon AA12
Skins.Add((Id=8845, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_AA12', MIC_1P=("WEP_SkinSet43_MAT.space_aa12.Space_AA12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet43_MAT.space_aa12.Space_AA12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet43_MAT.space_aa12.Space_AA12_3P_Pickup_MIC"))
@ -3992,6 +4028,7 @@ defaultproperties
//Chameleon Dynamic RGB RPG-7
Skins.Add((Id=9358, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("wep_skinset58_mat.chameleonrgb_rpg7.ChameleonRGB_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet58_MAT.chameleonrgb_rpg7.ChameleonRGB_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet58_MAT.chameleonrgb_rpg7.ChameleonRGB_RPG7_3P_Pickup_MIC"))
//Deep Sea Antique AA12
Skins.Add((Id=9298, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_AA12', MIC_1P=("WEP_SkinSet59_MAT.deepsea_aa12.DeepSea_AA12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet59_MAT.deepsea_aa12.DeepSea_AA12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet59_MAT.deepsea_aa12.DeepSea_AA12_3P_Pickup_MIC"))
@ -4099,4 +4136,184 @@ defaultproperties
//Deep Sea Precious RPG-7
Skins.Add((Id=9333, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet59_MAT.deepsea_rpg7.DeepSeaPrecious_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet59_MAT.deepsea_rpg7.DeepSeaPrecious_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet59_MAT.deepsea_rpg7.DeepSeaPrecious_RPG7_3P_Pickup_MIC"))
//Plague Doctor Mint Tommy Gun
Skins.Add((Id=9388, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.Plague_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.Plague_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.Plague_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Sterling Tommy Gun
Skins.Add((Id=9389, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.PlagueSterling_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.PlagueSterling_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.PlagueSterling_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Obsidian Tommy Gun
Skins.Add((Id=9390, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.PlagueObsidian_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.PlagueObsidian_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.PlagueObsidian_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Volcanic Tommy Gun
Skins.Add((Id=9391, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.PlagueVolcanic_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.PlagueVolcanic_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.PlagueVolcanic_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Emerald Tommy Gun
Skins.Add((Id=9392, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.PlagueEmerald_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.PlagueEmerald_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.PlagueEmerald_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Precious Tommy Gun
Skins.Add((Id=9393, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Thompson', MIC_1P=("WEP_SkinSet62_MAT.plague_tommygun.PlaguePrecious_TommyGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_tommygun.PlaguePrecious_TommyGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_tommygun.PlaguePrecious_TommyGun_3P_Pickup_MIC"))
//Plague Doctor Mint M79
Skins.Add((Id=9394, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.Plague_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.Plague_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.Plague_M79_3P_Pickup_MIC"))
//Plague Doctor Sterling M79
Skins.Add((Id=9395, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.PlagueSterling_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.PlagueSterling_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.PlagueSterling_M79_3P_Pickup_MIC"))
//Plague Doctor Obsidian M79
Skins.Add((Id=9396, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.PlagueObsidian_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.PlagueObsidian_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.PlagueObsidian_M79_3P_Pickup_MIC"))
//Plague Doctor Volcanic M79
Skins.Add((Id=9397, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.PlagueVolcanic_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.PlagueVolcanic_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.PlagueVolcanic_M79_3P_Pickup_MIC"))
//Plague Doctor Emerald M79
Skins.Add((Id=9398, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.PlagueEmerald_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.PlagueEmerald_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.PlagueEmerald_M79_3P_Pickup_MIC"))
//Plague Doctor Precious M79
Skins.Add((Id=9399, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("WEP_SkinSet62_MAT.plague_m79.PlaguePrecious_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_m79.PlaguePrecious_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_m79.PlaguePrecious_M79_3P_Pickup_MIC"))
//Plague Doctor Mint Desert Eagle
Skins.Add((Id=9400, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.Plague_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.Plague_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.Plague_Deagle_3P_Pickup_MIC"))
//Plague Doctor Sterling Desert Eagle
Skins.Add((Id=9401, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.PlagueSterling_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.PlagueSterling_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.PlagueSterling_Deagle_3P_Pickup_MIC"))
//Plague Doctor Obsidian Desert Eagle
Skins.Add((Id=9402, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.PlagueObsidian_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.PlagueObsidian_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.PlagueObsidian_Deagle_3P_Pickup_MIC"))
//Plague Doctor Volcanic Desert Eagle
Skins.Add((Id=9403, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.PlagueVolcanic_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.PlagueVolcanic_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.PlagueVolcanic_Deagle_3P_Pickup_MIC"))
//Plague Doctor Emerald Desert Eagle
Skins.Add((Id=9404, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.PlagueEmerald_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.PlagueEmerald_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.PlagueEmerald_Deagle_3P_Pickup_MIC"))
//Plague Doctor Precious Desert Eagle
Skins.Add((Id=9405, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet62_MAT.plague_deagle.PlaguePrecious_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_deagle.PlaguePrecious_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_deagle.PlaguePrecious_Deagle_3P_Pickup_MIC"))
//Plague Doctor Mint Crossbow
Skins.Add((Id=9406, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.Plague_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.Plague_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.Plague_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.Plague_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Sterling Crossbow
Skins.Add((Id=9407, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.PlagueSterling_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.PlagueSterling_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.PlagueSterling_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.PlagueSterling_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Obsidian Crossbow
Skins.Add((Id=9408, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.PlagueObsidian_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.PlagueObsidian_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.PlagueObsidian_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.PlagueObsidian_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Volcanic Crossbow
Skins.Add((Id=9409, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.PlagueVolcanic_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.PlagueVolcanic_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.PlagueVolcanic_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.PlagueVolcanic_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Emerald Crossbow
Skins.Add((Id=9410, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.PlagueEmerald_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.PlagueEmerald_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.PlagueEmerald_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.PlagueEmerald_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Precious Crossbow
Skins.Add((Id=9411, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Crossbow', MIC_1P=("WEP_SkinSet62_MAT.plague_crossbow.PlaguePrecious_Crossbow_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_crossbow.PlaguePrecious_Crossbow_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_crossbow.PlaguePrecious_Crossbow_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_crossbow.PlaguePrecious_Crossbow_3P_Pickup_MIC"))
//Plague Doctor Mint Doomstick
Skins.Add((Id=9412, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.Plague_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.Plague_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.Plague_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.Plague_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Sterling Doomstick
Skins.Add((Id=9413, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.PlagueSterling_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.PlagueSterling_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueSterling_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueSterling_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Obsidian Doomstick
Skins.Add((Id=9414, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.PlagueObsidian_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.PlagueObsidian_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueObsidian_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueObsidian_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Volcanic Doomstick
Skins.Add((Id=9415, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.PlagueVolcanic_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.PlagueVolcanic_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueVolcanic_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueVolcanic_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Emerald Doomstick
Skins.Add((Id=9416, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.PlagueEmerald_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.PlagueEmerald_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueEmerald_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.PlagueEmerald_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Precious Doomstick
Skins.Add((Id=9417, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_ElephantGun', MIC_1P=("WEP_SkinSet62_MAT.plague_quadbarrel.PlaguePrecious_QuadBarrel_Main_1P_Mint_MIC", "WEP_SkinSet62_MAT.plague_quadbarrel.PlaguePrecious_QuadBarrel_Barrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_quadbarrel.PlaguePrecious_QuadBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_quadbarrel.PlaguePrecious_QuadBarrel_3P_Pickup_MIC"))
//Plague Doctor Mint Dragonsbreath
Skins.Add((Id=9418, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.Plague_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.Plague_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.Plague_Dragonsbreath_3P_Pickup_MIC"))
//Plague Doctor Sterling Dragonsbreath
Skins.Add((Id=9419, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueSterling_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueSterling_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueSterling_Dragonsbreath_3P_Pickup_MIC"))
//Plague Doctor Obsidian Dragonsbreath
Skins.Add((Id=9420, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueObsidian_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueObsidian_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueObsidian_Dragonsbreath_3P_Pickup_MIC"))
//Plague Doctor Volcanic Dragonsbreath
Skins.Add((Id=9421, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueVolcanic_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueVolcanic_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueVolcanic_Dragonsbreath_3P_Pickup_MIC"))
//Plague Doctor Emerald Dragonsbreath
Skins.Add((Id=9422, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueEmerald_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueEmerald_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.PlagueEmerald_Dragonsbreath_3P_Pickup_MIC"))
//Plague Doctor Precious Dragonsbreath
Skins.Add((Id=9423, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet62_MAT.plague_dragonsbreath.PlaguePrecious_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet62_MAT.plague_dragonsbreath.PlaguePrecious_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet62_MAT.plague_dragonsbreath.PlaguePrecious_Dragonsbreath_3P_Pickup_MIC"))
//Chameleon Dynamic AA12
Skins.Add((Id=9441, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_AA12', MIC_1P=("WEP_SkinSet60_MAT.chameleon_aa12.Chameleon_AA12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleon_aa12.Chameleon_AA12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleon_aa12.Chameleon_AA12_3P_Pickup_MIC"))
//Chameleon Dynamic Flamethrower
Skins.Add((Id=9442, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet60_MAT.chameleon_flamethrower.Chameleon_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleon_flamethrower.Chameleon_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleon_flamethrower.Chameleon_Flamethrower_3P_Pickup_MIC"))
//Chameleon Dynamic M99
Skins.Add((Id=9443, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M99', MIC_1P=("WEP_SkinSet60_MAT.chameleon_m99.Chameleon_M99_1P_Mint_MIC", "WEP_SkinSet60_MAT.chameleon_m99.Chameleon_M99_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleon_m99.Chameleon_M99_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleon_m99.Chameleon_M99_3P_Pickup_MIC"))
//Chameleon Dynamic SCAR
Skins.Add((Id=9444, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_SCAR', MIC_1P=("WEP_SkinSet60_MAT.chameleon_scar.Chameleon_SCAR_1P_Mint_MIC", "WEP_SkinSet60_MAT.chameleon_scar.Chameleon_SCAR_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleon_scar.Chameleon_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleon_scar.Chameleon_SCAR_3P_Pickup_MIC"))
//Chameleon Dynamic RGB AA12
Skins.Add((Id=9445, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_AA12', MIC_1P=("WEP_SkinSet60_MAT.chameleonrgb_aa12.ChameleonRGB_AA12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleonrgb_aa12.ChameleonRGB_AA12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleonrgb_aa12.ChameleonRGB_AA12_3P_Pickup_MIC"))
//Chameleon Dynamic RGB Flamethrower
Skins.Add((Id=9446, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet60_MAT.chameleonrgb_flamethrower.ChameleonRGB_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleonrgb_flamethrower.ChameleonRGB_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleonrgb_flamethrower.ChameleonRGB_Flamethrower_3P_Pickup_MIC"))
//Chameleon Dynamic RGB M99
Skins.Add((Id=9447, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M99', MIC_1P=("WEP_SkinSet60_MAT.chameleonrgb_m99.ChameleonRGB_M99_1P_Mint_MIC", "WEP_SkinSet60_MAT.chameleonrgb_m99.ChameleonRGB_M99_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleonrgb_m99.ChameleonRGB_M99_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleonrgb_m99.ChameleonRGB_M99_3P_Pickup_MIC"))
//Chameleon Dynamic RGB SCAR
Skins.Add((Id=9448, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_SCAR', MIC_1P=("WEP_SkinSet60_MAT.chameleonrgb_scar.ChameleonRGB_SCAR_1P_Mint_MIC", "WEP_SkinSet60_MAT.chameleonrgb_scar.ChameleonRGB_SCAR_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet60_MAT.chameleonrgb_scar.ChameleonRGB_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet60_MAT.chameleonrgb_scar.ChameleonRGB_SCAR_3P_Pickup_MIC"))
//Classic Mint AK12
Skins.Add((Id=9433, Weapondef=class'KFWeapDef_Ak12', MIC_1P=("WEP_SkinSet61_MAT.classic_ak12.Classic_AK12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.classic_ak12.Classic_AK12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.classic_ak12.Classic_AK12_3P_Pickup_MIC"))
//Classic Mint Desert Eagle
Skins.Add((Id=9434, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet61_MAT.classic_deagle.Classic_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.classic_deagle.Classic_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.classic_deagle.Classic_Deagle_3P_Pickup_MIC"))
//Classic Mint M14EBR
Skins.Add((Id=9435, Weapondef=class'KFWeapDef_M14EBR', MIC_1P=("WEP_SkinSet61_MAT.classic_m14ebr.Classic_M14EBR_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.classic_m14ebr.Classic_M14EBR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.classic_m14ebr.Classic_M14EBR_3P_Pickup_MIC"))
//Classic Mint Kriss
Skins.Add((Id=9436, Weapondef=class'KFWeapDef_Kriss', MIC_1P=("WEP_SkinSet61_MAT.classic_kriss.Classic_Kriss_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.classic_kriss.Classic_Kriss_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.classic_kriss.Classic_Kriss_3P_Pickup_MIC"))
//Classic Precious AK12
Skins.Add((Id=9437, Weapondef=class'KFWeapDef_Ak12', MIC_1P=("WEP_SkinSet61_MAT.standard_ak12.Standard_AK12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.standard_ak12.Standard_AK12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.standard_ak12.Standard_AK12_3P_Pickup_MIC"))
//Classic Precious Desert Eagle
Skins.Add((Id=9438, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet61_MAT.standard_deagle.Standard_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.standard_deagle.Standard_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.standard_deagle.Standard_Deagle_3P_Pickup_MIC"))
//Classic Precious M14EBR
Skins.Add((Id=9439, Weapondef=class'KFWeapDef_M14EBR', MIC_1P=("WEP_SkinSet61_MAT.standard_m14ebr.Standard_M14EBR_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.standard_m14ebr.Standard_M14EBR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.standard_m14ebr.Standard_M14EBR_3P_Pickup_MIC"))
//Classic Precious Kriss
Skins.Add((Id=9440, Weapondef=class'KFWeapDef_Kriss', MIC_1P=("WEP_SkinSet61_MAT.standard_kriss.Standard_Kriss_1P_Mint_MIC"), MIC_3P="WEP_SkinSet61_MAT.standard_kriss.Standard_Kriss_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet61_MAT.standard_kriss.Standard_Kriss_3P_Pickup_MIC"))
//Xeno Dynamic M4
Skins.Add((Id=9425, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M4', MIC_1P=("wep_skinset63_mat.xeno_m4.Xeno_M4_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xeno_m4.Xeno_M4_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xeno_m4.Xeno_M4_3P_Pickup_MIC"))
//Xeno Dynamic Heckler & Koch UMP
Skins.Add((Id=9426, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HK_UMP', MIC_1P=("WEP_SkinSet63_MAT.xeno_hk_ump.Xeno_HK_UMP_1P_Mint_MIC", "WEP_SkinSet63_MAT.xeno_hk_ump.Xeno_HK_UMP_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xeno_hk_ump.Xeno_HK_UMP_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xeno_hk_ump.Xeno_HK_UMP_3P_Pickup_MIC"))
//Xeno Dynamic Centerfire
Skins.Add((Id=9427, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CenterfireMB464', MIC_1P=("WEP_SkinSet63_MAT.xeno_centerfire.Xeno_Centerfire_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xeno_centerfire.Xeno_Centerfire_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xeno_centerfire.Xeno_Centerfire_3P_Pickup_MIC"))
//Xeno Dynamic Hemoclobber
Skins.Add((Id=9428, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicBat', MIC_1P=("WEP_SkinSet63_MAT.xeno_medicbat.Xeno_MedicBat_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xeno_medicbat.Xeno_MedicBat_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xeno_medicbat.Xeno_MedicBat_3P_Pickup_MIC"))
//Xeno Dynamic RGB M4
Skins.Add((Id=9429, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M4', MIC_1P=("WEP_SkinSet63_MAT.xenorgb_m4.XenoRGB_M4_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xenorgb_m4.XenoRGB_M4_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xenorgb_m4.XenoRGB_M4_3P_Pickup_MIC"))
//Xeno Dynamic RGB Heckler & Koch UMP
Skins.Add((Id=9430, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HK_UMP', MIC_1P=("WEP_SkinSet63_MAT.xenorgb_hk_ump.XenoRGB_HK_UMP_1P_Mint_MIC", "WEP_SkinSet63_MAT.xenorgb_hk_ump.XenoRGB_HK_UMP_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xenorgb_hk_ump.XenoRGB_HK_UMP_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xenorgb_hk_ump.XenoRGB_HK_UMP_3P_Pickup_MIC"))
//Xeno Dynamic RGB Centerfire
Skins.Add((Id=9431, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CenterfireMB464', MIC_1P=("WEP_SkinSet63_MAT.xenorgb_centerfire.XenoRGB_Centerfire_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xenorgb_centerfire.XenoRGB_Centerfire_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xenorgb_centerfire.XenoRGB_Centerfire_3P_Pickup_MIC"))
//Xeno Dynamic RGB Hemoclobber
Skins.Add((Id=9432, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicBat', MIC_1P=("WEP_SkinSet63_MAT.xenorgb_medicbat.XenoRGB_MedicBat_1P_Mint_MIC"), MIC_3P="WEP_SkinSet63_MAT.xenorgb_medicbat.XenoRGB_MedicBat_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet63_MAT.xenorgb_medicbat.XenoRGB_MedicBat_3P_Pickup_MIC"))
}

View File

@ -27,7 +27,7 @@ var localized array<string> ModifierDescriptions;
cpptext
{
/** Num of Weekly events available */
static const int NumWeeklyEvents = 17;
static const int NumWeeklyEvents = 18;
}
DefaultProperties
{

View File

@ -242,6 +242,9 @@ function AdjustBoneDamage(out int InDamage, name BoneName, Vector DamagerSource,
{
local int ArmorZoneIdx, ModDmgMax, ModDmgRem, ObliterateDamage;
local float Modifier;
local class<KFDamageType> mykfDamageType;
mykfDamageType = class<KFDamageType>(DamageType);
// modify damage done and apply to armor
Modifier = GetArmorDamageTypeModifier(DamageType);
@ -259,7 +262,22 @@ function AdjustBoneDamage(out int InDamage, name BoneName, Vector DamagerSource,
}
else
{
// If we have armour penetration damage, we calculate the Damage % that is base (and applied to armor)
// And we calculate the AP one, that's applied as minimum always
if (mykfDamageType != none && mykfDamageType.default.DamageModifierAP > 0.f)
{
ModDmgRem = (1.0 - mykfDamageType.default.DamageModifierAP) * ModDmgRem;
}
TakeArmorZoneDamage(ArmorZoneIdx, ModDmgRem, ModDmgRem);
// Apply to Zed: % AP (unmodified InDamage) + what's left of base after armor applied (unmodified ModDmgRem)
if (mykfDamageType != none && mykfDamageType.default.DamageModifierAP > 0.f)
{
InDamage = InDamage * mykfDamageType.default.DamageModifierAP;
InDamage += float(ModDmgRem) / Modifier;
return;
}
}
}

View File

@ -157,4 +157,5 @@ const STATID_ACHIEVE_MoonbaseCollectibles = 4059;
const STATID_ACHIEVE_NetherholdCollectibles = 4060;
const STATID_ACHIEVE_CarillonHamletCollectibles = 4061;
const STATID_ACHIEVE_RigCollectibles = 4062;
const STATID_ACHIEVE_BarmwichCollectibles = 4063;
/** `endif */

View File

@ -76,3 +76,7 @@ const KFID_HasTabbedToStore = 177;
const KFID_AllowSwapTo9mm = 178; // Halloween 2021 QoL: added option to quick switch weapons to 9mm
const KFID_SurvivalStartingWeapIdx=179; // Summer 2022 QoL: added option to choose starting weapon for survival perk
const KFID_SurvivalStartingGrenIdx=180; // Summer 2022 QoL: added option to choose starting grenade for survival perk
const KFID_MouseLookUpScale=181; // Halloweeen 2022 QoL: added mouse options to menu
const KFID_MouseLookRightScale=182; // Halloweeen 2022 QoL: added mouse options to menu
const KFID_ViewSmoothingEnabled=183; // Halloweeen 2022 QoL: added mouse options to menu
const KFID_ViewAccelerationEnabled=184; // Halloweeen 2022 QoL: added mouse options to menu

View File

@ -0,0 +1,77 @@
//=============================================================================
// KFBarmwichBonfireVolume
//=============================================================================
// Barmwich volume used for bonfires. Triggers seasonal progression.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFBarmwichBonfireVolume extends KFPhysicsDamageByPawnVolume
placeable;
/** Objective index for the event this is tied to */
var() int ObjectiveIndex;
/** Index of the event this is tied to */
var() int EventIndex;
var array<Actor> AffectedActors;
var transient bool bIsDataValid;
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
bIsDataValid = IsObjectiveDataValid();
}
function CausePainTo(Actor Other)
{
Super.CausePainTo(Other);
if (bIsDataValid && KFPawn_Monster(Other) != none && KFPawn_Monster(Other).IsAliveAndWell())
{
if (AffectedActors.Find(Other) == INDEX_NONE)
{
AffectedActors.AddItem(Other);
NotifyProgression();
}
}
}
function NotifyProgression()
{
local KFPlayerController KFPC;
if (!bIsDataValid)
{
return;
}
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
{
KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex);
}
}
function ClearAllActors()
{
AffectedActors.Remove(0, AffectedActors.Length);
}
function ClearActor(Actor Other)
{
AffectedActors.RemoveItem(Other);
}
simulated function bool IsObjectiveDataValid()
{
return ObjectiveIndex >= 0 && ObjectiveIndex < 5 && EventIndex > SEI_None && EventIndex < SEI_MAX;
}
DefaultProperties
{
bIsDataValid = false;
}

View File

@ -43,7 +43,7 @@ defaultproperties
//KDeathUpKick=120
//KDeathVel=10
StumblePower=12
StumblePower=48 //12
GunHitPower=12
OverrideImpactEffect=ParticleSystem'WEP_HRG_BlastBrawlers_EMIT.FX_BlastBrawlers_Impact'

View File

@ -0,0 +1,87 @@
//=============================================================================
// KFDT_Ballistic_G36C
//=============================================================================
// Class Description
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//
//=============================================================================
class KFDT_Ballistic_G36C extends KFDT_Ballistic_AssaultRifle
abstract
hidedropdown;
/** G36C has still to play a metal effect if impacting metal. (and we demoted to impact on Flesh) */
var ParticleSystem MetalImpactEffect;
var AkEvent MetalImpactSound;
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
{
local KFSkinTypeEffects SkinType, OriginalSkinType, FleshSkinType;
local int i;
if ( P.CharacterArch != None && default.EffectGroup < FXG_Max )
{
// Search if affected target has Flesh skin type
for (i = 0; i < P.CharacterArch.ImpactSkins.Length ; ++i)
{
if (P.CharacterArch.ImpactSkins[i].Name == 'Flesh'
|| P.CharacterArch.ImpactSkins[i].Name == 'Tough_Flesh')
{
FleshSkinType = P.CharacterArch.ImpactSkins[i];
break;
}
}
SkinType = P.GetHitZoneSkinTypeEffects( HitZoneIndex );
OriginalSkinType = SkinType;
// If we don't hit flesh or shield, try to demote to Flesh
if (SkinType != none && SkinType.Name != 'Flesh' && SkinType.Name != 'Tough_Flesh' && SkinType.Name != 'ShieldEffects')
{
// We default to none as we don't want bullet to ricochet if any
SkinType = none;
// Demote to flesh skin hit
if (FleshSkinType != none)
{
SkinType = FleshSkinType;
}
}
// If we hit metal we have to make sure we play it's Metal impact effect (this effect doesn't contain bullet ricochet) (don't play sound though!)
if (OriginalSkinType != none && (OriginalSkinType.Name == 'Metal' || OriginalSkinType.Name == 'Machine'))
{
OriginalSkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup, default.MetalImpactEffect);
OriginalSkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup, default.MetalImpactSound);
}
if (SkinType != none)
{
SkinType.PlayImpactParticleEffect(P, HitLocation, HitDirection, HitZoneIndex, default.EffectGroup);
SkinType.PlayTakeHitSound(P, HitLocation, HitInstigator, default.EffectGroup);
}
}
}
defaultproperties
{
KDamageImpulse=900
KDeathUpKick=-300
KDeathVel=100
DamageModifierAP=0.8f
ArmorDamageModifier=15.0f
StumblePower=15
GunHitPower=15
WeaponDef=class'KFWeapDef_G36C'
//Perk
ModifierPerkList(0)=class'KFPerk_Swat'
MetalImpactEffect=ParticleSystem'FX_Impacts_EMIT.FX_Wep_Impact_MetalArmor_E'
MetalImpactSound=AkEvent'WW_Skin_Impacts.Play_Slashing_Metal_3P'
}

View File

@ -0,0 +1,82 @@
//=============================================================================
// KFDT_Ballistic_HRG_Dragonbreath
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Ballistic_HRG_Dragonbreath extends KFDT_Ballistic_Shotgun
abstract
hidedropdown;
// Damage type to use for the burning damage over time
var class<KFDamageType> BurnDamageType;
/** 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;
}
/** Play damage type specific impact effects when taking damage */
static function PlayImpactHitEffects( KFPawn P, vector HitLocation, vector HitDirection, byte HitZoneIndex, optional Pawn HitInstigator )
{
// Play burn effect when dead
if( P.bPlayedDeath && P.WorldInfo.TimeSeconds > P.TimeOfDeath )
{
default.BurnDamageType.static.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator);
return;
}
super.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator);
}
/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */
static function ApplySecondaryDamage( KFPawn Victim, int DamageTaken, optional Controller InstigatedBy )
{
// Overriden to specific a different damage type to do the burn damage over
// time. We do this so we don't get shotgun pellet impact sounds/fx during
// the DOT burning.
if ( default.BurnDamageType.default.DoT_Type != DOT_None )
{
Victim.ApplyDamageOverTime(DamageTaken, InstigatedBy, default.BurnDamageType);
}
}
defaultproperties
{
GoreDamageGroup=DGT_Shotgun
BloodSpread=0.4
BloodScale=0.6
KDamageImpulse=3500
KDeathUpKick=800
KDeathVel=650
GibImpulseScale=1.0
BurnPower=40
StumblePower=40
GunHitPower=50
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
BurnDamageType=class'KFDT_Fire_HRG_DragonsBreathDoT'
EffectGroup=FXG_IncendiaryRound
ModifierPerkList(0)=class'KFPerk_Firebug'
}

View File

@ -0,0 +1,18 @@
//=============================================================================
// KFDT_Ballistic_HRG_Locust
//=============================================================================
// HRG Locust bullet impact
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Ballistic_HRG_Locust extends KFDamageType
abstract
hidedropdown;
defaultproperties
{
ModifierPerkList(0)=class'KFPerk_Survivalist'
WeaponDef=class'KFWeapDef_HRG_Locust'
}

View File

@ -0,0 +1,16 @@
//=============================================================================
// KFDT_Bludgeon_G36C
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Bludgeon_G36C extends KFDT_Bludgeon_RifleButt
abstract
hidedropdown;
DefaultProperties
{
//defaults
WeaponDef=class'KFWeapDef_G36C'
}

View File

@ -0,0 +1,16 @@
//=============================================================================
// KFDT_Bludgeon_HRG_Dragonbreath
//=============================================================================
// Killing Floor 2
// Copyright (C) 2017 Tripwire Interactive LLC
//=============================================================================
class KFDT_Bludgeon_HRG_Dragonbreath extends KFDT_Bludgeon_RifleButt
abstract
hidedropdown;
DefaultProperties
{
//defaults
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
}

View File

@ -0,0 +1,15 @@
//=============================================================================
// KFDT_Bludgeon_HRG_Locust
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Bludgeon_HRG_Locust extends KFDT_Bludgeon_RifleButt
abstract
hidedropdown;
DefaultProperties
{
//defaults
WeaponDef=class'KFWeapDef_HRG_Locust'
}

View File

@ -0,0 +1,40 @@
//=============================================================================
// KFDT_Explosive_HRG_Locust
//=============================================================================
// Explosive damage type for the HRG Locust
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Explosive_HRG_Locust extends KFDT_Explosive
abstract
hidedropdown;
// Damage type to use for the damage over time effect
var class<KFDamageType> DoTDamageType;
/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */
static function ApplySecondaryDamage(KFPawn Victim, int DamageTaken, optional Controller InstigatedBy)
{
if (Victim.Controller == InstigatedBy)
{
return;
}
if (default.DoTDamageType.default.DoT_Type != DOT_None)
{
Victim.ApplyDamageOverTime(class'KFDT_Toxic_HRG_Locust'.default.SpreadOnTouchDamage, InstigatedBy, default.DoTDamageType);
}
}
defaultproperties
{
//Perk
ModifierPerkList(0)=class'KFPerk_Survivalist'
WeaponDef=class'KFWeapDef_HRG_Locust'
DoTDamageType=class'KFDT_Toxic_HRG_Locust'
bCausesFracture=false
bCanPlayDeadHitEffects=false
}

View File

@ -0,0 +1,39 @@
//=============================================================================
// KFDT_Fire_Ground_HRG_DragonBreath
//=============================================================================
// Damage caused by burning from being hit by a HRG dragon breath ground fire
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Fire_Ground_HRG_DragonBreath extends KFDT_Fire_Ground
abstract;
static function int GetKillerDialogID()
{
return 86;//KILL_Fire
}
static function int GetDamagerDialogID()
{
return 102;//DAMZ_Fire
}
static function int GetDamageeDialogID()
{
return 116;//DAMP_Fire
}
defaultproperties
{
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
DoT_Type=DOT_Fire
DoT_Duration=2.7
DoT_Interval=0.5
DoT_DamageScale=0.7
BurnPower=10
}

View File

@ -0,0 +1,41 @@
//=============================================================================
// KFDT_Fire_HRG_DragonsBreathDoT
//=============================================================================
// Damage caused by burning from being hit by an HRG dragon's breath round
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//
//=============================================================================
class KFDT_Fire_HRG_DragonsBreathDoT extends KFDT_Fire
abstract
hidedropdown;
static function int GetKillerDialogID()
{
return 86;//KILL_Fire
}
static function int GetDamagerDialogID()
{
return 102;//DAMZ_Fire
}
static function int GetDamageeDialogID()
{
return 116;//DAMP_Fire
}
defaultproperties
{
WeaponDef=class'KFWeapDef_HRG_Dragonbreath'
DoT_Type=DOT_Fire
DoT_Duration=2.7 //5.0 //1.0
DoT_Interval=0.5
DoT_DamageScale=0.7 //1.0
BurnPower=10 //1.0 //18.5
}

View File

@ -0,0 +1,23 @@
//=============================================================================
// KFDT_Piercing_ScytheStab
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Piercing_ScytheStab extends KFDT_Piercing
abstract
hidedropdown;
defaultproperties
{
KDamageImpulse=200
KDeathUpKick=250
StumblePower=50
MeleeHitPower=100
WeaponDef=class'KFWeapDef_Scythe'
ModifierPerkList(0)=class'KFPerk_Berserker'
}

View File

@ -0,0 +1,140 @@
//=============================================================================
// KFDT_Slashing_ScytheLong
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Slashing_ScytheLong extends KFDT_Slashing
abstract
hidedropdown;
/** Allows the damage type to customize exactly which hit zones it can dismember */
static simulated function bool CanDismemberHitZone( name InHitZoneName )
{
return true;
}
/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */
static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName)
{
local EPawnOctant SlashDir;
local KFCharacterInfo_Monster MonsterInfo;
MonsterInfo = InPawn.GetCharacterMonsterInfo();
if ( MonsterInfo == none )
{
return;
}
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
if( SlashDir == DIR_Forward || SlashDir == DIR_Backward )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Randomly pick the left or right shoulder bone and split the guy in half vertically
OutBoneName = Rand(2) == 0
? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName
: MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
else if( SlashDir == DIR_Left || SlashDir == DIR_Right )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit )
{
// Split the guy in half horizontally
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName;
}
}
}
else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
// ... and choose one of the shoulder constraints at random
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
}
else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
}
}
}
/** Allows the damage type to modify the impulse when a specified hit zone is dismembered */
static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, name InHitZoneName, vector HitDirection,
out vector OutImpulseDir, out vector OutParentImpulseDir,
out float OutImpulseScale, out float OutParentImpulseScale)
{
local EPawnOctant SlashDir;
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
// Apply upward impulse on decapitation from a clean horizontal slash
if( InHitZoneName == 'head' &&
( SlashDir == DIR_Left || SlashDir == DIR_Right ) )
{
OutImpulseDir += 10*vect(0,0,1);
OutImpulseDir = Normal(OutImpulseDir);
OutParentImpulseScale = 0.f;
}
// Do not apply any impulse on split in half from a vertical slash
else if( (InHitZoneName == 'head' || InHitZoneName == 'chest' ) &&
( SlashDir == DIR_Forward || SlashDir == DIR_Backward) )
{
OutImpulseScale = 0.f;
OutParentImpulseScale = 0.f;
}
}
defaultproperties
{
KDamageImpulse=10000 //1500
KDeathUpKick=2000 //200
KDeathVel=3750 //375
KnockdownPower=0
StunPower=0
StumblePower=100
MeleeHitPower=100
WeaponDef=class'KFWeapDef_Scythe'
ModifierPerkList(0)=class'KFPerk_Berserker'
}

View File

@ -0,0 +1,38 @@
//=============================================================================
// KFDT_Slashing_ScytheLongAlt
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Slashing_ScytheLongAlt extends KFDT_Slashing_ZweihanderHeavy
abstract
hidedropdown;
defaultproperties
{
KDamageImpulse=3600 //1600
KDeathUpKick=400 //200
KDeathVel=750 //500
KnockdownPower=50
StunPower=0
StumblePower=200
MeleeHitPower=100
// Obliteration
GoreDamageGroup = DGT_Explosive
RadialDamageImpulse = 8000.f // This controls how much impulse is applied to gibs when exploding
bUseHitLocationForGibImpulses = true // This will make the impulse origin where the victim was hit for directional gibs
bPointImpulseTowardsOrigin = true // This creates an impulse direction aligned along hitlocation and pawn location -- this will push all gibs in the same direction
ImpulseOriginScale = 100.f // Higher means more directional gibbing, lower means more outward (and upward) gibbing
ImpulseOriginLift = 150.f
MaxObliterationGibs = 12 // Maximum number of gibs that can be spawned by obliteration, 0=MAX
bCanGib = true
bCanObliterate = true
ObliterationHealthThreshold = 0
ObliterationDamageThreshold = 100
WeaponDef=class'KFWeapDef_Scythe'
ModifierPerkList(0)=class'KFPerk_Berserker'
}

View File

@ -0,0 +1,140 @@
//=============================================================================
// KFDT_Slashing_ScytheShort
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Slashing_ScytheShort extends KFDT_Slashing
abstract
hidedropdown;
/** Allows the damage type to customize exactly which hit zones it can dismember */
static simulated function bool CanDismemberHitZone( name InHitZoneName )
{
return true;
}
/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */
static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName)
{
local EPawnOctant SlashDir;
local KFCharacterInfo_Monster MonsterInfo;
MonsterInfo = InPawn.GetCharacterMonsterInfo();
if ( MonsterInfo == none )
{
return;
}
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
if( SlashDir == DIR_Forward || SlashDir == DIR_Backward )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Randomly pick the left or right shoulder bone and split the guy in half vertically
OutBoneName = Rand(2) == 0
? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName
: MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
else if( SlashDir == DIR_Left || SlashDir == DIR_Right )
{
if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit )
{
// Split the guy in half horizontally
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName;
}
}
}
else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
// ... and choose one of the shoulder constraints at random
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName;
}
}
}
}
else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft )
{
if( InHitZoneName == 'chest' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
else if( InHitZoneName == 'head' )
{
if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit )
{
// Use a random chance to decide whether to dismember the head or the shoulder constraints
if( Rand(2) == 0 )
{
OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName;
}
}
}
}
}
/** Allows the damage type to modify the impulse when a specified hit zone is dismembered */
static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, name InHitZoneName, vector HitDirection,
out vector OutImpulseDir, out vector OutParentImpulseDir,
out float OutImpulseScale, out float OutParentImpulseScale)
{
local EPawnOctant SlashDir;
SlashDir = GetLastSlashDirection(InPawn, HitDirection);
// Apply upward impulse on decapitation from a clean horizontal slash
if( InHitZoneName == 'head' &&
( SlashDir == DIR_Left || SlashDir == DIR_Right ) )
{
OutImpulseDir += 10*vect(0,0,1);
OutImpulseDir = Normal(OutImpulseDir);
OutParentImpulseScale = 0.f;
}
// Do not apply any impulse on split in half from a vertical slash
else if( (InHitZoneName == 'head' || InHitZoneName == 'chest' ) &&
( SlashDir == DIR_Forward || SlashDir == DIR_Backward) )
{
OutImpulseScale = 0.f;
OutParentImpulseScale = 0.f;
}
}
defaultproperties
{
KDamageImpulse=10000 //1500
KDeathUpKick=2000 //200
KDeathVel=3750 //375
KnockdownPower=0
StunPower=0
StumblePower=50
MeleeHitPower=100
WeaponDef=class'KFWeapDef_Scythe'
ModifierPerkList(0)=class'KFPerk_Berserker'
}

View File

@ -0,0 +1,38 @@
//=============================================================================
// KFDT_Slashing_ScytheShortAlt
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFDT_Slashing_ScytheShortAlt extends KFDT_Slashing_ZweihanderHeavy
abstract
hidedropdown;
defaultproperties
{
KDamageImpulse=3600 //1600
KDeathUpKick=400 //200
KDeathVel=750 //500
KnockdownPower=0
StunPower=0
StumblePower=150
MeleeHitPower=100
// Obliteration
GoreDamageGroup = DGT_Explosive
RadialDamageImpulse = 8000.f // This controls how much impulse is applied to gibs when exploding
bUseHitLocationForGibImpulses = true // This will make the impulse origin where the victim was hit for directional gibs
bPointImpulseTowardsOrigin = true // This creates an impulse direction aligned along hitlocation and pawn location -- this will push all gibs in the same direction
ImpulseOriginScale = 100.f // Higher means more directional gibbing, lower means more outward (and upward) gibbing
ImpulseOriginLift = 150.f
MaxObliterationGibs = 12 // Maximum number of gibs that can be spawned by obliteration, 0=MAX
bCanGib = true
bCanObliterate = true
ObliterationHealthThreshold = 0
ObliterationDamageThreshold = 100
WeaponDef=class'KFWeapDef_Scythe'
ModifierPerkList(0)=class'KFPerk_Berserker'
}

View File

@ -0,0 +1,33 @@
//=============================================================================
// KFExplosion_HRG_Dragonbreath_GroundFire
//=============================================================================
// Explosion actor class for ground fire
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFExplosion_HRG_Dragonbreath_GroundFire extends KFExplosionActorLingering;
simulated function SpawnExplosionParticleSystem(ParticleSystem Template)
{
// If the template is none, grab the default
if( !ExplosionTemplate.bAllowPerMaterialFX && Template == none )
{
Template = KFGameExplosion(ExplosionTemplate).ExplosionEffects.DefaultImpactEffect.ParticleTemplate;
}
// Use custom pool
WorldInfo.GroundFireEmitterPool.SpawnEmitter(Template, Location, rotator(ExplosionTemplate.HitNormal), None);
}
DefaultProperties
{
//Interval=0.25f INTERVAL IS OVERRIDDEN BY ITS PROJECTILE
MaxTime=2.0
ExplosionLightPriority=LPP_Low
LoopStartEvent=AkEvent'ww_wep_hrg_megadragonbreath.Play_WEP_HRG_MegaDragonbreath_Flame_LP'
LoopStopEvent=AkEvent'ww_wep_hrg_megadragonbreath.Stop_WEP_HRG_MegaDragonbreath_End_Flame_LP'
}

View File

@ -0,0 +1,43 @@
//=============================================================================
// KFExplosion_HRG_Locust
//=============================================================================
// Explosion actor class for HRG Locust
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFExplosion_HRG_Locust extends KFExplosionActorLingering;
var private bool bFirstExplosion;
protected simulated function bool DoExplosionDamage(bool bCauseDamage, bool bCauseEffects)
{
local bool bReturnValue;
// Only does explosion damage one time
if (bCauseDamage && bFirstExplosion == false)
{
bCauseDamage = false;
}
bReturnValue = super.DoExplosionDamage(bCauseDamage, bCauseEffects);
bFirstExplosion = false;
return bReturnValue;
}
DefaultProperties
{
Interval=0.5f
MaxTime=3.0
bOnlyDamagePawns=true
bDoFullDamage=false
bFirstExplosion=true
LoopStartEvent=AkEvent'WW_WEP_HRG_Locust.Play_WEP_HRG_Locust_Insects'
LoopStopEvent=AkEvent'WW_WEP_HRG_Locust.Stop_WEP_HRG_Locust_Insect'
}

View File

@ -87,6 +87,7 @@ protected simulated function AffectsPawn(Pawn Victim, float DamageScale)
if( HumanVictim != none && HumanVictim.GetExposureTo(Location) > 0 )
{
OwnerProjectile = KFProj_MedicGrenade(Owner);
if( OwnerProjectile != none )
{
bCanRepairArmor = OwnerProjectile.HealedPawns.Find( HumanVictim ) == INDEX_NONE;

View File

@ -180,7 +180,7 @@ protected simulated function bool DoExplosionDamage(bool bCauseDamage, bool bCau
if( bOnlyDamagePawns )
{
return ExplodePawns();
return ExplodePawns(bCauseDamage);
}
return super(KFExplosionActor).DoExplosionDamage(bCauseDamage, bCauseEffects);

View File

@ -62,7 +62,7 @@ function UpdateHealer(Optional bool bForce)
}
function ShowActiveIndicators( array<string> IconPathStrings )
function ShowActiveIndicators( array<ActiveSkill> ActiveSkills )
{
}

View File

@ -48,6 +48,8 @@ var protected transient bool bWaveStarted;
// When this is true next wave will be last
var protected bool bGunGamePlayerOnLastGun;
var transient array<KFBarmwichBonfireVolume> BonfireVolumes;
/** Whether this game mode should play music from the get-go (lobby) */
static function bool ShouldPlayMusicAtStart()
{
@ -75,6 +77,8 @@ event PostBeginPlay()
TimeBetweenWaves = GetTraderTime();
bGunGamePlayerOnLastGun = false;
UpdateBonfires();
}
/** Set up the spawning */
@ -1144,6 +1148,8 @@ function WaveEnded(EWaveEndCondition WinCondition)
return;
}
ClearAllActorsFromBonfire();
if (WorldInfo.NetMode == NM_DedicatedServer)
{
scripttrace();
@ -1202,28 +1208,9 @@ function WaveEnded(EWaveEndCondition WinCondition)
}
}
if (OutbreakEvent != none && OutbreakEvent.ActiveEvent.bGunGameMode)
if (OutbreakEvent != none)
{
MyKFGRI.GunGameWavesCurrent += 1;
// If we unlocked last weapon we only finish if we completed the boss wave
// If we didn't unlock to last weapon and we just finished last wave (before BOSS), repeat
if (bGunGamePlayerOnLastGun)
{
MyKFGRI.bWaveGunGameIsFinal = true;
if (WaveNum < WaveMax)
{
WaveNum = WaveMax - 1;
}
}
else if (WaveNum >= WaveMax - 1)
{
// Repeat wave before BOSS till forever
WaveNum = WaveMax - 2;
}
MyKFGRI.bNetDirty = true;
OnOutbreakWaveWon();
}
if (WaveNum < WaveMax)
@ -1873,6 +1860,38 @@ function DebugKillZeds()
}
}
function OnOutbreakWaveWon() {}
function UpdateBonfires()
{
local KFBarmwichBonfireVolume BonfireVolume;
foreach AllActors(class'KFBarmwichBonfireVolume', BonfireVolume)
{
BonfireVolumes.AddItem(BonfireVolume);
}
}
function ClearAllActorsFromBonfire()
{
local KFBarmwichBonfireVolume BonfireVolume;
foreach BonfireVolumes(BonfireVolume)
{
BonfireVolume.ClearAllActors();
}
}
function ClearActorFromBonfire(Actor Other)
{
local KFBarmwichBonfireVolume BonfireVolume;
foreach BonfireVolumes(BonfireVolume)
{
BonfireVolume.ClearActor(Other);
}
}
DefaultProperties
{
TimeBetweenWaves=60 //This is going to be a difficulty setting later

View File

@ -988,7 +988,7 @@ function LoadGunGameWeapons(Controller NewPlayer)
Weapon = KFWeapon(Inv);
if (Weapon != none)
{
Weapon.GunGameRemove();
Weapon.RemoveGun();
}
}
}
@ -1108,37 +1108,43 @@ function ResetGunGame(KFPlayerController_WeeklySurvival KFPC_WS)
function NotifyKilled(Controller Killer, Controller Killed, Pawn KilledPawn, class<DamageType> damageType )
{
local KFPawn_Monster KFPM;
local KFPlayerController_WeeklySurvival KFPC_WS;
local KFPlayerController_WeeklySurvival KFPC_WS_Killer, KFPC_WS_Killed;
super.NotifyKilled(Killer, Killed, KilledPawn, damageType);
if (!OutbreakEvent.ActiveEvent.bGunGameMode)
KFPM = KFPawn_Monster(KilledPawn);
KFPC_WS_Killer = KFPlayerController_WeeklySurvival(Killer);
KFPC_WS_Killed = KFPlayerController_WeeklySurvival(Killed);
if (OutbreakEvent.ActiveEvent.bGunGameMode)
{
return;
}
// If pawn is monster increase gun game score for that monster
// If pawn is monster increase gun game score for that monster
KFPM = KFPawn_Monster(KilledPawn);
KFPC_WS = KFPlayerController_WeeklySurvival(Killer);
if (KFPM != none && KFPC_WS != none)
{
if (KFPC_WS.Pawn.Health > 0)
if (KFPM != none && KFPC_WS_Killer != none)
{
KFPC_WS.GunGameData.Score += KFPM.GunGameKilledScore;
UpdateGunGameLevel(KFPC_WS);
if (KFPC_WS_Killer.Pawn.Health > 0)
{
KFPC_WS_Killer.GunGameData.Score += KFPM.GunGameKilledScore;
UpdateGunGameLevel(KFPC_WS_Killer);
}
}
else
{
// If pawn is human reset game score (we can just check Killed exists as Controller
if (KFPC_WS_Killed != none)
{
ResetGunGame(KFPC_WS_Killed);
}
}
}
else
if (OutbreakEvent.ActiveEvent.bVIPGameMode)
{
// If pawn is human reset game score (we can just check Killed exists as Controller)
KFPC_WS = KFPlayerController_WeeklySurvival(Killed);
if (KFPC_WS != none)
if (KFPC_WS_Killed != none && KFPC_WS_Killed.VIPGameData.isVIP)
{
ResetGunGame(KFPC_WS);
// UnregisterPlayer is done on the same frame but this function comes first..
// we queue a petition to end the game if no vip is found
SetTimer(1.5f, false, 'OnVIPDiesEndMatch');
}
}
}
@ -1240,7 +1246,7 @@ function UpdateGunGameLevel(KFPlayerController_WeeklySurvival KFPC_WS)
{
// To prevent audio/vfx lock, while firing when removing the equipped weapon we do a proper gun remove
// This new function manages it's state internally
CurrentWeapon.GunGameRemove();
CurrentWeapon.RemoveGun();
}
if (class'KFPerk_SWAT'.static.Is9mm(CurrentWeapon))
@ -1278,6 +1284,222 @@ function UpdateGunGameLevel(KFPlayerController_WeeklySurvival KFPC_WS)
}
}
///////////////////////////////////////////////////////////////////////////////////
function UnregisterPlayer(PlayerController PC)
{
local KFPlayerController_WeeklySurvival KFPC_WS;
super.UnregisterPlayer(PC);
KFPC_WS = KFPlayerController_WeeklySurvival(PC);
if (OutbreakEvent.ActiveEvent.bVIPGameMode)
{
if (KFPC_WS != none && KFPC_WS.VIPGameData.IsVIP)
{
ChooseVIP(false, KFPC_WS);
}
}
}
function WaveStarted()
{
Super.WaveStarted();
if (OutbreakEvent.ActiveEvent.bVIPGameMode)
{
if (WaveNum <= 1)
{
ChooseVIP(true);
}
}
}
function OnVIPDiesEndMatch()
{
local KFPlayerController KFPC;
foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC)
{
KFPC.SetCameraMode('ThirdPerson');
}
WaveEnded(WEC_TeamWipedOut);
}
function ChooseVIP_SetupVIP()
{
local KFPlayerController_WeeklySurvival KFPC_WS, NewVIP;
local KFGameReplicationInfo KFGRI;
NewVIP = none;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
{
if (KFPC_WS != none)
{
if (KFPC_WS.VIPGameData.IsVIP)
{
NewVIP = KFPC_WS;
break;
}
}
}
if (NewVIP != none)
{
//`Log("Setup new VIP: " $NewVIP);
if (NewVIP.Pawn != none)
{
//`Log("Finished setup new VIP: " $NewVIP);
NewVIP.GetPerk().PerkSetOwnerHealthAndArmor(false);
if (NewVIP.VIPGameData.PendingHealthReset)
{
NewVIP.VIPGameData.PendingHealthReset = false;
// Change current health directly, Pawn.HealDamage does a lot of other stuff that can block the healing
NewVIP.Pawn.Health = NewVIP.Pawn.HealthMax;
}
// Replicate new data to clients
KFGRI.UpdateVIPPlayer(KFPlayerReplicationInfo(NewVIP.PlayerReplicationInfo));
KFGRI.UpdateVIPMaxHealth(NewVIP.Pawn.HealthMax);
KFGRI.UpdateVIPCurrentHealth(NewVIP.Pawn.Health);
NewVIP.PlayVIPGameChosenSound(3.5f);
ClearTimer('ChooseVIP_SetupVIP');
}
}
}
function ChooseVIP(bool ForceAddHealth, optional KFPlayerController_WeeklySurvival PlayerJustLeft = none)
{
local int RandomNumber;
local KFPlayerController_WeeklySurvival KFPC_WS, CurrentVIP, NewVIP;
local array<KFPlayerController_WeeklySurvival> PotentialVIP;
local KFGameReplicationInfo KFGRI;
//`Log("ChooseVIP!!!!!");
ClearTimer('ChooseVIP_SetupVIP');
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
{
if (KFPC_WS != none)
{
if (KFPC_WS.VIPGameData.IsVIP == false && KFPC_WS.VIPGameData.WasVIP == false)
{
PotentialVIP.AddItem(KFPC_WS);
}
if (KFPC_WS.VIPGameData.IsVIP)
{
CurrentVIP = KFPC_WS;
}
}
}
if (CurrentVIP != none)
{
//`Log("Remove old VIP: " $CurrentVIP);
CurrentVIP.VIPGameData.IsVIP = false;
CurrentVIP.GetPerk().PerkSetOwnerHealthAndArmor(false);
}
// If there's no potential VIP we restart
if (PotentialVIP.Length == 0)
{
foreach WorldInfo.AllControllers(class'KFPlayerController_WeeklySurvival', KFPC_WS)
{
if (KFPC_WS != none)
{
KFPC_WS.VIPGameData.WasVIP = false;
if (PlayerJustLeft == none
|| PlayerJustLeft != KFPC_WS)
{
PotentialVIP.AddItem(KFPC_WS);
}
}
}
}
if (PotentialVIP.Length > 0)
{
RandomNumber = Rand(PotentialVIP.Length);
NewVIP = PotentialVIP[RandomNumber];
NewVIP.VIPGameData.IsVIP = true;
NewVIP.VIPGameData.WasVIP = true;
}
if (NewVIP != none)
{
if (ForceAddHealth || (KFGRI != none && KFGRI.bWaveIsActive == false))
{
NewVIP.VIPGameData.PendingHealthReset = true;
}
// If there's no Pawn we have to wait on a Timer function
if (NewVIP.Pawn != none)
{
ChooseVIP_SetupVIP();
}
else
{
SetTimer(0.25f, true, 'ChooseVIP_SetupVIP');
}
ClearTimer('OnVIPDiesEndMatch');
}
}
function OnOutbreakWaveWon()
{
Super.OnOutbreakWaveWon();
// GunGame Mode
if (OutbreakEvent.ActiveEvent.bGunGameMode)
{
MyKFGRI.GunGameWavesCurrent += 1;
// If we unlocked last weapon we only finish if we completed the boss wave
// If we didn't unlock to last weapon and we just finished last wave (before BOSS), repeat
if (bGunGamePlayerOnLastGun)
{
MyKFGRI.bWaveGunGameIsFinal = true;
if (WaveNum < WaveMax)
{
WaveNum = WaveMax - 1;
}
}
else if (WaveNum >= WaveMax - 1)
{
// Repeat wave before BOSS till forever
WaveNum = WaveMax - 2;
}
MyKFGRI.bNetDirty = true;
}
// VIP Mode
if (OutbreakEvent.ActiveEvent.bVIPGameMode)
{
ChooseVIP(true);
}
}
defaultproperties
{
//Overrides

View File

@ -198,19 +198,32 @@ simulated function bool CanActivateObjectiveByWeekly()
{
if (Role == Role_Authority)
{
if (KFGameInfo(WorldInfo.Game).OutbreakEvent != none
&& KFGameInfo(WorldInfo.Game).OutbreakEvent.ActiveEvent.bGunGameMode)
if (KFGameInfo(WorldInfo.Game).OutbreakEvent != none)
{
return false;
if (KFGameInfo(WorldInfo.Game).OutbreakEvent.ActiveEvent.bGunGameMode)
{
return false;
}
if (KFGameInfo(WorldInfo.Game).OutbreakEvent.ActiveEvent.bVIPGameMode)
{
return false;
}
}
}
else
{
if (KFGameReplicationInfo(WorldInfo.GRI) != none
&& KFGameReplicationInfo(WorldInfo.GRI).bIsWeeklyMode
&& KFGameReplicationInfo(WorldInfo.GRI).CurrentWeeklyIndex == 16)
if (KFGameReplicationInfo(WorldInfo.GRI) != none && KFGameReplicationInfo(WorldInfo.GRI).bIsWeeklyMode)
{
return false;
if (KFGameReplicationInfo(WorldInfo.GRI).CurrentWeeklyIndex == 16)
{
return false;
}
if (KFGameReplicationInfo(WorldInfo.GRI).CurrentWeeklyIndex == 17)
{
return false;
}
}
}

View File

@ -920,7 +920,6 @@ defaultproperties
bSpawnWeaponListAffectsSecondaryWeapons=true,
OverrideItemPickupModifier= 0.5f, //1.0f, //2.0f, // 0.f,
OverrideAmmoPickupModifier= 1.0f, //2.0f, //3.0f, // 0.01f,
bOnlyArmorItemPickup=true,
TraderTimeModifier=1.0f, // 0.1f,
TimeBetweenWaves=30.f,
bDisableAddDosh=true,
@ -1190,6 +1189,37 @@ defaultproperties
)}
// VIP
SetEvents[17]={(
EventDifficulty=2,
GameLength=GL_Normal,
bVIPGameMode=true,
VIPTargetting=(class'KFGameContent.KFPawn_ZedScrake'
, class'KFGameContent.KFPawn_ZedFleshpound'
, class'KFGameContent.KFPawn_ZedFleshpoundMini'
, class'KFGameContent.KFPawn_ZedGorefast'
, class'KFGameContent.KFPawn_ZedGorefastDualBlade'
, class'KFGameContent.KFPawn_ZedClot_Cyst'
, class'KFGameContent.KFPawn_ZedClot_Slasher'
, class'KFGameContent.KFPawn_ZedClot_Alpha'
, class'KFGameContent.KFPawn_ZedClot_AlphaKing'
, class'KFGameContent.KFPawn_ZedBloat'
, class'KFGameContent.KFPawn_ZedHusk'
, class'KFGameContent.KFPawn_ZedSiren'
, class'KFGameContent.KFPawn_ZedCrawler'
, class'KFGameContent.KFPawn_ZedCrawlerKing'
, class'KFGameContent.KFPawn_ZedStalker'
, class'KFGameContent.KFPawn_ZedDAR_EMP'
, class'KFGameContent.KFPawn_ZedDAR_Laser'
, class'KFGameContent.KFPawn_ZedDAR_Rocket'
, class'KFGameContent.KFPawn_ZedMatriarch'
, class'KFGameContent.KFPawn_ZedPatriarch'
, class'KFGameContent.KFPawn_ZedBloatKing'
, class'KFGameContent.KFPawn_ZedBloatKingSubspawn'
, class'KFGameContent.KFPawn_ZedFleshpoundKing'
, class'KFGameContent.KFPawn_ZedHans'),
)}
//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

View File

@ -440,7 +440,7 @@ function AdjustDamage(out int InDamage, out vector Momentum, Controller Instigat
}
}
function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class<DamageType> DamageType, Actor DamageCauser)
function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class<KFDamageType> DamageType, Actor DamageCauser)
{
if (ShieldHealthPctByte == 0)
{

View File

@ -39,6 +39,7 @@ state WaveState
local TraceHitInfo HitInfo;
local float Radius;
local float DamageHead;
local name HitBoneName;
if(bWaveActive)
{
@ -54,9 +55,17 @@ state WaveState
if(DamageHead > 0)
{
//`Log("Take: "$Victim);
//HitInfo.BoneName = 'head';
HitBoneName = Victim.HeadBoneName;
if(HitBoneName != `NAME_NONE)
{
HitInfo.BoneName = HitBoneName;
}
//`Log("HitInfo.BoneName: "$HitInfo.BoneName);
Victim.TakeDamage(DamageHead * UpgradeDamageMod, InstigatorController, Victim.Location, Normal(Victim.Location - Instigator.Location), MyDamageType, HitInfo, (Owner != None) ? Owner : self);
//Monster.PlayDismemberment(0, MyDamageType, WaveImpactMomentum);
if (Victim.Health <= 0)
{

View File

@ -0,0 +1,25 @@
//=============================================================================
// KFProj_HRG_DragonBreath_Splash
//=============================================================================
// Projectile class for hrg dragonbreath gun splash. Handles a few overrides.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFProj_HRG_DragonBreath_Splash extends KFProj_FlareGunSplash;
defaultproperties
{
PostExplosionLifetime=2.5
ExplosionActorClass=class'KFExplosion_HRG_Dragonbreath_GroundFire'
Begin Object Name=ExploTemplate0
Damage=8
DamageRadius=150.0
MyDamageType=class'KFDT_Fire_Ground_HRG_DragonBreath'
ExplosionEffects=KFImpactEffectInfo'WEP_Flamethrower_ARCH.GroundFire_Impacts'
End Object
AssociatedPerkClass=none
}

View File

@ -0,0 +1,171 @@
//=============================================================================
// KFProj_HRG_Locust
//=============================================================================
// HRG Locust projectile
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//
//=============================================================================
class KFProj_HRG_Locust extends KFProj_BallisticExplosive
hidedropdown;
/** Our intended target actor */
var private KFPawn LockedTarget;
/** How much 'stickyness' when seeking toward our target. Determines how accurate rocket is */
var const float SeekStrength;
replication
{
if( bNetInitial )
LockedTarget;
}
function SetLockedTarget( KFPawn NewTarget )
{
LockedTarget = NewTarget;
}
simulated function bool AllowNuke()
{
return false;
}
simulated function bool AllowDemolitionistConcussive()
{
return false;
}
simulated function bool AllowDemolitionistExplosionChangeRadius()
{
return false;
}
simulated event Tick( float DeltaTime )
{
local vector TargetImpactPos, DirToTarget;
super.Tick( DeltaTime );
// Skip the first frame, then start seeking
if( !bHasExploded
&& LockedTarget != none
&& Physics == PHYS_Projectile
&& Velocity != vect(0,0,0)
&& LockedTarget.IsAliveAndWell()
&& `TimeSince(CreationTime) > 0.03f )
{
// Grab our desired relative impact location from the weapon class
TargetImpactPos = class'KFWeap_HRG_Locust'.static.GetLockedTargetLoc( LockedTarget );
// Seek towards target
Speed = VSize( Velocity );
DirToTarget = Normal( TargetImpactPos - Location );
Velocity = Normal( Velocity + (DirToTarget * (SeekStrength * DeltaTime)) ) * Speed;
// Aim rotation towards velocity every frame
SetRotation( rotator(Velocity) );
}
}
simulated protected function PrepareExplosionTemplate()
{
local Weapon OwnerWeapon;
local Pawn OwnerPawn;
local KFPerk_Survivalist Perk;
super(KFProjectile).PrepareExplosionTemplate();
OwnerWeapon = Weapon(Owner);
if (OwnerWeapon != none)
{
OwnerPawn = Pawn(OwnerWeapon.Owner);
if (OwnerPawn != none)
{
Perk = KFPerk_Survivalist(KFPawn(OwnerPawn).GetPerk());
if (Perk != none)
{
ExplosionTemplate.DamageRadius *= KFPawn(OwnerPawn).GetPerk().GetAoERadiusModifier();
}
}
}
}
defaultproperties
{
Physics=PHYS_Projectile
Speed=4000 //6000
MaxSpeed=4000 //6000
TossZ=0
GravityScale=1.0
MomentumTransfer=0.0f
Damage=10
DamageRadius=0
SeekStrength=928000.0f // 128000.0f
bWarnAIWhenFired=true
ProjFlightTemplate=ParticleSystem'WEP_HRG_Locust_EMIT.FX_HRG_Locust_Projectile'
ProjFlightTemplateZedTime=ParticleSystem'WEP_HRG_Locust_EMIT.FX_HRG_Locust_Projectile_ZED_TIME'
ProjDisintegrateTemplate=ParticleSystem'WEP_HRG_Locust_EMIT.FX_Flying_Bugs_dispersion'
AmbientSoundPlayEvent=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Projectile'
AmbientSoundStopEvent=AkEvent'WW_WEP_Seeker_6.Stop_WEP_Seeker_6_Projectile'
ExplosionActorClass=class'KFExplosion_HRG_Locust'
AltExploEffects=KFImpactEffectInfo'WEP_HRG_Locust_ARCH.FX_HRG_Locust_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
// explosion
Begin Object Class=KFGameExplosion Name=ExploTemplate0
Damage=80
DamageRadius=300
DamageFalloffExponent=0.5f
DamageDelay=0.f
//Impulse applied to Zeds
MomentumTransferScale=1
// Damage Effects
MyDamageType=class'KFDT_Explosive_HRG_Locust'
KnockDownStrength=0
FractureMeshRadius=0.0
FracturePartVel=0.0
ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Locust_ARCH.FX_HRG_Locust_Explosion_Concussive_force'
ExplosionSound=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Explosion'
// Dynamic Light
ExploLight=ExplosionPointLight
ExploLightStartFadeOutTime=0.0
ExploLightFadeOutTime=0.2
// Camera Shake
CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble'
CamShakeInnerRadius=0
CamShakeOuterRadius=500
CamShakeFalloff=3.f
bOrientCameraShakeTowardsEpicenter=true
bIgnoreInstigator=true
End Object
ExplosionTemplate=ExploTemplate0
bCanDisintegrate=false
}

View File

@ -905,8 +905,8 @@ defaultproperties
MaxDamageRadiusPerPercentage=340
MinDamageRadiusPerPercentage=160
MaxDamagePerPercentage=350 //300
MinDamagePerPercentage=35 //30
MaxDamagePerPercentage=400 //350 //300
MinDamagePerPercentage=40 //35 //30
MaxCollisionRadius=20
MinCollisionRadius=10

View File

@ -0,0 +1,85 @@
//=============================================================================
// KFProj_Pellet_HRG_Dragonbreath
//=============================================================================
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFProj_Pellet_HRG_Dragonbreath extends KFProj_Bullet_Pellet
hidedropdown;
/** Last hit normal from Touch() or HitWall() */
var vector LastHitNormal;
var float GroundFireChance;
simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal)
{
LastHitNormal = HitNormal;
Super.ProcessTouch(Other, HitLocation, HitNormal);
}
/**
* Explode this Projectile
*/
simulated function TriggerExplosion(Vector HitLocation, Vector HitNormal, Actor HitActor)
{
LastHitNormal = HitNormal;
Super.TriggerExplosion(HitLocation, HitNormal, HitActor);
}
simulated protected function StopSimulating()
{
local vector FlameSpawnVel;
if (Role == ROLE_Authority && Physics == PHYS_Falling && FRand() < GroundFireChance)
{
//SpawnGroundFire();
FlameSpawnVel = 0.25f * CalculateResidualFlameVelocity(LastHitNormal, Normal(Velocity), VSize(Velocity));
SpawnResidualFlame(class'KFProj_HRG_DragonBreath_Splash', Location + (LastHitNormal * 10.f), FlameSpawnVel);
}
super.StopSimulating();
}
defaultproperties
{
GroundFireChance=1.f
Physics=PHYS_Falling
MaxSpeed=7000.0
Speed=7000.0
TerminalVelocity=7000.0
bWarnAIWhenFired=true
DamageRadius=0
GravityScale=0.35
TossZ=0
Begin Object Class=PointLightComponent Name=PointLight0
LightColor=(R=252,G=218,B=171,A=255)
Brightness=0.5f
Radius=500.f
FalloffExponent=10.f
CastShadows=False
CastStaticShadows=FALSE
CastDynamicShadows=False
bCastPerObjectShadows=false
bEnabled=true
LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE)
End Object
ProjFlightLight=PointLight0
ImpactEffects=KFImpactEffectInfo'WEP_DragonsBreath_ARCH.DragonsBreath_bullet_impact'
ProjFlightTemplate=ParticleSystem'WEP_DragonsBreath_EMIT.Tracer.FX_DragonsBreath_Tracer'
ProjFlightTemplateZedTime=ParticleSystem'WEP_DragonsBreath_EMIT.Tracer.FX_DragonsBreath_Tracer_ZEDTime'
AmbientSoundPlayEvent=AkEvent'WW_WEP_SA_DragonsBreath.Play_SA_DragonsBreath_Projectile_Loop'
AmbientSoundStopEvent=AkEvent'WW_WEP_SA_DragonsBreath.Stop_SA_DragonsBreath_Projectile_Loop'
}

View File

@ -0,0 +1,128 @@
//=============================================================================
// KFSeasonalEventStats_Fall2022
//=============================================================================
// Tracks event-specific challenges/accomplishments for Fall 2022
//=============================================================================
// Killing Floor 2
// Copyright (C) 2021 Tripwire Interactive LLC
//=============================================================================
class KFSeasonalEventStats_Fall2022 extends KFSeasonalEventStats;
var transient private const int BossKillsRequired, ZedsInBonfiresRequired, EndlessWaveRequired;
private event Initialize(string MapName)
{
local string CapsMapName;
CapsMapName = Caps(MapName);
bObjectiveIsValidForMap[0] = 1; // Kill 15 Bosses on any map or mode
bObjectiveIsValidForMap[1] = 0; // Complete the Weekly on BarmwichTown
bObjectiveIsValidForMap[2] = 0; // Open the Weapon Room
bObjectiveIsValidForMap[3] = 0; // Make 50 Zeds to pass through the bonfires of Barmwitch Town
bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Barmwitch Town
if (CapsMapName == "KF-BARMWICHTOWN")
{
bObjectiveIsValidForMap[1] = 1;
bObjectiveIsValidForMap[2] = 1;
bObjectiveIsValidForMap[3] = 1;
bObjectiveIsValidForMap[4] = 1;
}
SetSeasonalEventStatsMax(BossKillsRequired, 0, 0, ZedsInBonfiresRequired, EndlessWaveRequired);
}
private event GrantEventItems()
{
if (Outer.IsEventObjectiveComplete(0) &&
Outer.IsEventObjectiveComplete(1) &&
Outer.IsEventObjectiveComplete(2) &&
Outer.IsEventObjectiveComplete(3) &&
Outer.IsEventObjectiveComplete(4))
{
GrantEventItem(9424);
}
}
// Kill 15 Bosses on any map or mode
simulated function OnBossDied()
{
local int ObjIdx;
ObjIdx = 0;
// Boss kills in any map
if (bObjectiveIsValidForMap[ObjIdx] != 0)
{
IncrementSeasonalEventStat(ObjIdx, 1);
if (Outer.GetSeasonalEventStatValue(ObjIdx) >= BossKillsRequired)
{
FinishedObjective(SEI_Fall, ObjIdx);
}
}
}
// Complete the Weekly on Netherhold
simulated event OnGameWon(class<GameInfo> GameClass, int Difficulty, int GameLength, bool bCoOp)
{
local int ObjIdx;
ObjIdx = 1;
if (bObjectiveIsValidForMap[ObjIdx] != 0)
{
if (GameClass == class'KFGameInfo_WeeklySurvival')
{
FinishedObjective(SEI_Fall, ObjIdx);
}
}
}
// Complete wave 15 on Endless Hard or higher difficulty on Netherhold
simulated event OnWaveCompleted(class<GameInfo> GameClass, int Difficulty, int WaveNum)
{
local int ObjIdx;
ObjIdx = 4;
if (bObjectiveIsValidForMap[ObjIdx] != 0)
{
if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD)
{
FinishedObjective(SEI_Fall, ObjIdx);
}
}
}
simulated function OnTryCompleteObjective(int ObjectiveIndex, int EventIndex)
{
local int WeaponRoomIdx, BonfireIdx;
WeaponRoomIdx = 2;
BonfireIdx = 3;
if(EventIndex == SEI_Fall)
{
if (ObjectiveIndex == WeaponRoomIdx)
{
if (bObjectiveIsValidForMap[ObjectiveIndex] != 0)
{
FinishedObjective(SEI_Fall, ObjectiveIndex);
}
}
else if (ObjectiveIndex == BonfireIdx)
{
if (bObjectiveIsValidForMap[ObjectiveIndex] != 0)
{
IncrementSeasonalEventStat(ObjectiveIndex, 1);
if (Outer.GetSeasonalEventStatValue(ObjectiveIndex) >= ZedsInBonfiresRequired)
{
FinishedObjective(SEI_Fall, ObjectiveIndex);
}
}
}
}
}
defaultproperties
{
BossKillsRequired=15
EndlessWaveRequired=15
ZedsInBonfiresRequired=50
}

View File

@ -0,0 +1,83 @@
//=============================================================================
// KFWeapAttach_HRG_Dragonbreath
//=============================================================================
//
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeapAttach_HRG_Dragonbreath extends KFWeaponAttachment;
`define HRGDRAGONBREATH_MIC_BARREL_INDEX 0
var transient float BarrelHeatPerProjectile;
var transient float MaxBarrelHeat;
var transient float BarrelCooldownRate;
var transient float CurrentBarrelHeat;
var transient float LastBarrelHeat;
var transient int NumPelletsDefault;
var transient int NumPelletsAlt;
simulated event PreBeginPlay()
{
Super.PreBeginPlay();
BarrelHeatPerProjectile = class'KFWeap_HRG_Dragonbreath'.default.BarrelHeatPerProjectile;
MaxBarrelHeat = class'KFWeap_HRG_Dragonbreath'.default.MaxBarrelHeat;
BarrelCooldownRate = class'KFWeap_HRG_Dragonbreath'.default.BarrelCooldownRate;
NumPelletsDefault = class'KFWeap_HRG_Dragonbreath'.default.NumPellets[0];
NumPelletsAlt = class'KFWeap_HRG_Dragonbreath'.default.NumPellets[1];
}
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
// Force start with "Glow_Intensity" of 0.0f
LastBarrelHeat = MaxBarrelHeat;
ChangeBarrelMaterial();
}
simulated function ChangeBarrelMaterial()
{
if( CurrentBarrelHeat != LastBarrelHeat )
{
if ( WeaponMIC == None && WeapMesh != None )
{
WeaponMIC = WeapMesh.CreateAndSetMaterialInstanceConstant(`HRGDRAGONBREATH_MIC_BARREL_INDEX);
}
WeaponMIC.SetScalarParameterValue('Barrel_intensity', CurrentBarrelHeat);
}
}
simulated function Tick(float Delta)
{
Super.Tick(Delta);
CurrentBarrelHeat = fmax(CurrentBarrelHeat - BarrelCooldownRate * Delta, 0.0f);
ChangeBarrelMaterial();
}
/** Override to update emissive in weapon's barrel after firing */
simulated function PlayWeaponFireAnim()
{
local float BarrelHeatPerShot;
local KFPawn OwnerPawn;
Super.PlayWeaponFireAnim();
OwnerPawn = KFPawn(Owner);
BarrelHeatPerShot = BarrelHeatPerProjectile * (OwnerPawn.FiringMode == 0 ? NumPelletsDefault : NumPelletsAlt);
CurrentBarrelHeat = fmin(CurrentBarrelHeat + BarrelHeatPerShot, MaxBarrelHeat);
}
defaultproperties
{
CurrentBarrelHeat=0.0f
LastBarrelHeat=0.0f
NumPelletsDefault=0
NumPelletsAlt=0
}

View File

@ -0,0 +1,144 @@
//=============================================================================
// KFWeapAttach_Scythe
//=============================================================================
//
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeapAttach_Scythe extends KFWeaponAttachment;
var const float UnfoldBlendingDuration;
var const float UnfoldedAnimRateModifier;
const FoldAnim = 'Clean_NoBlood';
var AnimTree CustomAnimTree;
var AnimNodeBlendPerBone FoldBlendNode;
var transient bool bIsFolded;
event PreBeginPlay()
{
Super.PreBeginPlay();
// Override the animtree. Doing this here (before AttachTo) instead of in defaultprops
// avoids an undesired call to our owning Pawn's PostInitAnimTree
if ( CustomAnimTree != None )
{
WeapMesh.SetAnimTreeTemplate(CustomAnimTree);
WeapAnimNode = AnimNodeSequence(WeapMesh.FindAnimNode('WeaponSeq'));
FoldBlendNode = AnimNodeBlendPerBone(WeapMesh.FindAnimNode('FoldBlendNode'));
// The special event might have arrived before the attachment is created, but it's updated in the owner, so copy the state here...
if (KFPawn(Owner) != none && FoldBlendNode != none)
{
bIsFolded = KFPawn(Owner).WeaponSpecialAction == 0;
FoldBlendNode.SetBlendTarget(bIsFolded ? 1.0f : 0.0f, 0.f);
}
}
}
simulated function ChangeMode()
{
bIsFolded = !bIsFolded;
// FoldControl = SkelControlSingleBone( WeapMesh.FindSkelControl('FoldControl') );
if( FoldBlendNode != none )
{
FoldBlendNode.SetBlendTarget( bIsFolded ? 1.0f : 0.0f, 0.0f );
}
}
/** Called from the pawn when our first person weapon changes states */
simulated function UpdateThirdPersonWeaponAction(EWeaponState NewWeaponState, KFPawn P, byte ThirdPersonAnimRateByte )
{
Super.UpdateThirdPersonWeaponAction(NewWeaponState, P, ThirdPersonAnimRate);
if (NewWeaponState == WEP_Cleaning)
{
if (WeapAnimNode != none)
{
if (WeapAnimNode.AnimSeq == none)
{
WeapAnimNode.SetAnim(FoldAnim);
}
WeapAnimNode.PlayAnim();
}
}
}
simulated function ANIMNOTIFY_ShellEject()
{
ChangeMode();
}
/**
* Plays a split (upper and lower body) animation on the owning pawn
* Network: All but dedicated
*
* @param P Owning pawn to play animation on
* @param AnimName Anim to play
* @param bPlaySynchronizedWeaponAnim If true, try to play the same animation on the weapon mesh
*/
simulated function float PlayCharacterMeshAnim(KFPawn P, name AnimName, optional bool bPlaySynchedWeaponAnim, optional bool bLooping)
{
local float AnimRate;
local float Duration;
local EAnimSlotStance Stance;
local string AnimStr;
// skip weapon anims while in a special move
if( P.IsDoingSpecialMove() && !P.SpecialMoves[P.SpecialMove].bAllowThirdPersonWeaponAnims )
{
return 0.f;
}
Stance = (!P.bIsCrouched) ? EAS_UpperBody : EAS_CH_UpperBody;
AnimRate = ThirdPersonAnimRate;
AnimStr = Caps(string(AnimName));
if (!bIsFolded && (InStr(AnimStr, "ATK") != INDEX_NONE || InStr(AnimName, "COMB") != INDEX_NONE))
{
AnimRate *= UnfoldedAnimRateModifier;
}
Duration = P.PlayBodyAnim(AnimName, Stance, AnimRate, DefaultBlendInTime, DefaultBlendOutTime, bLooping);
if ( Duration > 0 && bPlaySynchedWeaponAnim )
{
PlayWeaponMeshAnim(AnimName, P.BodyStanceNodes[Stance], bLooping);
}
`log(GetFuncName()@"called on:"$P@"Anim:"$AnimName@"Duration:"$Duration, bDebug);
return Duration;
}
/** Special event added for weap attachments. Free for use */
function OnSpecialEvent(int Arg)
{
bIsFolded = Arg == 0;
// FoldControl = SkelControlSingleBone( WeapMesh.FindSkelControl('FoldControl') );
if( FoldBlendNode != none )
{
FoldBlendNode.SetBlendTarget( bIsFolded ? 1.0f : 0.0f, 0.0f );
}
}
defaultproperties
{
CustomAnimTree=AnimTree'WEP_Scythe_ARCH.3P_Scythe_Animtree'
bIsFolded=true;
UnfoldBlendingDuration=0.25f
UnfoldedAnimRateModifier=0.7f;
// Weapon SkeletalMesh
Begin Object Name=SkeletalMeshComponent0
bForceRefPose=0
End Object
}

View File

@ -0,0 +1,159 @@
//=============================================================================
// KFWeap_AssaultRifle_G36C
//=============================================================================
// Class Description
//=============================================================================
// Killing Floor 2
// Copyright (C) 2022 Tripwire Interactive LLC
//=============================================================================
class KFWeap_AssaultRifle_G36C extends KFWeap_SMGBase;
simulated function ZoomIn(bool bAnimateTransition, float ZoomTimeToGo)
{
super.ZoomIn(bAnimateTransition, ZoomTimeToGo);
if (LaserSight != none)
{
LaserSight.ChangeVisibility(false);
}
}
simulated function ZoomOut( bool bAnimateTransition, float ZoomTimeToGo )
{
super.ZoomOut( bAnimateTransition, ZoomTimeToGo );
if (LaserSight != none)
{
LaserSight.ChangeVisibility(true);
}
}
defaultproperties
{
bHasFireLastAnims=true
BonesToLockOnEmpty=(RW_Bolt, RW_Charging_Handle)
// Shooting Animations
FireSightedAnims[0]=Shoot_Iron
FireSightedAnims[1]=Shoot_Iron2
FireSightedAnims[2]=Shoot_Iron3
// FOV
MeshFOV=70
MeshIronSightFOV=20
PlayerIronSightFOV=70
// Depth of field
DOF_FG_FocalRadius=150
DOF_FG_MaxNearBlurSize=3
// Zooming/Position
IronSightPosition=(X=40,Y=0.1,Z=-4.57)
PlayerViewOffset=(X=14,Y=11,Z=-5)
// Content
PackageKey="G36C"
FirstPersonMeshName="WEP_1P_G36C_MESH.Wep_1stP_G36C_Rig"
FirstPersonAnimSetNames(0)="WEP_1P_G36C_ANIM.Wep_1stP_G36C_Anim"
PickupMeshName="WEP_3P_G36C_MESH.Wep_G36C_Pickup"
AttachmentArchetypeName="WEP_G36C_ARCH.Wep_G36C_3P"
MuzzleFlashTemplateName="WEP_G36C_ARCH.Wep_G36C_MuzzleFlash"
LaserSightTemplate=KFLaserSightAttachment'FX_LaserSight_ARCH.LaserSight_WithAttachment_1P'
// Ammo
MagazineCapacity[0]=30
SpareAmmoCapacity[0]=450
InitialSpareMags[0]=3
bCanBeReloaded=true
bReloadFromMagazine=true
// Recoil
maxRecoilPitch=90
minRecoilPitch=80
maxRecoilYaw=80
minRecoilYaw=-80
RecoilRate=0.085
RecoilMaxYawLimit=500
RecoilMinYawLimit=65035
RecoilMaxPitchLimit=900
RecoilMinPitchLimit=65035
RecoilISMaxYawLimit=100
RecoilISMinYawLimit=65460
RecoilISMaxPitchLimit=350
RecoilISMinPitchLimit=65460
IronSightMeshFOVCompensationScale=4.0
// Old Recoil Data
// maxRecoilPitch=80
// minRecoilPitch=65
// maxRecoilYaw=60
// minRecoilYaw=-60
// RecoilRate=0.063
// RecoilMaxYawLimit=400
// RecoilMinYawLimit=65135
// RecoilMaxPitchLimit=800
// RecoilMinPitchLimit=65035
// RecoilISMaxYawLimit=150
// RecoilISMinYawLimit=65385
// RecoilISMaxPitchLimit=350
// RecoilISMinPitchLimit=65435
// IronSightMeshFOVCompensationScale=1.5
// Inventory
InventorySize=7
GroupPriority=100
WeaponSelectTexture=Texture2D'wep_ui_g36c_tex.UI_WeaponSelect_G36C'
// DEFAULT_FIREMODE
FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto'
FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring
WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_InstantHit
WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_AssaultRifle'
InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_G36C'
PenetrationPower(DEFAULT_FIREMODE)=4.0
FireInterval(DEFAULT_FIREMODE)=+0.08 // 750 RPM
Spread(DEFAULT_FIREMODE)=0.005
InstantHitDamage(DEFAULT_FIREMODE)=45.0
FireOffset=(X=30,Y=4.5,Z=-5)
// ALT_FIREMODE
FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle'
FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring
WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_InstantHit
WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_AssaultRifle'
InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_G36C'
PenetrationPower(ALTFIRE_FIREMODE)=4.0
FireInterval(ALTFIRE_FIREMODE)=+0.08 // 750 RPM
InstantHitDamage(ALTFIRE_FIREMODE)=45.0
Spread(ALTFIRE_FIREMODE)=0.005
// BASH_FIREMODE
InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_G36C'
InstantHitDamage(BASH_FIREMODE)=26
// Fire Effects
WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_Shoot_LP', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_Shoot_LP')
WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_Shoot_Single', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_Shoot_Single')
WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_SA_AK12.Play_WEP_SA_AK12_Handling_DryFire' //@TODO: Replace me
WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_SA_AK12.Play_WEP_SA_AK12_Handling_DryFire' //@TODO: Replace me
// WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_G36C.Play_WEP_G36C_Dry_Fire'
// WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_G36C.Play_WEP_G36C_Dry_Fire'
// Advanced (High RPM) Fire Effects
bLoopingFireAnim(DEFAULT_FIREMODE)=true
bLoopingFireSnd(DEFAULT_FIREMODE)=true
WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_3P_End_LP', FirstPersonCue=AkEvent'WW_WEP_G36C.Play_WEP_G36C_1P_End_LP')
SingleFireSoundIndex=ALTFIRE_FIREMODE
// Attachments
bHasIronSights=true
bHasFlashlight=false
bHasLaserSight=true
AssociatedPerkClasses(0)=class'KFPerk_Swat'
// Weapon Upgrade stat boosts
WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1)))
}

View File

@ -998,7 +998,7 @@ defaultproperties
// Zooming/Position
PlayerViewOffset = (X = 3.0, Y = 10, Z = -1)
IronSightPosition = (X = 0, Y = 0, Z = 0)
IronSightPosition = (X = 0, Y = 0.037, Z = 0.11)
// Ammo
MagazineCapacity[0] = 50

View File

@ -73,7 +73,7 @@ defaultproperties
DOF_FG_MaxNearBlurSize=2.5
// Zooming/Position
IronSightPosition=(X=10,Y=0,Z=0) //x20
IronSightPosition=(X=10,Y=-0.015,Z=0.09) //x20
PlayerViewOffset=(X=30.0,Y=10,Z=-2.5) //x18 y9 z0
// Content

Some files were not shown because too many files have changed in this diff Show More