From 28f1e3c001546635683714bea420f0bea6d5d946 Mon Sep 17 00:00:00 2001 From: GenZmeY Date: Tue, 2 Mar 2021 14:56:51 +0300 Subject: [PATCH] upload --- Engine/Classes/DamageType.uc | 4 +- Engine/Classes/GameInfo.uc | 16 + Engine/Classes/OnlineGameSettings.uc | 7 + Engine/Classes/OnlineSubsystem.uc | 1 + Engine/Classes/Pawn.uc | 9 + KFGame/Classes/KFAfflictionManager.uc | 9 +- KFGame/Classes/KFCharacterInfo_Human.uc | 6 +- KFGame/Classes/KFCheatManager.uc | 10 + ...cialEventObjectivesContainer_Spring2021.uc | 27 + KFGame/Classes/KFGFxHUD_PlayerStatus.uc | 14 + KFGame/Classes/KFGFxHUD_WaveInfo.uc | 7 +- KFGame/Classes/KFGFxMenu_Gear.uc | 1 - KFGame/Classes/KFGFxMenu_Perks.uc | 10 + .../Classes/KFGFxPerksContainer_Selection.uc | 4 +- KFGame/Classes/KFGFxServerBrowser_Filters.uc | 19 +- .../Classes/KFGFxServerBrowser_ServerList.uc | 2 + .../KFGFxStartGameContainer_FindGame.uc | 24 +- KFGame/Classes/KFGFxStoreContainer_Main.uc | 24 +- KFGame/Classes/KFGameInfo.uc | 31 +- KFGame/Classes/KFGameReplicationInfo.uc | 64 +- KFGame/Classes/KFGfxMenu_StartGame.uc | 4 +- KFGame/Classes/KFInventoryManager.uc | 4 +- KFGame/Classes/KFMapInfo.uc | 4 + KFGame/Classes/KFOnlineStatsReadDingo.uc | 2 + KFGame/Classes/KFOnlineStatsWrite.uc | 22 + KFGame/Classes/KFOnlineStatsWriteDingo.uc | 1 + KFGame/Classes/KFOutbreakEvent.uc | 126 +++- KFGame/Classes/KFPawn.uc | 7 +- KFGame/Classes/KFPawn_Human.uc | 160 ++++- KFGame/Classes/KFPawn_Monster.uc | 16 +- KFGame/Classes/KFPawn_MonsterBoss.uc | 2 + KFGame/Classes/KFPerk.uc | 52 +- KFGame/Classes/KFPerk_Berserker.uc | 116 +++- KFGame/Classes/KFPerk_Commando.uc | 14 +- KFGame/Classes/KFPerk_Demolitionist.uc | 4 +- KFGame/Classes/KFPerk_FieldMedic.uc | 4 +- KFGame/Classes/KFPerk_Firebug.uc | 2 + KFGame/Classes/KFPerk_Gunslinger.uc | 2 + KFGame/Classes/KFPerk_Sharpshooter.uc | 32 +- KFGame/Classes/KFPerk_Support.uc | 4 +- KFGame/Classes/KFPerk_Survivalist.uc | 17 +- KFGame/Classes/KFPerk_Swat.uc | 16 +- KFGame/Classes/KFPlayerController.uc | 105 +++ .../KFPowerUp_HellishRage_NoCostHeal.uc | 14 + .../KFProjectileStickHelper_HRGScorcher.uc | 8 +- KFGame/Classes/KFSeasonalEventStats.uc | 3 +- KFGame/Classes/KFUnlockManager.uc | 5 + KFGame/Classes/KFWeapDef_Bullpup.uc | 2 +- KFGame/Classes/KFWeapDef_GravityImploder.uc | 28 + KFGame/Classes/KFWeapDef_HRG_SonicGun.uc | 25 + KFGame/Classes/KFWeap_HealerBase.uc | 6 +- KFGame/Classes/KFWeaponSkinList.uc | 116 ++++ KFGame/Classes/KFZedArmorInfo.uc | 13 +- KFGame/KFOnlineStats.uci | 1 + .../KFDT_Ballistic_GravityImploderImpact.uc | 24 + ...KFDT_Ballistic_GravityImploderImpactAlt.uc | 23 + ...tic_HRG_SonicGun_SonicBlastFullyCharged.uc | 46 ++ ...stic_HRG_SonicGun_SonicBlastHalfCharged.uc | 46 ++ ...listic_HRG_SonicGun_SonicBlastUncharged.uc | 47 ++ .../Classes/KFDT_Bludgeon_GravityImploder.uc | 15 + .../Classes/KFDT_Bludgeon_HRG_SonicGun.uc | 16 + .../Classes/KFDT_Explosive_GravityImploder.uc | 33 + .../KFDT_Explosive_GravityImploderWave.uc | 29 + .../KFDT_Freeze_FreezeThrower_IceShards.uc | 6 +- .../Classes/KFDT_Piercing_Crossbow.uc | 7 +- .../Classes/KFExplosion_GravityImplosion.uc | 15 + KFGameContent/Classes/KFGameInfo_Survival.uc | 71 +- .../Classes/KFGameInfo_WeeklySurvival.uc | 194 +++++- .../Classes/KFOutbreakEvent_Weekly.uc | 99 ++- KFGameContent/Classes/KFPawn_ZedFleshpound.uc | 4 +- .../Classes/KFPawn_ZedFleshpoundKing.uc | 2 +- .../Classes/KFPawn_ZedFleshpoundMini.uc | 6 +- KFGameContent/Classes/KFPawn_ZedMatriarch.uc | 3 + .../Classes/KFProj_BrokenFlare_HRGScorcher.uc | 18 + .../Classes/KFProj_Cannonball_Blunderbuss.uc | 66 +- .../Classes/KFProj_Grenade_GravityImploder.uc | 188 ++++++ .../KFProj_Grenade_GravityImploderAlt.uc | 584 +++++++++++++++++ .../KFProj_LightingFlare_HRGScorcher.uc | 28 +- .../Classes/KFProj_Mine_Reconstructor.uc | 3 +- ...roj_SonicBlastFullyCharged_HRG_SonicGun.uc | 55 ++ ...Proj_SonicBlastHalfCharged_HRG_SonicGun.uc | 113 ++++ ...KFProj_SonicBlastUncharged_HRG_SonicGun.uc | 117 ++++ .../KFSeasonalEventStats_Spring2021.uc | 140 ++++ .../Classes/KFWeapAttach_GravityImploder.uc | 54 ++ .../Classes/KFWeap_AssaultRifle_Bullpup.uc | 8 +- KFGameContent/Classes/KFWeap_Bow_Crossbow.uc | 18 + .../Classes/KFWeap_GravityImploder.uc | 187 ++++++ KFGameContent/Classes/KFWeap_HRG_SonicGun.uc | 613 ++++++++++++++++++ .../Classes/KFWeap_Ice_FreezeThrower.uc | 16 +- .../Classes/KFWeap_Shotgun_DoubleBarrel.uc | 7 + .../Classes/KFWeap_Shotgun_ElephantGun.uc | 14 +- .../OnlineMarketplaceInterfaceDingo.uc | 4 +- WebAdmin/Classes/AdminCommandHandler.uc | 5 + WebAdmin/Classes/QHCurrent.uc | 76 ++- WebAdmin/Classes/QHDefaults.uc | 4 +- 95 files changed, 3970 insertions(+), 260 deletions(-) create mode 100644 KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Spring2021.uc create mode 100644 KFGame/Classes/KFPowerUp_HellishRage_NoCostHeal.uc create mode 100644 KFGame/Classes/KFWeapDef_GravityImploder.uc create mode 100644 KFGame/Classes/KFWeapDef_HRG_SonicGun.uc create mode 100644 KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpact.uc create mode 100644 KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpactAlt.uc create mode 100644 KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged.uc create mode 100644 KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged.uc create mode 100644 KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged.uc create mode 100644 KFGameContent/Classes/KFDT_Bludgeon_GravityImploder.uc create mode 100644 KFGameContent/Classes/KFDT_Bludgeon_HRG_SonicGun.uc create mode 100644 KFGameContent/Classes/KFDT_Explosive_GravityImploder.uc create mode 100644 KFGameContent/Classes/KFDT_Explosive_GravityImploderWave.uc create mode 100644 KFGameContent/Classes/KFExplosion_GravityImplosion.uc create mode 100644 KFGameContent/Classes/KFProj_Grenade_GravityImploder.uc create mode 100644 KFGameContent/Classes/KFProj_Grenade_GravityImploderAlt.uc create mode 100644 KFGameContent/Classes/KFProj_SonicBlastFullyCharged_HRG_SonicGun.uc create mode 100644 KFGameContent/Classes/KFProj_SonicBlastHalfCharged_HRG_SonicGun.uc create mode 100644 KFGameContent/Classes/KFProj_SonicBlastUncharged_HRG_SonicGun.uc create mode 100644 KFGameContent/Classes/KFSeasonalEventStats_Spring2021.uc create mode 100644 KFGameContent/Classes/KFWeapAttach_GravityImploder.uc create mode 100644 KFGameContent/Classes/KFWeap_GravityImploder.uc create mode 100644 KFGameContent/Classes/KFWeap_HRG_SonicGun.uc diff --git a/Engine/Classes/DamageType.uc b/Engine/Classes/DamageType.uc index 5ab9b4f..1094343 100644 --- a/Engine/Classes/DamageType.uc +++ b/Engine/Classes/DamageType.uc @@ -13,7 +13,8 @@ class DamageType extends object native abstract; -var() bool bArmorStops; // does regular armor provide protection against this damage +var() bool bArmorStops; // does regular armor provide protection against this damage (only affects KFPawn_Human) +var float ArmorDamageModifier; // modifier for armor damage (only affects KFPawn_Monster) var bool bCausedByWorld; //this damage was caused by the world (falling off level, into lava, etc) var bool bExtraMomentumZ; // Add extra Z to momentum on walking pawns to throw them up into the air @@ -54,6 +55,7 @@ static function float VehicleDamageScalingFor(Vehicle V) defaultproperties { bArmorStops=true + ArmorDamageModifier=1 KDamageImpulse=800 VehicleDamageScaling=+1.0 VehicleMomentumScaling=+1.0 diff --git a/Engine/Classes/GameInfo.uc b/Engine/Classes/GameInfo.uc index 569f40c..e565cb2 100644 --- a/Engine/Classes/GameInfo.uc +++ b/Engine/Classes/GameInfo.uc @@ -2173,6 +2173,22 @@ function Logout( Controller Exiting ) } } +simulated function ExileServerUsingKickBan() +{ + local OnlineGameSettings GameSettings; + + if (GameInterface != None) + { + GameSettings = GameInterface.GetGameSettings(PlayerReplicationInfoClass.default.SessionName); + } + + if (GameSettings != None) + { + GameSettings.bServerExiled = true; + } + +} + /** * Removes the player from the named session when they leave * diff --git a/Engine/Classes/OnlineGameSettings.uc b/Engine/Classes/OnlineGameSettings.uc index c44ee26..4fa2d2f 100644 --- a/Engine/Classes/OnlineGameSettings.uc +++ b/Engine/Classes/OnlineGameSettings.uc @@ -115,6 +115,10 @@ var databinding int BotPlayers; var databinding string SteamServerUID; //@SABER_EGS_END +//@SABER_BEGIN "Exiling" servers which kicks/bans +var databinding bool bServerExiled; +//@SABER_END + `if (`__TW_ONLINESUBSYSTEM_) //used to keep track of the gfx objects in the serverbrowser's list @@ -176,4 +180,7 @@ defaultproperties //@SABER_EGS_BEGIN Crossplay support BotPlayers=0 //@SABER_EGS_END + //@SABER_BEGIN "Exiling" servers which kicks/bans + bServerExiled=false + //@SABER_END } \ No newline at end of file diff --git a/Engine/Classes/OnlineSubsystem.uc b/Engine/Classes/OnlineSubsystem.uc index 49a2182..0a9e94e 100644 --- a/Engine/Classes/OnlineSubsystem.uc +++ b/Engine/Classes/OnlineSubsystem.uc @@ -2301,6 +2301,7 @@ static function DumpGameSettings(const OnlineGameSettings GameSettings) `Log(" bIsLanMatch: "$GameSettings.bIsLanMatch); `Log(" bIsDedicated: "$GameSettings.bIsDedicated); `Log(" bUsesStats: "$GameSettings.bUsesStats); + `Log(" bServerExiled: "$GameSettings.bServerExiled); `Log(" bUsesArbitration: "$GameSettings.bUsesArbitration); `Log(" bAntiCheatProtected: "$GameSettings.bAntiCheatProtected); `Log(" bShouldAdvertise: "$GameSettings.bShouldAdvertise); diff --git a/Engine/Classes/Pawn.uc b/Engine/Classes/Pawn.uc index 6c8ddda..e5dceca 100644 --- a/Engine/Classes/Pawn.uc +++ b/Engine/Classes/Pawn.uc @@ -2596,10 +2596,17 @@ 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) { @@ -2619,6 +2626,8 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector `endif } +function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class DamageType, Actor DamageCauser); + /* * Queries the PRI and returns our current team index. */ diff --git a/KFGame/Classes/KFAfflictionManager.uc b/KFGame/Classes/KFAfflictionManager.uc index ece691d..0b47291 100644 --- a/KFGame/Classes/KFAfflictionManager.uc +++ b/KFGame/Classes/KFAfflictionManager.uc @@ -9,6 +9,8 @@ class KFAfflictionManager extends Object within KFPawn native(Pawn); +const STUN_GUARANTEED_POWER = 10000.f; + /** Abstracted body parts that can be associated with multiple zones */ enum EHitZoneBodyPart { @@ -246,11 +248,12 @@ protected function ProcessSpecialMoveAfflictions(KFPerk InstigatorPerk, vector H StumblePower *= StumbleModifier; StunPower *= StunModifier; - // [FFERRANDO @ SABER3D] INCAP MASTER NOW MODIFIES THE STUN POWER BY SETTING IT TO THE GIVEN VALUE - if (InstigatorPerk != None && InstigatorPerk.GetIncapMasterActive()) + // [RMORENO @ SABER3D] //Overriding stun power with a High number so we can assure the stun independently of weapon, Zed resistances, body part hit. This does NOT ignores other factors like cooldowns. + if (InstigatorPerk != None && InstigatorPerk.IsStunGuaranteed( DamageType, HitZoneIdx )) { - StunPower += InstigatorPerk.GetStunPowerModifier( DamageType, HitZoneIdx ); + StunPower = STUN_GUARANTEED_POWER; } + // increment affliction power if (KnockdownPower > 0 && CanDoSpecialmove(SM_Knockdown)) { diff --git a/KFGame/Classes/KFCharacterInfo_Human.uc b/KFGame/Classes/KFCharacterInfo_Human.uc index b149919..a36b00b 100644 --- a/KFGame/Classes/KFCharacterInfo_Human.uc +++ b/KFGame/Classes/KFCharacterInfo_Human.uc @@ -310,7 +310,7 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic { local int AttachmentIdx, CosmeticMeshIdx; local bool bMaskHeadMesh; - local int NumberOfCosmetics, NumberOfCosmeticsPostRemoval; + //local int NumberOfCosmetics, NumberOfCosmeticsPostRemoval; super.SetCharacterMeshFromArch( KFP, KFPRI ); @@ -356,7 +356,7 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic CosmeticMeshIdx = KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx]; if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE) { - NumberOfCosmetics++; + //NumberOfCosmetics++; bMaskHeadMesh = bMaskHeadMesh || CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh; // Attach all saved attachments to the character @@ -878,7 +878,7 @@ private function SetAttachmentMeshAndSkin( * Removes any attachments that exist in the same socket or have overriding cases * Network: Local Player */ -function array DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI, optional out array out_RemovedAttachments ) +function DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI, optional out array out_RemovedAttachments ) { local name NewAttachmentSocketName; local int i, CurrentAttachmentIdx; diff --git a/KFGame/Classes/KFCheatManager.uc b/KFGame/Classes/KFCheatManager.uc index 05f1a65..1d84007 100644 --- a/KFGame/Classes/KFCheatManager.uc +++ b/KFGame/Classes/KFCheatManager.uc @@ -929,6 +929,15 @@ simulated exec function Vampire() GiveWeapon( "KFGameContent.KFWeap_HRG_Vampire" ); } +/** + * Give the player the HRG SonicGun + */ +simulated exec function SonicGun() +{ + GiveWeapon( "KFGameContent.KFWeap_HRG_SonicGun" ); +} + + /** * Give the player all pistol weapons */ @@ -1177,6 +1186,7 @@ exec function Surv() GiveWeapon( "KFGameContent.KFWeap_HRG_EMP_ArcGenerator" ); GiveWeapon( "KFGameContent.KFWeap_Ice_FreezeThrower" ); GiveWeapon( "KFGameContent.KFWeap_AssaultRifle_LazerCutter" ); + GiveWeapon( "KFGameContent.KFWeap_HRG_SonicGun" ); } /** diff --git a/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Spring2021.uc b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Spring2021.uc new file mode 100644 index 0000000..1de446e --- /dev/null +++ b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Spring2021.uc @@ -0,0 +1,27 @@ +class KFGFxSpecialEventObjectivesContainer_Spring2021 extends KFGFxSpecialEventObjectivesContainer; + +function Initialize(KFGFxObject_Menu NewParentMenu) +{ + super.Initialize(NewParentMenu); +} + +DefaultProperties +{ + ObjectiveIconURLs[0] = "Spring2021_UI.UI_Objectives_Spring2021_Cyber_Threat" // Kill 15 Bosses on any map or mode + ObjectiveIconURLs[1] = "Spring2021_UI.UI_Objectives_Spring2021_Weekly_Hack" // Complete the Weekly on Dystopia 2029 + ObjectiveIconURLs[2] = "Spring2021_UI.UI_Objectives_Spring2021_AI_Out_of_Control" // Kill 100 E.D.A.R.s on Dystopia 2029 + ObjectiveIconURLs[3] = "Spring2021_UI.UI_Objectives_Spring2021_Not_a_Simulation" // Complete a wave without taking any damage 10 times on Dystopia 2029 + ObjectiveIconURLs[4] = "Spring2021_UI.UI_Objectives_Spring2021_Zed_World" // Complete wave 15 on Endless Hard or higher difficulty on Dystopia 2029 + + //defaults + AllCompleteRewardIconURL="CHR_CosmeticSet_Spring_01_Item_TEX.cyborg_companionbackpack.cyborgcompanionbackpack_precious" + ChanceDropIconURLs[0]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket" + ChanceDropIconURLs[1]="CHR_CosmeticSet14_Item_TEX.Tickets.CyberPunk_ticket_golden" + IconURL="Spring2021_UI.KF2_Spring_DystopianDevastation_SmallLogo" + + UsesProgressList[0] = true + UsesProgressList[1] = false + UsesProgressList[2] = true + UsesProgressList[3] = true + UsesProgressList[4] = false +} \ No newline at end of file diff --git a/KFGame/Classes/KFGFxHUD_PlayerStatus.uc b/KFGame/Classes/KFGFxHUD_PlayerStatus.uc index 2d1b4b3..9e510a0 100644 --- a/KFGame/Classes/KFGFxHUD_PlayerStatus.uc +++ b/KFGame/Classes/KFGFxHUD_PlayerStatus.uc @@ -12,6 +12,7 @@ class KFGFxHUD_PlayerStatus extends GFxObject; /** Cached KFPlayerController */ var KFPlayerController MyPC; +var KFGameReplicationinfo KFGRI; var KFPawn_Human MyHumanPawn; var KFInventoryManager MyInventoryManager; // Player's perk type as of the last tick. @@ -46,6 +47,7 @@ function TickHud(float DeltaTime) UpdateHealth(); UpdateArmor(); UpdateHealer(); + UpdateGlobalDamage(); } function ShowActiveIndicators( array IconPathStrings ) @@ -213,6 +215,18 @@ function ShowXPBark( int DeltaXP, string iconPath, bool bIsCurrentPerk ) ActionScriptVoid("showXPBark"); } +function UpdateGlobalDamage() +{ + if(KFGRI == none) + { + KFGRI = KFGameReplicationInfo(GetPC().WorldInfo.GRI); + } + else + { + SetBool("waveApplyingDamage", KFGRI.IsGlobalDamage()); + } +} + DefaultProperties { diff --git a/KFGame/Classes/KFGFxHUD_WaveInfo.uc b/KFGame/Classes/KFGFxHUD_WaveInfo.uc index 5ce2403..32804d2 100644 --- a/KFGame/Classes/KFGFxHUD_WaveInfo.uc +++ b/KFGame/Classes/KFGFxHUD_WaveInfo.uc @@ -12,6 +12,7 @@ class KFGFxHUD_WaveInfo extends GFxObject; /** Cached KFPlayerController */ var KFGameReplicationinfo KFGRI; + // var int LastWaveMax; // @@ -50,10 +51,10 @@ function TickHud(float DeltaTime) { if (KFGRI.bWaveIsActive && !KFGRI.bWaveStarted) { - SetString("waitingForWaveStart", "-----"); + SetString("waitingForWaveStart", "-----"); } else if (!KFGRI.bWaveIsActive) - { + { UpdateTraderTimeRemaining(); } else @@ -82,7 +83,6 @@ function UpdateWaveCount() return; } - // Max # of waves. CurrentWaveMax = KFGRI.GetFinalWaveNum(); if(LastWaveMax != CurrentWaveMax) @@ -156,7 +156,6 @@ function UpdateTraderTimeRemaining() } } - DefaultProperties { LastTraderTimeRemaining=0 diff --git a/KFGame/Classes/KFGFxMenu_Gear.uc b/KFGame/Classes/KFGFxMenu_Gear.uc index 9117d7d..9a82aa6 100644 --- a/KFGame/Classes/KFGFxMenu_Gear.uc +++ b/KFGame/Classes/KFGFxMenu_Gear.uc @@ -697,7 +697,6 @@ private function Callback_AttachmentNumbered(int MeshIndex, int SkinIndex, int S { local Pawn P; local KFPawn KFP; - local int i; local array RemovedAttachments; P = GetPC().Pawn; if( P != none ) diff --git a/KFGame/Classes/KFGFxMenu_Perks.uc b/KFGame/Classes/KFGFxMenu_Perks.uc index 7c125f2..eba6ff5 100644 --- a/KFGame/Classes/KFGFxMenu_Perks.uc +++ b/KFGame/Classes/KFGFxMenu_Perks.uc @@ -224,8 +224,18 @@ function bool IsMatchStarted() function PerkChanged( byte NewPerkIndex, bool bClickedIndex) { + local KFGameReplicationInfo KFGRI; + if( KFPC != none ) { + KFGRI = KFGameReplicationInfo( KFPC.WorldInfo.GRI ); + + // If the perk is not allowed stop the change process + if( KFGRI != none && !KFGRI.IsPerkAllowed(KFPC.PerkList[NewPerkIndex].PerkClass) ) + { + return; + } + // We aren't actually changing our selected perk so don't save stuff. UpdateSkillsHolder( KFPC.PerkList[NewPerkIndex].PerkClass ); diff --git a/KFGame/Classes/KFGFxPerksContainer_Selection.uc b/KFGame/Classes/KFGFxPerksContainer_Selection.uc index 8ae0ebf..fa7038b 100644 --- a/KFGame/Classes/KFGFxPerksContainer_Selection.uc +++ b/KFGame/Classes/KFGFxPerksContainer_Selection.uc @@ -86,7 +86,7 @@ function UpdatePerkSelection(byte SelectedPerkIndex) TempObj.SetString( "Title", PerkClass.default.PerkName ); TempObj.SetString( "iconSource", "img://"$PerkClass.static.GetPerkIconPath() ); TempObj.SetBool("bTierUnlocked", bool(bTierUnlocked) && KFPC.PerkList[i].PerkLevel >= UnlockedPerkLevel); - + TempObj.SetBool("bPerkAllowed", true); DataProvider.SetElementObject( i, TempObj ); } SetObject( "perkData", DataProvider ); @@ -111,7 +111,7 @@ function UpdatePendingPerkInfo(byte SelectedPerkIndex) local KFPlayerController KFPC; KFPC = KFPlayerController( GetPC() ); - + if( KFPC != none && KFGRI != none ) { if(!class'WorldInfo'.static.IsMenuLevel()) diff --git a/KFGame/Classes/KFGFxServerBrowser_Filters.uc b/KFGame/Classes/KFGFxServerBrowser_Filters.uc index 372a5ac..6e891b7 100644 --- a/KFGame/Classes/KFGFxServerBrowser_Filters.uc +++ b/KFGame/Classes/KFGFxServerBrowser_Filters.uc @@ -13,13 +13,13 @@ class KFGFxServerBrowser_Filters extends KFGFxObject_Container config(UI); var KFGFxMenu_ServerBrowser ServerMenu; -var localized string NoPasswordString, NoMutatorsString, NotFullString, NotEmptyString, NoRankedStandardString, NoRankedCustomString, NoUnrankedString, DedicatedString, VACSecureString, InLobbyString, InProgressString, OnlyStockMapsString, OnlyCustomMapsString, LimitServerResultsString; +var localized string NoPasswordString, NoMutatorsString, NotFullString, NotEmptyString, NoRankedStandardString, NoRankedCustomString, NoUnrankedString, DedicatedString, VACSecureString, InLobbyString, InProgressString, OnlyStockMapsString, OnlyCustomMapsString, LimitServerResultsString, NotServerExiledString; var array FilterStrings; -var config Bool bNoPassword, bNoMutators, bNotFull, bNotEmpty, bUsesStats, bCustom, bDedicated, bVAC_Secure, bInLobby, bInProgress, bOnlyStockMaps, bOnlyCustomMaps, bLimitServerResults; +var config Bool bNoPassword, bNoMutators, bNotFull, bNotEmpty, bUsesStats, bCustom, bDedicated, bVAC_Secure, bInLobby, bInProgress, bOnlyStockMaps, bOnlyCustomMaps, bLimitServerResults, bNoLocalAdmin; var config byte SavedGameModeIndex, SavedMapIndex, SavedDifficultyIndex, SavedLengthIndex, SavedPingIndex; -var Bool bNoPasswordPending, bNoMutatorsPending, bNotFullPending, bNotEmptyPending, bUsesStatsPending, bCustomPending, bDedicatedPending, bVAC_SecurePending, bInLobbyPending, bInProgressPending, bOnlyStockMapsPending, bOnlyCustomMapsPending, bLimitServerResultsPending; +var Bool bNoPasswordPending, bNoMutatorsPending, bNotFullPending, bNotEmptyPending, bUsesStatsPending, bCustomPending, bDedicatedPending, bVAC_SecurePending, bInLobbyPending, bInProgressPending, bOnlyStockMapsPending, bOnlyCustomMapsPending, bLimitServerResultsPending, bNoLocalAdminPending; var byte SavedGameModeIndexPending, SavedMapIndexPending, SavedDifficultyIndexPending, SavedLengthIndexPending, SavedPingIndexPending; var transient string CachedMapName, CachedModeName; @@ -45,6 +45,7 @@ enum EFilter_Key LIMIT_SERVER_RESULTS, /*ONLY_STOCK_MAPS, //Not using for EA ONLY_CUSTOM_MAPS,*/ //Not using for EA + NO_LOCAL_ADMIN, FILTERS_MAX, }; @@ -115,6 +116,7 @@ function InitFiltersArray() FilterStrings[IN_LOBBY] = InLobbyString; FilterStrings[IN_PROGRESS] = InProgressString; FilterStrings[LIMIT_SERVER_RESULTS] = LimitServerResultsString @class'KFGFxServerBrowser_ServerList'.default.MaxSearchResults; + FilterStrings[NO_LOCAL_ADMIN] = NotServerExiledString; /*FilterStrings[ONLY_STOCK_MAPS] = OnlyStockMapsString; FilterStrings[ONLY_CUSTOM_MAPS] = OnlyCustomMapsString;*/ } @@ -316,6 +318,7 @@ function ApplyFilters() bOnlyStockMaps = bOnlyStockMapsPending; bOnlyCustomMaps = bOnlyCustomMapsPending; bLimitServerResults = bLimitServerResultsPending; + bNoLocalAdmin = bNoLocalAdminPending; SavedGameModeIndex = SavedGameModeIndexPending; SavedMapIndex = SavedMapIndexPending; @@ -340,7 +343,8 @@ function ClearPendingValues() bInProgressPending = bInProgress; bOnlyStockMapsPending = bOnlyStockMaps; bOnlyCustomMapsPending = bOnlyCustomMaps; - bLimitServerResultsPending = bLimitServerResults; + bLimitServerResultsPending = bLimitServerResults; + bNoLocalAdminPending = bNoLocalAdmin; SavedGameModeIndexPending = SavedGameModeIndex; SavedMapIndexPending = SavedMapIndex; SavedDifficultyIndexPending = SavedDifficultyIndex; @@ -364,6 +368,7 @@ function ResetFilters() bOnlyStockMaps = false; bOnlyCustomMaps = false; bLimitServerResults = true; + bNoLocalAdmin = true; SavedGameModeIndex = 255; SavedMapIndex = 255; @@ -420,6 +425,9 @@ function SetBoolByEFilter_Key(EFilter_Key Filter, bool FilterValue) case LIMIT_SERVER_RESULTS: bLimitServerResultsPending = FilterValue; break; + case NO_LOCAL_ADMIN: + bNoLocalAdminPending = FilterValue; + break; /*case ONLY_STOCK_MAPS: bOnlyStockMapsPending = FilterValue; break; @@ -467,6 +475,9 @@ function bool GetBoolByEFilter_Key(EFilter_Key Filter) case LIMIT_SERVER_RESULTS: return bLimitServerResults; + + case NO_LOCAL_ADMIN: + return bNoLocalAdmin; /*case ONLY_STOCK_MAPS: return bOnlyStockMaps; diff --git a/KFGame/Classes/KFGFxServerBrowser_ServerList.uc b/KFGame/Classes/KFGFxServerBrowser_ServerList.uc index ad78fde..22c747f 100644 --- a/KFGame/Classes/KFGFxServerBrowser_ServerList.uc +++ b/KFGame/Classes/KFGFxServerBrowser_ServerList.uc @@ -278,6 +278,7 @@ function BuildServerFilters(KFGFxServerBrowser_Filters Filters, OnlineGameSearch Search.AddServerFilter("version_match", string(class'KFGameEngine'.static.GetKFGameVersion())); Search.TestAddServerFilter( Filters.bNotFull, "notfull"); Search.TestAddServerFilter( Filters.bNotEmpty, "hasplayers"); + Search.TestAddBoolGametagFilter(GametagSearch, Filters.bNoLocalAdmin, 'bServerExiled', 0); if( !class'WorldInfo'.static.IsConsoleBuild() ) { @@ -972,6 +973,7 @@ function UpdateListDataProvider() TempObj.SetString("mode", class'KFCommon_LocalizedStrings'.static.GetGameModeString(TempOnlineGamesSettings.Mode) ); TempObj.SetString("map", TempOnlineGamesSettings.MapName); TempObj.SetBool("locked", TempOnlineGamesSettings.bRequiresPassword); + TempObj.SetBool("serverExiled", TempOnlineGamesSettings.bServerExiled); //Get Game State from var const databinding EOnlineGameState GameState; TempObj.SetString("gameStatus", String(TempOnlineGamesSettings.GameState)); diff --git a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc index 781b69f..7cc800d 100644 --- a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc +++ b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc @@ -175,22 +175,28 @@ function FillWhatsNew() local SWhatsNew item; WhatsNewItems.Remove(0, WhatsNewItems.Length); // Latest Update - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_ChristmasBreakdown_Event", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_DystopianDevastation_Event", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/"); + WhatsNewItems.AddItem(item); +// KF2 Armory Season Pass 2021 + 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 Time Limited Item - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/5588"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/5803"); WhatsNewItems.AddItem(item); // Featured Weapon Skin Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Xmas_IceBreaker", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8616"); - WhatsNewItems.AddItem(item); -// Featured Weapon Skin Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_Spectre", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8618"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_Neon_MKVII", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8774"); WhatsNewItems.AddItem(item); // Featured Cosmetic Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Winter","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/8617"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_Paratrooper","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/8775"); + WhatsNewItems.AddItem(item); +// Featured Cosmetic Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_DystopianDevastation", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8773"); + WhatsNewItems.AddItem(item); +// Featured Cosmetic Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_Chemical", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8776"); WhatsNewItems.AddItem(item); // Featured Weapon Bundle - item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_FrostGun", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8619"); + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_GravityImploder", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8777"); WhatsNewItems.AddItem(item); // Misc Community Links item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityHub", "Jaegorhorn", "https://steamcommunity.com/app/232090"); @@ -199,7 +205,7 @@ function FillWhatsNew() WhatsNewItems.AddItem(item); item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Survey", "Survey", "http://www.tripwireinteractive.com/redirect/KF2Survey/"); WhatsNewItems.AddItem(item); - item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityIssue", "CommunityTracker", "https://trello.com/b/ZOwMRlcW/killing-floor-2-community-issue-roadmap"); + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityIssue", "CommunityTracker", "http://www.killingfloor2.com/roadmap"); WhatsNewItems.AddItem(item); item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Merch", "Merch", "http://www.tripwireinteractive.com/redirect/shop/"); WhatsNewItems.AddItem(item); diff --git a/KFGame/Classes/KFGFxStoreContainer_Main.uc b/KFGame/Classes/KFGFxStoreContainer_Main.uc index bb6cc77..f92bded 100644 --- a/KFGame/Classes/KFGFxStoreContainer_Main.uc +++ b/KFGame/Classes/KFGFxStoreContainer_Main.uc @@ -446,19 +446,19 @@ DefaultProperties XboxFilterExceptions[0]="Wasteland Bundle" // Wasteland Outfit Bundle - FeaturedItemIDs[0]=7944 - FeaturedItemIDs[1]=8615 - FeaturedItemIDs[2]=8616 - FeaturedItemIDs[3]=8617 - FeaturedItemIDs[4]=8618 - FeaturedItemIDs[5]=8619 + FeaturedItemIDs[0]=8115 + FeaturedItemIDs[1]=8773 + FeaturedItemIDs[2]=8774 + FeaturedItemIDs[3]=8775 + FeaturedItemIDs[4]=8776 + FeaturedItemIDs[5]=8777 - ConsoleFeaturedItemIDs[0]=7947 - ConsoleFeaturedItemIDs[1]=8615 - ConsoleFeaturedItemIDs[2]=8616 - ConsoleFeaturedItemIDs[3]=8617 - ConsoleFeaturedItemIDs[4]=8618 - ConsoleFeaturedItemIDs[5]=8619 + ConsoleFeaturedItemIDs[0]=8116 + ConsoleFeaturedItemIDs[1]=8773 + ConsoleFeaturedItemIDs[2]=8774 + ConsoleFeaturedItemIDs[3]=8775 + ConsoleFeaturedItemIDs[4]=8776 + ConsoleFeaturedItemIDs[5]=8777 MaxFeaturedItems=5 } \ No newline at end of file diff --git a/KFGame/Classes/KFGameInfo.uc b/KFGame/Classes/KFGameInfo.uc index a4dc12f..a157072 100644 --- a/KFGame/Classes/KFGameInfo.uc +++ b/KFGame/Classes/KFGameInfo.uc @@ -1165,8 +1165,14 @@ function ResetAllPickups() AllPickupFactories.AddItem( AmmoPickups[i] ); } - ResetPickups( ItemPickups, NumWeaponPickups ); - ResetPickups( AmmoPickups, NumAmmoPickups ); + if(NumWeaponPickups > 0 ) + { + ResetPickups( ItemPickups, NumWeaponPickups ); + } + if(NumAmmoPickups > 0) + { + ResetPickups( AmmoPickups, NumAmmoPickups ); + } } /** Pick random pickup items to enable and put all others to sleep */ @@ -1632,12 +1638,24 @@ function bool AllowPrimaryWeapon(string ClassPath) return true; } +/** Whether or not a specific secondary weapon is allowed. Called at player spawn time while setting inventory. */ +function bool AllowSecondaryWeapon(string ClassPath) +{ + return true; +} + /** Allows gametype to adjust starting grenade count. Called at player spawn time from GiveInitialGrenadeCount in the inventory. */ function int AdjustStartingGrenadeCount(int CurrentCount) { return CurrentCount; } +/** Allows gametype to validate a perk for the current match */ +function bool IsPerkAllowed(class PerkClass) +{ + return true; +} + /************************************************************************************ * @name Difficulty Scaling ***********************************************************************************/ @@ -2719,7 +2737,14 @@ function CheckZedTimeOnKill(Controller Killer, Controller KilledPlayer, Pawn Kil // Handle monster/zed kills - increased probability if closer to the player if( Killer != none && Killer.Pawn != none && VSizeSq(Killer.Pawn.Location - KilledPawn.Location) < 90000 ) // 3 meters { - DramaticEvent(0.05); + if(OutbreakEvent != none && Role == ROLE_Authority && OutbreakEvent.ActiveEvent.bModifyZedTimeOnANearZedKill) + { + DramaticEvent(OutbreakEvent.ActiveEvent.ZedTimeOnANearZedKill); + } + else + { + DramaticEvent(0.05); + } } else { diff --git a/KFGame/Classes/KFGameReplicationInfo.uc b/KFGame/Classes/KFGameReplicationInfo.uc index fc58696..67ec017 100644 --- a/KFGame/Classes/KFGameReplicationInfo.uc +++ b/KFGame/Classes/KFGameReplicationInfo.uc @@ -77,6 +77,25 @@ var bool bMatchVictory; //Whether or not traders are enabled var bool bTradersEnabled; +struct native PerkAvailableData +{ + var bool bPerksAvailableLimited; + + var bool bBerserkerAvailable; + var bool bCommandoAvailable; + var bool bSupportAvailable; + var bool bFieldMedicAvailable; + var bool bDemolitionistAvailable; + var bool bFirebugAvailable; + var bool bGunslingerAvailable; + var bool bSharpshooterAvailable; + var bool bSwatAvailable; + var bool bSurvivalistAvailable; +}; + +//Wheter or not some perks are not allowed +var repnotify PerkAvailableData PerksAvailableData; + /************************************ * Spawning ************************************/ @@ -275,6 +294,10 @@ var float VersusZedDamageMod; /** The current game is a versus game */ var bool bVersusGame; +/** The current game has global damage*/ +var bool bGlobalDamage; + + /************************************ * Team Management ************************************/ @@ -350,11 +373,13 @@ cpptext replication { if ( bNetDirty ) - TraderVolume, TraderVolumeCheckType, bTraderIsOpen, NextTrader, WaveNum, bWaveIsEndless, AIRemaining, WaveTotalAICount, bWaveIsActive, MaxHumanCount, + TraderVolume, TraderVolumeCheckType, bTraderIsOpen, NextTrader, WaveNum, bWaveIsEndless, AIRemaining, WaveTotalAICount, bWaveIsActive, MaxHumanCount, bGlobalDamage, CurrentObjective, PreviousObjective, PreviousObjectiveResult, PreviousObjectiveXPResult, PreviousObjectiveVoshResult, MusicIntensity, ReplicatedMusicTrackInfo, MusicTrackRepCount, bIsUnrankedGame, GameSharedUnlocks, bHidePawnIcons, ConsoleGameSessionGuid, GameDifficulty, GameDifficultyModifier, BossIndex, bWaveStarted, NextObjective; //@HSL - JRO - 3/21/2016 - PS4 Sessions if ( bNetInitial ) GameLength, WaveMax, bCustom, bVersusGame, TraderItems, GameAmmoCostScale, bAllowGrenadePurchase, MaxPerkLevel, bTradersEnabled; + if ( bNetInitial || bNetDirty ) + PerksAvailableData; if ( bNetInitial && Role == ROLE_Authority ) ServerAdInfo; @@ -492,6 +517,10 @@ simulated event ReplicatedEvent(name VarName) { ReceivedGameLength(); } + else if(VarName == nameof(PerksAvailableData)) + { + UpdatePerksAvailable(); + } else { super.ReplicatedEvent(VarName); @@ -2108,6 +2137,39 @@ simulated function bool IsObjectiveMode() return false; } +function SetGlobalDamage(bool bEnable) +{ + bGlobalDamage = bEnable; +} + +simulated function bool IsGlobalDamage() +{ + return bGlobalDamage; +} + +simulated function bool IsPerkAllowed(class PerkClass) +{ + if(PerksAvailableData.bPerksAvailableLimited) + { + if(PerkClass == class'KFPerk_Berserker') return PerksAvailableData.bBerserkerAvailable; + else if(PerkClass == class'KFPerk_Commando') return PerksAvailableData.bCommandoAvailable; + else if(PerkClass == class'KFPerk_Support') return PerksAvailableData.bSupportAvailable; + else if(PerkClass == class'KFPerk_FieldMedic') return PerksAvailableData.bFieldMedicAvailable; + else if(PerkClass == class'KFPerk_Demolitionist') return PerksAvailableData.bDemolitionistAvailable; + else if(PerkClass == class'KFPerk_Firebug') return PerksAvailableData.bFirebugAvailable; + else if(PerkClass == class'KFPerk_Gunslinger') return PerksAvailableData.bGunslingerAvailable; + else if(PerkClass == class'KFPerk_Sharpshooter') return PerksAvailableData.bSharpshooterAvailable; + else if(PerkClass == class'KFPerk_Swat') return PerksAvailableData.bSwatAvailable; + else if(PerkClass == class'KFPerk_Survivalist') return PerksAvailableData.bSurvivalistAvailable; + } + return true; +} + +simulated function UpdatePerksAvailable() +{ + KFPlayerController(GetALocalPlayerController()).UpdatePerkOnInit(); +} + defaultproperties { TraderItemsPath="GP_Trader_ARCH.DefaultTraderItems" diff --git a/KFGame/Classes/KFGfxMenu_StartGame.uc b/KFGame/Classes/KFGfxMenu_StartGame.uc index 59b563b..4a44965 100644 --- a/KFGame/Classes/KFGfxMenu_StartGame.uc +++ b/KFGame/Classes/KFGfxMenu_StartGame.uc @@ -202,7 +202,7 @@ static function class GetSpecialEventClass switch (SpecialEventID) { case SEI_Spring: - return class'KFGFxSpecialEventObjectivesContainer_Spring2020'; + return class'KFGFxSpecialEventObjectivesContainer_Spring2021'; case SEI_Summer: return class'KFGFxSpecialEventObjectivesContainer_Summer2020'; case SEI_Fall: @@ -1480,6 +1480,8 @@ function BuildServerFilters(OnlineGameInterface GameInterfaceSteam, KFGFxStartGa else { Search.AddServerFilter("version_match", string(class'KFGameEngine'.static.GetKFGameVersion())); + Search.TestAddBoolGametagFilter(GameTagFilters, true, 'bServerExiled', 0);//Consoles does NOT have this property, so only in PC matchmaking search variables has to be added + //TestAddBoolGametagFilter Explanation: if set to true the second param, it will add the property to the search filters. But this property may interest us to search it as "false" or "true" so that is the purpose of the fourth param. } if (OptionsComponent.GetMakeNewServer() || bAttemptingServerCreate ) diff --git a/KFGame/Classes/KFInventoryManager.uc b/KFGame/Classes/KFInventoryManager.uc index fd35d5e..2757303 100644 --- a/KFGame/Classes/KFInventoryManager.uc +++ b/KFGame/Classes/KFInventoryManager.uc @@ -1121,7 +1121,6 @@ simulated function AttemptQuickHeal() { local KFWeap_HealerBase W; local KFPlayerController KFPC; - local class KFPowerUpClass; // Do not heal if we have full health if ( Instigator.Health >= Instigator.HealthMax ) @@ -1138,8 +1137,7 @@ simulated function AttemptQuickHeal() KFPC = KFPlayerController(Instigator.Owner); if( KFPC != none ) { - KFPowerUpClass = KFPC.GetPowerUpClass(); - if( KFPowerUpClass != none && !KFPowerUpClass.default.CanBeHealedWhilePowerUpIsActive ) + if(!KFPC.CanUseHealObject()) { return; } diff --git a/KFGame/Classes/KFMapInfo.uc b/KFGame/Classes/KFMapInfo.uc index da91edc..28b844b 100644 --- a/KFGame/Classes/KFMapInfo.uc +++ b/KFGame/Classes/KFMapInfo.uc @@ -116,6 +116,8 @@ var() EBossAIType SurvivalBossOverride; var() SeasonalEventIndex ZedSeasonalThemeId; // Mutator code class that can override various map settings var() class MapMutatorClass; +// Whether to allow shotgun jumps +var() bool bAllowShootgunJump; // Objectives to use in Objective Mode var(ObjectiveMode) array ObjectiveModeObjectives; @@ -451,4 +453,6 @@ DefaultProperties AmbientMusicTracks.Add(KFMusicTrackInfo'WW_MAMB_Default.TI_SJ_Menace') TraderVoiceGroupClassPath="KFGameContent.KFTraderVoiceGroup_Default" + + bAllowShootgunJump=true } diff --git a/KFGame/Classes/KFOnlineStatsReadDingo.uc b/KFGame/Classes/KFOnlineStatsReadDingo.uc index 247a992..46d5aa2 100644 --- a/KFGame/Classes/KFOnlineStatsReadDingo.uc +++ b/KFGame/Classes/KFOnlineStatsReadDingo.uc @@ -66,6 +66,7 @@ defaultproperties ColumnIds.Add(STATID_ACHIEVE_DesolationCollectibles) ColumnIds.Add(STATID_ACHIEVE_HellmarkStationCollectibles) ColumnIds.Add(STATID_ACHIEVE_ElysiumEndlessWaveFifteen) + ColumnIds.Add(STATID_ACHIEVE_Dystopia2029Collectibles) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky5, Name="AchievementMrPerky5")) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky10, Name = "AchievementMrPerky10")) @@ -120,4 +121,5 @@ defaultproperties ColumnMappings.Add((Id=STATID_ACHIEVE_DesolationCollectibles,Name="AchievementCollectDesolation")) ColumnMappings.Add((Id=STATID_ACHIEVE_HellmarkStationCollectibles,Name="AchievementCollectHellmarkStation")) ColumnMappings.Add((Id=STATID_ACHIEVE_ElysiumEndlessWaveFifteen,Name="AchievementEndlessElysium")) + ColumnMappings.Add((Id=STATID_ACHIEVE_Dystopia2029Collectibles,NAme="AchievementCollectDystopia2029")) } diff --git a/KFGame/Classes/KFOnlineStatsWrite.uc b/KFGame/Classes/KFOnlineStatsWrite.uc index 1e43191..d01b3a5 100644 --- a/KFGame/Classes/KFOnlineStatsWrite.uc +++ b/KFGame/Classes/KFOnlineStatsWrite.uc @@ -425,6 +425,10 @@ const KFACHID_ElysiumHard = 277; const KFACHID_ElysiumHellOnEarth = 278; const KFACHID_ElysiumEndlessWaveFifteen = 279; +const KFACHID_Dystopia2029Hard = 280; +const KFACHID_Dystopia2029HellOnEarth = 281; +const KFACHID_Dystopia2029Collectibles = 282; + /* __TW_ANALYTICS_ */ var int PerRoundWeldXP; var int PerRoundHealXP; @@ -1073,6 +1077,12 @@ function SavePersonalBest( EPersonalBests PersonalBestID, int Value ) /********************************************************************************************* * @name Gameplay ********************************************************************************************* */ + +private event AddToHitsTaken() +{ + SeasonalEventStats_OnHitTaken(); +} + /** * @brief Add a kill and give some EXP tp the player * @param MonsterClass The killed monster's class @@ -1792,6 +1802,14 @@ final native simulated event SeasonalEventStats_OnGameWon(class GameCl final native simulated event SeasonalEventStats_OnGameEnd(class GameClass); +final simulated function SeasonalEventStats_OnHitTaken() +{ + if (SeasonalEventIsValid()) + { + SeasonalEvent.OnHitTaken(); + } +} + final simulated function SeasonalEventStats_OnZedKilled(class MonsterClass, int Difficulty, class DT) { if (SeasonalEventIsValid()) @@ -2062,6 +2080,7 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_Winchester1894, KFDT_Bludgeon_Winchester,KFDT_Ballistic_Winchester),CompletionAmount=5000)) //2000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Bow_Crossbow, KFDT_Bludgeon_Crossbow,KFDT_Piercing_Crossbow),CompletionAmount=7000)) //5000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_M14EBR, KFDT_Bludgeon_M14EBR,KFDT_Ballistic_M14EBR),CompletionAmount=9000)) //7000 + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_SonicGun, KFDT_Bludgeon_HRG_SonicGun, KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged, KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged, KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged),CompletionAmount=7000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_RailGun, KFDT_Bludgeon_RailGun,KFDT_Ballistic_RailGun),CompletionAmount=5000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_CenterfireMB464, KFDT_Bludgeon_CenterfireMB464,KFDT_Ballistic_CenterfireMB464),CompletionAmount=7000)) //5000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_M99, KFDT_Bludgeon_M99,KFDT_Ballistic_M99),CompletionAmount=5000)) @@ -2203,6 +2222,9 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-ELYSIUM),CompletionAmount=1)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-ELYSIUM),CompletionAmount=2)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-ELYSIUM),CompletionAmount=3)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-DYSTOPIA2029),CompletionAmount=1)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-DYSTOPIA2029),CompletionAmount=2)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-DYSTOPIA2029),CompletionAmount=3)) //Versus Damage // Per design doc that I have right now, these are x class damage y players, not damage y amount diff --git a/KFGame/Classes/KFOnlineStatsWriteDingo.uc b/KFGame/Classes/KFOnlineStatsWriteDingo.uc index da2854a..866cccc 100644 --- a/KFGame/Classes/KFOnlineStatsWriteDingo.uc +++ b/KFGame/Classes/KFOnlineStatsWriteDingo.uc @@ -68,4 +68,5 @@ defaultproperties Properties.Add((PropertyId = STATID_ACHIEVE_DesolationCollectibles,Data = (Type = SDT_Int32,Value1 = 0))) Properties.Add((PropertyId = STATID_ACHIEVE_HellmarkStationCollectibles,Data = (Type = SDT_Int32,Value1 = 0))) Properties.Add((PropertyId = STATID_ACHIEVE_ElysiumEndlessWaveFifteen,Data = (Type = SDT_Int32,Value1 = 0))) + Properties.Add((PropertyId = STATID_ACHIEVE_Dystopia2029Collectibles, Data = (Type = SDT_Int32,Value1 = 0))) } diff --git a/KFGame/Classes/KFOutbreakEvent.uc b/KFGame/Classes/KFOutbreakEvent.uc index 2e768cf..badc695 100644 --- a/KFGame/Classes/KFOutbreakEvent.uc +++ b/KFGame/Classes/KFOutbreakEvent.uc @@ -81,9 +81,19 @@ struct StatAdjustments /** 1 to max player count range of how many AI should spawn during the sub wave */ var() Vector2D AdditionalSubSpawnCount; + /** Ammount of health recovered to the player on kill */ + var() int HealByKill; + + /** Ammount of health recovered to the player on kill assistance */ + var() int HealByAssistance; + /** Killing the zed should give a different dosh amount than the standard. */ var() int DoshGiven; + /** Speed modifier */ + var() float InitialGroundSpeedModifierScale; + + structdefaultproperties { HealthScale = 1.f; @@ -101,6 +111,8 @@ struct StatAdjustments AdditionalSubSpawnCount = (X = 1,Y = 1) DoshGiven=INDEX_NONE + + InitialGroundSpeedModifierScale = 1.0 } }; @@ -135,12 +147,23 @@ struct WeeklyOverrides */ var() KFGFxObject_TraderItems SpawnWeaponList; + /** If this flag is set to true, the secondary weapon will be checked for availability in the current game mode */ + var() bool bSpawnWeaponListAffectsSecondaryWeapons; + /** If this array is not empty, modifies the trader's list of available weapons */ var() KFGFxObject_TraderItems TraderWeaponList; /** Whether or not grenades are disabled at spawn and for purchase */ var() bool bDisableGrenades; + /** If this array is not empty, modifies the list of perks available for this weekly mode */ + var() const array > PerksAvailableList; + + /** Activates the special conditions for the Colliseum Weekly Mode + * 1) Disables Berserker lvl25 skills 2) Enables lvl25 battery ram skill of the swat + */ + var() bool bColliseumSkillConditionsActive; + /** If this array is not empty, replaces AIClassList entries with a new spawn class */ var() array SpawnReplacementList; @@ -202,6 +225,12 @@ struct WeeklyOverrides /** Height to use for kicking players out of partial zed time */ var() float ZedTimeHeight; + /** Use a new probability of getting a drama event when a Zed is killed on a 3m radius of the player */ + var() bool bModifyZedTimeOnANearZedKill; + + /** Percentage value (0...1) for the probability of getting a drama event when a Zed is killed on a 3m radius of the player */ + var() float ZedTimeOnANearZedKill; + /** Whether or not to use size scale on damage */ var() bool bScaleOnHealth; @@ -289,6 +318,27 @@ struct WeeklyOverrides /** Boom performance optimization - Max booms in one frame (avoids big Demo spikes) */ var() int MaxBoomsPerFrame; + /** Heal after kill */ + var() bool bHealAfterKill; + + /** Cannot be Healed*/ + var() bool bCannotBeHealed; + + /** Global Damage affects shield or ignores it */ + var() bool bGlobalDamageAffectsShield; + + /** Global Damage Should be applied during a boss wave*/ + var() bool bApplyGlobalDamageBossWave; + + /** Replenish player's health once a wave ends. */ + var() bool bHealPlayerAfterWave; + + /** Global modifier of dosh received by players when a zed is killed. Default value is 1.0 */ + var() float DoshOnKillGlobalModifier; + + /** Delay After a wave starts for applying global damage. */ + var() float DamageDelayAfterWaveStarted; + /** If another outbreak mode shares the same events, this will link the two to quicker UI lookup */ var() int WeeklyOutbreakId; @@ -323,7 +373,18 @@ struct WeeklyOverrides InflationDeathGravity = -0.1 MaxPerkLevel = 4 bAllowSpawnReplacementDuringBossWave = true + bHealAfterKill = false + bCannotBeHealed = false + bGlobalDamageAffectsShield = true + bApplyGlobalDamageBossWave = true + bHealPlayerAfterWave = false + DamageDelayAfterWaveStarted = 10.0f WeeklyOutbreakId=INDEX_NONE + bSpawnWeaponListAffectsSecondaryWeapons = false + bColliseumSkillConditionsActive = false + bModifyZedTimeOnANearZedKill = false + ZedTimeOnANearZedKill = 0.05 + DoshOnKillGlobalModifier = 1.0f } }; @@ -336,6 +397,7 @@ struct CachedOutbreakInfo var byte MaxPerkLevel; var float CachedWorldGravityZ; var float CachedGlobalGravityZ; + var PerkAvailableData PerksAvailableData; structdefaultproperties { @@ -404,6 +466,11 @@ function ClearActiveEvent() KFGameReplicationInfo(GameReplicationInfo).TraderItems = CachedItems.TraderItems; } + if(ActiveEvent.PerksAvailableList.length > 0) + { + KFGameReplicationInfo(GameReplicationInfo).PerksAvailableData = CachedItems.PerksAvailableData; + } + KFGameReplicationInfo(GameReplicationInfo).GameAmmoCostScale = CachedItems.GameAmmoCostScale; KFGameReplicationInfo(GameReplicationInfo).bAllowGrenadePurchase = CachedItems.bAllowGrenadePurchase; KFGameReplicationInfo(GameReplicationInfo).bTradersEnabled = CachedItems.bTradersEnabled; @@ -425,6 +492,11 @@ function CacheGRI() CachedItems.TraderItems = KFGameReplicationInfo(GameReplicationInfo).TraderItems; } + if(ActiveEvent.PerksAvailableList.length > 0) + { + CachedItems.PerksAvailableData = KFGameReplicationInfo(GameReplicationInfo).PerksAvailableData; + } + CachedItems.GameAmmoCostScale = KFGameReplicationInfo(GameReplicationInfo).GameAmmoCostScale; CachedItems.bAllowGrenadePurchase = KFGameReplicationInfo(GameReplicationInfo).bAllowGrenadePurchase; CachedItems.bTradersEnabled = KFGameReplicationInfo(GameReplicationInfo).bTradersEnabled; @@ -434,20 +506,54 @@ function CacheGRI() function UpdateGRI() { + local int i; + local KFGameReplicationInfo KFGRI; + CacheGRI(); //This should have just been spawned in the super if (GameReplicationInfo != none && KFGameReplicationInfo(GameReplicationInfo) != none) { + KFGRI = KFGameReplicationInfo(GameReplicationInfo); + if (ActiveEvent.TraderWeaponList != none) { - KFGameReplicationInfo(GameReplicationInfo).TraderItems = ActiveEvent.TraderWeaponList; + KFGRI.TraderItems = ActiveEvent.TraderWeaponList; } - KFGameReplicationInfo(GameReplicationInfo).GameAmmoCostScale = ActiveEvent.GlobalAmmoCostScale; - KFGameReplicationInfo(GameReplicationInfo).bAllowGrenadePurchase = !ActiveEvent.bDisableGrenades; - KFGameReplicationInfo(GameReplicationInfo).bTradersEnabled = !ActiveEvent.bDisableTraders; - KFGameReplicationInfo(GameReplicationInfo).MaxPerkLevel = ActiveEvent.MaxPerkLevel; + if(ActiveEvent.PerksAvailableList.length > 0) + { + KFGRI.PerksAvailableData.bPerksAvailableLimited = true; + KFGRI.PerksAvailableData.bBerserkerAvailable = false; + KFGRI.PerksAvailableData.bCommandoAvailable = false; + KFGRI.PerksAvailableData.bSupportAvailable = false; + KFGRI.PerksAvailableData.bFieldMedicAvailable = false; + KFGRI.PerksAvailableData.bDemolitionistAvailable = false; + KFGRI.PerksAvailableData.bFirebugAvailable = false; + KFGRI.PerksAvailableData.bGunslingerAvailable = false; + KFGRI.PerksAvailableData.bSharpshooterAvailable = false; + KFGRI.PerksAvailableData.bSwatAvailable = false; + KFGRI.PerksAvailableData.bSurvivalistAvailable = false; + + for(i=0 ; i DamageType; + + DamageType = ActiveEvent.bGlobalDamageAffectsShield ? class'DmgType_Crushed' : class'KFDT_Falling'; foreach WorldInfo.AllPawns(class'KFPawn_Human', Pawn) { - Pawn.TakeDamage(OutbreakEvent.ActiveEvent.GlobalDamageTickAmount, none, Pawn.Location, vect(0, 0, 0), class'DmgType_Crushed'); + Pawn.TakeDamage(OutbreakEvent.ActiveEvent.GlobalDamageTickAmount, none, Pawn.Location, vect(0, 0, 0), DamageType); } } diff --git a/KFGame/Classes/KFPawn.uc b/KFGame/Classes/KFPawn.uc index 36c6feb..4b1b495 100644 --- a/KFGame/Classes/KFPawn.uc +++ b/KFGame/Classes/KFPawn.uc @@ -2672,9 +2672,6 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector OldHealth = Health; 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(DamageType), DamageCauser); - ActualDamage = OldHealth - Health; if( ActualDamage > 0 ) { @@ -3999,12 +3996,12 @@ simulated function KFSkinTypeEffects GetHitZoneSkinTypeEffects( int HitZoneIdx ) */ simulated function AdjustAffliction(out float AfflictionPower); -function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class DamageType, Actor DamageCauser) +function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class DamageType, Actor DamageCauser) { //Handle afflictions if (AfflictionHandler != None) { - AfflictionHandler.NotifyTakeHit(DamageInstigator, HitDir, DamageType, DamageCauser); + AfflictionHandler.NotifyTakeHit(DamageInstigator, HitDir, class(DamageType), DamageCauser); } } diff --git a/KFGame/Classes/KFPawn_Human.uc b/KFGame/Classes/KFPawn_Human.uc index 33981c9..3c5724a 100644 --- a/KFGame/Classes/KFPawn_Human.uc +++ b/KFGame/Classes/KFPawn_Human.uc @@ -159,9 +159,9 @@ var float MinHealthPctToTriggerSurrounded; ********************************************************************************************* */ var array ActiveSkillIconPaths; -var private byte HealingSpeedBoost; -var private byte HealingDamageBoost; -var private byte HealingShield; +var repnotify private byte HealingSpeedBoost; +var repnotify private byte HealingDamageBoost; +var repnotify private byte HealingShield; var transient KFExplosion_AirborneAgent AAExplosionActor; @@ -359,9 +359,17 @@ simulated event ReplicatedEvent(name VarName) case nameof(PowerUpFxStopInfo): StopPowerUpEffect(PowerUpFxStopInfo); break; + case nameof(HealingSpeedBoost): + NotifyHealingSpeedBoostBuff(HealingSpeedBoost); + break; + case nameof(HealingDamageBoost): + NotifyHealingDamageBoostBuff(HealingDamageBoost); + break; + case nameof(HealingShield): + NotifyHealingShieldBoostBuff(HealingShield); + break; } - Super.ReplicatedEvent(VarName); } @@ -436,6 +444,7 @@ simulated function OnCharacterMeshChanged() function AddDefaultInventory() { local KFPerk MyPerk; + local KFGameInfo GameInfo; MyPerk = GetPerk(); @@ -447,7 +456,12 @@ function AddDefaultInventory() /** DefaultInventory.AddItem(class(DynamicLoadObject("KFGameContent.KFWeap_Pistol_9mm", class'Class'))); Loading the secondary weapon in the perk again */ - DefaultInventory.AddItem(class(DynamicLoadObject("KFGameContent.KFWeap_Healer_Syringe", class'Class'))); + GameInfo = KFGameInfo(WorldInfo.Game); + if(GameInfo.OutbreakEvent == none || !GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed) + { + DefaultInventory.AddItem(class(DynamicLoadObject("KFGameContent.KFWeap_Healer_Syringe", class'Class'))); + } + DefaultInventory.AddItem(class(DynamicLoadObject("KFGameContent.KFWeap_Welder", class'Class'))); DefaultInventory.AddItem(class(DynamicLoadObject("KFGameContent.KFInventory_Money", class'Class'))); @@ -675,18 +689,9 @@ event bool HealDamage(int Amount, Controller Healer, class DamageTyp event bool HealDamage(int Amount, Controller Healer, class DamageType) `endif { - local int DoshEarned; - local float UsedHealAmount; - local KFPlayerReplicationInfo InstigatorPRI; - local KFPlayerController InstigatorPC, KFPC; - local KFPerk InstigatorPerk; + local KFPlayerController KFPC; local KFPowerUp KFPowerUp; - local class KFDT; - local int i; - local bool bRepairedArmor; - local int OldHealth; - - OldHealth = Health; + local KFGameInfo GameInfo; KFPC = KFPlayerController(Controller); if ( KFPC != none ) @@ -698,6 +703,30 @@ event bool HealDamage(int Amount, Controller Healer, class DamageTyp } } + GameInfo = KFGameInfo(WorldInfo.Game); + if (GameInfo.OutbreakEvent != none && GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed) + { + return false; + } + + return HealDamageForce(Amount, Healer, DamageType, bCanRepairArmor, bMessageHealer); +} + + +event bool HealDamageForce(int Amount, Controller Healer, class DamageType, optional bool bCanRepairArmor=true, optional bool bMessageHealer=true) +{ + local int DoshEarned; + local float UsedHealAmount; + local KFPlayerReplicationInfo InstigatorPRI; + local KFPlayerController InstigatorPC, KFPC; + local KFPerk InstigatorPerk; + local class KFDT; + local int i; + local bool bRepairedArmor; + local int OldHealth; + + OldHealth = Health; + InstigatorPC = KFPlayerController(Healer); InstigatorPerk = InstigatorPC != None ? InstigatorPC.GetPerk() : None; if( InstigatorPerk != None ) @@ -1260,6 +1289,7 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector { local int ActualDamageTaken, OldHealth; //local KFGameInfo KFGI; + local KFGameReplicationInfo KFGRI; local KFPlayerReplicationInfo KFPRI; local KFAIController_ZedBoss InstigatedByBoss; @@ -1272,6 +1302,12 @@ event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector `log(GetFuncName()@"Damage AFTER ="$ActualDamageTaken$" DamageType: "$DamageType$" DamageCauser: "$DamageCauser, bLogTakeDamage); + KFGRI = KFGameReplicationInfo(KFGameInfo(WorldInfo.Game).GameReplicationInfo); + if( Damage > 0 && IsAliveAndWell() && !KFGRI.bTraderIsOpen ) + { + KFPlayerController(Controller).NotifyHitTaken(); + } + if( ActualDamageTaken > 0 && IsAliveAndWell() ) { CheckAndEndActiveEMoteSpecialMove(); @@ -1396,6 +1432,11 @@ 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) + { + NotifyHealingSpeedBoostBuff(HealingSpeedBoost); + } } simulated function ResetHealingSpeedBoost() @@ -1406,6 +1447,11 @@ simulated function ResetHealingSpeedBoost() { ClearTimer( nameOf( ResetHealingSpeedBoost ) ); } + + if ( WorldInfo.NetMode == NM_STANDALONE) + { + NotifyHealingSpeedBoostBuff(HealingSpeedBoost); + } } simulated function float GetHealingDamageBoostModifier() @@ -1417,6 +1463,11 @@ 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) + { + NotifyHealingDamageBoostBuff(HealingDamageBoost); + } } simulated function ResetHealingDamageBoost() @@ -1427,6 +1478,11 @@ simulated function ResetHealingDamageBoost() { ClearTimer( nameOf( ResetHealingDamageBoost ) ); } + + if ( WorldInfo.NetMode == NM_STANDALONE) + { + NotifyHealingDamageBoostBuff(HealingDamageBoost); + } } simulated function float GetHealingShieldModifier() @@ -1438,6 +1494,11 @@ 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) + { + NotifyHealingShieldBoostBuff(HealingShield); + } } simulated function ResetHealingShield() @@ -1448,6 +1509,11 @@ simulated function ResetHealingShield() { ClearTimer( nameOf( ResetHealingShield ) ); } + + if ( WorldInfo.NetMode == NM_STANDALONE) + { + NotifyHealingShieldBoostBuff(HealingShield); + } } /** @@ -1964,6 +2030,68 @@ simulated function DisplayDebug(HUD HUD, out float out_YL, out float out_YPos) } } +simulated function NotifyHealingSpeedBoostBuff(byte Speed) +{ + if( Role == ROLE_Authority ) + { + HealingSpeedBoost = Speed; + bForceNetUpdate = true; + } + + if( IsLocallyControlled() ) + { + UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingSpeedBoost].IconPath, Speed > 0.0f); + } +} + +simulated function NotifyHealingDamageBoostBuff(byte Damage) +{ + if( Role == ROLE_Authority ) + { + HealingSpeedBoost = Damage; + bForceNetUpdate = true; + } + + if( IsLocallyControlled() ) + { + UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingDamageBoost].IconPath, Damage > 0.0f); + } +} + +simulated function NotifyHealingShieldBoostBuff(byte Shield) +{ + if( Role == ROLE_Authority ) + { + HealingSpeedBoost = Shield; + bForceNetUpdate = true; + } + + if( IsLocallyControlled() ) + { + UpdateActiveSkillsPath(class'KFPerk_FieldMedic'.default.PerkSkills[EMedicHealingShield].IconPath, Shield > 0.0f); + } +} + +function UpdateActiveSkillsPath(string IconPath, bool Active) +{ + local KFPlayerController KFPC; + + if(Active) + { + if (ActiveSkillIconPaths.Find(IconPath) == INDEX_NONE) + { + ActiveSkillIconPaths.AddItem(IconPath); + } + } + else + { + ActiveSkillIconPaths.RemoveItem(IconPath); + } + + KFPC = KFPlayerController(Controller); + KFPC.MyGFxHUD.PlayerStatusContainer.ShowActiveIndicators(ActiveSkillIconPaths); +} + defaultproperties { Begin Object Class=KFFlashlightAttachment name=Flashlight_0 diff --git a/KFGame/Classes/KFPawn_Monster.uc b/KFGame/Classes/KFPawn_Monster.uc index 581730a..2cc6465 100644 --- a/KFGame/Classes/KFPawn_Monster.uc +++ b/KFGame/Classes/KFPawn_Monster.uc @@ -88,6 +88,10 @@ var private const float XPValues[4]; /** List of sockets representing weakpoint zone locations */ var() array WeakSpotSocketNames; +/** Heal after die */ +var int HealByKill; +var int HealByAssistance; + /** * Information on resistant or vulnerable damage types * @todo: This is all static data so we should consider moving to the archetype @@ -318,8 +322,11 @@ var protected const float BlockSprintSpeedModifier; /** The last time a successful block ended */ var transient float LastBlockTime; +/** Multiplier applied to the vortex attraction force */ +var protected float VortexAttracionModifier; + var float KnockedDownBySonicWaveOdds; -var bool bCloakOnMeleeEnd; +var bool bCloakOnMeleeEnd; var bool bIsCloakingSpottedByLP; var repnotify bool bIsCloakingSpottedByTeam; var float LastSpottedStatusUpdate; @@ -2368,6 +2375,11 @@ function BleedOutTimer() } } +function float GetVortexAttractionModifier () +{ + return VortexAttracionModifier; +} + /** Applies the rally buff and spawns a rally effect */ simulated function bool Rally( KFPawn RallyInstigator, @@ -4852,4 +4864,6 @@ DefaultProperties Components.Add(HeadshotAkComponent0) bSprintOverride=false + + VortexAttracionModifier=1.0f } diff --git a/KFGame/Classes/KFPawn_MonsterBoss.uc b/KFGame/Classes/KFPawn_MonsterBoss.uc index 160364d..b1729b8 100644 --- a/KFGame/Classes/KFPawn_MonsterBoss.uc +++ b/KFGame/Classes/KFPawn_MonsterBoss.uc @@ -443,4 +443,6 @@ defaultproperties SpeedLimitScalar=1.30 bCanBePinned=false + + VortexAttracionModifier=0.3f } \ No newline at end of file diff --git a/KFGame/Classes/KFPerk.uc b/KFGame/Classes/KFPerk.uc index 5923b15..ed6be35 100644 --- a/KFGame/Classes/KFPerk.uc +++ b/KFGame/Classes/KFPerk.uc @@ -189,6 +189,17 @@ var float HeadshotAccuracyHandicap; var array PrestigeRewardItemIconPaths; +/********************************************************************************************* +* Transient vars +********************************************************************************************* */ +/** + Indicates if the last hit was a headshot. + This is added for the crossbow to apply the stun on enemies only if hit in the head. + Afflictions are calculated after adjusting the damage, so the bone is not necessary + indicating a headshot anymore. + */ +var transient bool bWasLastHitAHeadshot; + /********************************************************************************************* * Caching ********************************************************************************************* */ @@ -461,6 +472,17 @@ static function bool IsBackupWeapon( KFWeapon KFW ) return KFW != none && KFW.default.bIsBackupWeapon; } +/** + * @brief Return if a weapon is Dual 9mm + * + * @param KFW Weapon to check + * @return true if backup weapon + */ +static function bool IsDual9mm( KFWeapon KFW ) +{ + return KFW != none && KFW.Class.Name == 'KFWeap_Pistol_Dual9mm'; +} + /********************************************************************************************* * @name Build / Level Management - Apply and save the updated build and level ********************************************************************************************* */ @@ -934,13 +956,18 @@ function AddDefaultInventory( KFPawn P ) { P.DefaultInventory.AddItem(class(DynamicLoadObject(GetPrimaryWeaponClassPath(), class'Class'))); } + + if(KFGameInfo(WorldInfo.Game).AllowSecondaryWeapon(GetSecondaryWeaponClassPath())) + { + P.DefaultInventory.AddItem(class(DynamicLoadObject(GetSecondaryWeaponClassPath(), class'Class'))); + } } else { P.DefaultInventory.AddItem(class(DynamicLoadObject(GetPrimaryWeaponClassPath(), class'Class'))); + P.DefaultInventory.AddItem(class(DynamicLoadObject(GetSecondaryWeaponClassPath(), class'Class'))); } - // Secondary weapon is spawned through the pawn unless we want an additional one not anymore - P.DefaultInventory.AddItem(class(DynamicLoadObject(GetSecondaryWeaponClassPath(), class'Class'))); + P.DefaultInventory.AddItem(class(DynamicLoadObject(GetKnifeWeaponClassPath(), class'Class'))); } } @@ -1073,8 +1100,7 @@ simulated function ModifySprintSpeed( out float Speed ){ ModifySpeed( Speed ); } function FinalizeSpeedVariables(); /** Kickback - recaoil bonus */ simulated function ModifyRecoil( out float CurrentRecoilModifier, KFWeapon KFW ); -/** Allow perk to adjust damage given */ -function ModifyDamageGiven( out int InDamage, optional Actor DamageCauser, optional KFPawn_Monster MyKFPM, optional KFPlayerController DamageInstigator, optional class DamageType, optional int HitZoneIdx ); +/** Allows to modify the damage taken */ function ModifyDamageTaken( out int InDamage, optional class DamageType, optional Controller InstigatedBy ); /** Ammunition capacity and mag count increased */ simulated function ModifyMagSizeAndNumber( KFWeapon KFW, out int MagazineCapacity, optional array< Class > WeaponPerkClass, optional bool bSecondary=false, optional name WeaponClassname ); @@ -1092,6 +1118,7 @@ static simulated function float GetZedTimeExtension( byte Level ){ return 1.0f; function float GetKnockdownPowerModifier( optional class DamageType, optional byte BodyPart, optional bool bIsSprinting=false ){ return 0.f; } function float GetStumblePowerModifier( optional KFPawn KFP, optional class DamageType, optional out float CooldownModifier, optional byte BodyPart ){ return 0.f; } function float GetStunPowerModifier( optional class DamageType, optional byte HitZoneIdx ){ return 0.f; } +function bool IsStunGuaranteed( optional class DamageType, optional byte HitZoneIdx ){ return false; } function float GetReactionModifier( optional class DamageType ){ return 1.f; } simulated function float GetSnareSpeedModifier() { return 1.f; } simulated function float GetSnarePowerModifier( optional class DamageType, optional byte HitZoneIdx ){ return 1.f; } @@ -1199,9 +1226,6 @@ simulated function int GetArmorDamageAmount( int AbsorbedAmt ) { return Absorbed simulated event float GetZedTimeSpeedScale() { return 1.f; } -/** Survivalist dunctions */ -simulated function bool GetIncapMasterActive(){ return false; } - static function ModifyAssistDosh( out int EarnedDosh ) { local float TempDosh; @@ -1304,6 +1328,7 @@ function TickRegen( float DeltaTime ) local KFPlayerController KFPC; local KFPowerUp PowerUp; local bool bCannotBeHealed; + local KFGameInfo GameInfo; TimeUntilNextRegen -= DeltaTime; if( TimeUntilNextRegen <= 0.f ) @@ -1314,9 +1339,12 @@ function TickRegen( float DeltaTime ) if( KFPC != none ) { PowerUp = KFPC.GetPowerUp(); - bCannotBeHealed = PowerUp != none && !PowerUp.CanBeHealedWhilePowerUpIsActive; + bCannotBeHealed = PowerUp != none && !PowerUp.CanBeHealed(); } + GameInfo = KFGameInfo(WorldInfo.Game); + bCannotBeHealed = bCannotBeHealed || (GameInfo.OutbreakEvent != none && GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed); + // If the Pawn cannot be healed return... if( bCannotBeHealed ) { @@ -1372,6 +1400,12 @@ simulated function class GetGrenadeWeaponDef() return default.GrenadeWeaponDef; } +/** Allow perk to adjust damage given */ +function ModifyDamageGiven( out int InDamage, optional Actor DamageCauser, optional KFPawn_Monster MyKFPM, optional KFPlayerController DamageInstigator, optional class DamageType, optional int HitZoneIdx ) +{ + bWasLastHitAHeadshot = MyKFPM != none && HitZoneIdx == HZI_HEAD; +} + /********************************************************************************************* * @name Debug ********************************************************************************************* */ @@ -1485,4 +1519,6 @@ DefaultProperties AssistDoshModifier=1.f PrestigeRewardItemIconPaths[0]="Xmas_UI.UI_Objectives_Xmas_Krampus" + + bWasLastHitAHeadshot=false } diff --git a/KFGame/Classes/KFPerk_Berserker.uc b/KFGame/Classes/KFPerk_Berserker.uc index 618dcc5..aa14206 100644 --- a/KFGame/Classes/KFPerk_Berserker.uc +++ b/KFGame/Classes/KFPerk_Berserker.uc @@ -53,6 +53,11 @@ enum EBerserkPerkSkills EBerserkerSpartan }; +/** The last time a zed was bumped using battering ram */ +var float LastBumpTime; +/** The unique list of actors that have been bumped before the last cooldown reset */ +var array CurrentBumpedActors; + cpptext { // specific abilities @@ -71,7 +76,7 @@ function ApplySkillsToPawn() if( OwnerPawn != none ) { - OwnerPawn.bMovesFastInZedTime = IsFastInZedTime(); + OwnerPawn.bMovesFastInZedTime = IsFastInZedTime() || IsSWATEnforcerActiveForWeekly(); } } @@ -112,13 +117,17 @@ reliable client function ClientClearPerkEffects() event Tick( float DeltaTime ) { super.Tick( DeltaTime ); - if( IsNinjaActive() ) { TickRegen( DeltaTime ); } } +simulated event float GetZedTimeSpeedScale() +{ + return GetZedTimeSpeedScaleForColliseum(); +} + /********************************************************************************************* * @name Passive skills functions ********************************************************************************************* */ @@ -136,6 +145,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon MyKFWeapon; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) @@ -540,6 +551,7 @@ function NotifyZedTimeStarted() local KFPlayerController KFPC; local KFPowerUp PowerUp; local KFAIController KFAIC; + local KFGameInfo GameInfo; local bool bScaredAI; local bool bCannotBeHealed; @@ -549,9 +561,15 @@ function NotifyZedTimeStarted() if( KFPC != none ) { PowerUp = KFPC.GetPowerUp(); - bCannotBeHealed = PowerUp != none && !PowerUp.CanBeHealedWhilePowerUpIsActive; + bCannotBeHealed = (PowerUp != none && !PowerUp.CanBeHealedWhilePowerUpIsActive); + + GameInfo = KFGameInfo(WorldInfo.Game); + if(GameInfo != none) + { + bCannotBeHealed = bCannotBeHealed ||(GameInfo.OutbreakEvent != none && GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed); + } } - + if( bCannotBeHealed == false ) { OwnerPawn.Health += OwnerPawn.HealthMax * GetSkillValue( PerkSkills[EBerserkerRage] ); @@ -637,11 +655,11 @@ private static function float GetParryDamageModifier() { return default.ParryDamageReduction; } + /********************************************************************************************* * @name Getters / Setters ********************************************************************************************* */ - /** * @brief Checks if the fortitude skill is active * @@ -789,7 +807,7 @@ function bool CanNotBeGrabbed() */ simulated private event bool IsRageActive() { - return PerkSkills[EBerserkerRage].bActive && WorldInfo.TimeDilation < 1.f && IsPerkLevelAllowed(EBerserkerRage); + return PerkSkills[EBerserkerRage].bActive && WorldInfo.TimeDilation < 1.f && IsPerkLevelAllowed(EBerserkerRage) && !ShouldDisableZedTimeSkillsForWeekly(); } /** @@ -799,12 +817,12 @@ simulated private event bool IsRageActive() */ simulated final private event bool IsSpartanActive() { - return PerkSkills[EBerserkerSpartan].bActive && WorldInfo.TimeDilation < 1.f && IsPerkLevelAllowed(EBerserkerSpartan); + return PerkSkills[EBerserkerSpartan].bActive && WorldInfo.TimeDilation < 1.f && IsPerkLevelAllowed(EBerserkerSpartan) && !ShouldDisableZedTimeSkillsForWeekly(); } simulated private event bool CouldSpartanBeActive() { - return PerkSkills[EBerserkerSpartan].bActive && IsPerkLevelAllowed(EBerserkerSpartan); + return PerkSkills[EBerserkerSpartan].bActive && IsPerkLevelAllowed(EBerserkerSpartan) && !ShouldDisableZedTimeSkillsForWeekly(); } /** @@ -814,7 +832,12 @@ simulated private event bool CouldSpartanBeActive() */ simulated function bool IsFastInZedTime() { - return PerkSkills[EBerserkerSpartan].bActive && IsPerkLevelAllowed(EBerserkerSpartan); + return PerkSkills[EBerserkerSpartan].bActive && IsPerkLevelAllowed(EBerserkerSpartan) && !ShouldDisableZedTimeSkillsForWeekly(); +} + +simulated function bool IsFastInZedTimeOutbreak() +{ + return ShouldDisableZedTimeSkillsForWeekly(); } /** @@ -825,7 +848,7 @@ simulated function bool IsFastInZedTime() */ simulated event bool ShouldUseFastInstigatorDilation(KFWeapon Weap) { - if (PerkSkills[EBerserkerSpartan].bActive && Weap != none && IsPerkLevelAllowed(EBerserkerSpartan)) + if (PerkSkills[EBerserkerSpartan].bActive && Weap != none && IsPerkLevelAllowed(EBerserkerSpartan) && !ShouldDisableZedTimeSkillsForWeekly()) { return Weap.GetWeaponPerkClass(default.Class) == default.Class; } @@ -833,6 +856,75 @@ simulated event bool ShouldUseFastInstigatorDilation(KFWeapon Weap) return false; } +/********************************************************************************************* +* @name Special Weekly Modes +********************************************************************************************* */ + +simulated event float GetZedTimeSpeedScaleForColliseum() +{ + return IsSWATEnforcerActiveForWeekly() ? class'KFPerk_Swat'.default.SWATEnforcerZedTimeSpeedScale : 1.f; +} + +function bool ShouldDisableZedTimeSkillsForWeekly() +{ + return MyKFGI != none && MyKFGI.OutbreakEvent != none && MyKFGI.OutbreakEvent.ActiveEvent.bColliseumSkillConditionsActive; +} + +function bool IsSWATEnforcerActiveForWeekly() +{ + return MyKFGI != none && MyKFGI.OutbreakEvent != none && MyKFGI.OutbreakEvent.ActiveEvent.bColliseumSkillConditionsActive; +} + +simulated function bool ShouldKnockDownOnBump() +{ + return IsSWATEnforcerActiveForWeekly() && WorldInfo.TimeDilation < 1.f; +} + +simulated function OnBump(Actor BumpedActor, KFPawn_Human BumpInstigator, vector BumpedVelocity, rotator BumpedRotation) +{ + local KFPawn_Monster KFPM; + local bool CanBump; + + if (ShouldKnockDownOnBump() && Normal(BumpedVelocity) dot Vector(BumpedRotation) > 0.7f) + { + KFPM = KFPawn_Monster(BumpedActor); + if (KFPM != none) + { + // cooldown so that the same zed can't be bumped multiple frames back to back + // especially relevant if they can't be knocked down or stumbled so the player is always bumping them + if (WorldInfo.TimeSeconds - LastBumpTime > class'KFPerk_Swat'.default.BumpCooldown) + { + CurrentBumpedActors.length = 0; + CurrentBumpedActors.AddItem(BumpedActor); + CanBump = true; + } + // if still within the cooldown time, can still bump the actor as long as it hasn't been bumped yet + else if (CurrentBumpedActors.Find(BumpedActor) == INDEX_NONE) + { + CurrentBumpedActors.AddItem(BumpedActor); + CanBump = true; + } + + LastBumpTime = WorldInfo.TimeSeconds; + + if (CanBump) + { + if (KFPM.IsHeadless()) + { + KFPM.TakeDamage(KFPM.HealthMax, BumpInstigator.Controller, BumpInstigator.Location, + Normal(vector(BumpedRotation)) * class'KFPerk_Swat'.default.BumpMomentum, class'KFPerk_Swat'.default.BumpDamageType); + } + else + { + KFPM.TakeDamage(class'KFPerk_Swat'.default.BumpDamageAmount, BumpInstigator.Controller, BumpInstigator.Location, + Normal(vector(BumpedRotation)) * class'KFPerk_Swat'.default.BumpMomentum, class'KFPerk_Swat'.default.BumpDamageType); + KFPM.Knockdown(BumpedVelocity * 3, vect(1, 1, 1), KFPM.Location, 1000, 100); + } + } + } + } +} + /********************************************************************************************* * @name UI / HUD ********************************************************************************************* */ @@ -926,11 +1018,11 @@ DefaultProperties DamageResistance=(Name="Damage Resistance",Increment=0.03f,Rank=0,StartingValue=0.f,MaxValue=0.15f) NightVision=(Name="Night Vision",Increment=0.f,Rank=0,StartingValue=0.f,MaxValue=0.f) - PerkSkills(EBerserkerFortitude)=(Name="Fortitude",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Fortitude",Increment=0.f,Rank=0,StartingValue=0.75,MaxValue=0.75) + PerkSkills(EBerserkerFortitude)=(Name="Fortitude",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Fortitude",Increment=0.f,Rank=0,StartingValue=1.0,MaxValue=1.0) //0.75 PerkSkills(EBerserkerNinja)=(Name="Ninja",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Ninja",Increment=0.f,Rank=0,StartingValue=0.2f,MaxValue=0.2f) PerkSkills(EBerserkerVampire)=(Name="Vampire",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Vampire",Increment=0.f,Rank=0,StartingValue=4.f,MaxValue=4.f) PerkSkills(EBerserkerSpeed)=(Name="Speed",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Speed",Increment=0.f,Rank=0,StartingValue=0.2f,MaxValue=0.2f) - PerkSkills(EBerserkerResistance)=(Name="Resistance",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_PoisonResistance",Increment=0.f,Rank=0,StartingValue=0.2f,MaxValue=0.2f) + PerkSkills(EBerserkerResistance)=(Name="Resistance",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_PoisonResistance",Increment=0.f,Rank=0,StartingValue=0.25f,MaxValue=0.25f) //0.2 PerkSkills(EBerserkerParry)=(Name="Parry",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Parry",Increment=0.f,Rank=0,StartingValue=0.35,MaxValue=0.35) PerkSkills(EBerserkerSmash)=(Name="Smash",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Smash",Increment=0.f,Rank=0,StartingValue=0.5f,MaxValue=0.5f) PerkSkills(EBerserkerFury)=(Name="Fury",IconPath="UI_PerkTalent_TEX.berserker.UI_Talents_Berserker_Intimidate",Increment=0.f,Rank=0,StartingValue=0.3f,MaxValue=0.3f) diff --git a/KFGame/Classes/KFPerk_Commando.uc b/KFGame/Classes/KFPerk_Commando.uc index 6e2c3e3..ae2c1d4 100644 --- a/KFGame/Classes/KFPerk_Commando.uc +++ b/KFGame/Classes/KFPerk_Commando.uc @@ -74,6 +74,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau { local KFWeapon KFW; local float TempDamage; + + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); TempDamage = InDamage; @@ -82,7 +84,7 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau KFW = GetWeaponFromDamageCauser( DamageCauser ); } - if( (KFW != none && IsWeaponOnPerk( KFW,, self.class )) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) ) + if( (KFW != none && (IsWeaponOnPerk( KFW,, self.class ) || IsDual9mm(KFW) || Is9mm(KFW))) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) ) { TempDamage += InDamage * GetPassiveValue( WeaponDamage, CurrentLevel ); if( IsRapidFireActive() ) @@ -97,7 +99,7 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau // have the perks so tied into using that, it's easier to just specifically fix commando here. if( KFW != none && !DamageCauser.IsA('KFProj_Grenade')) { - if( IsBackupActive() && (IsBackupWeapon( KFW ) || KFW.Class.Name == 'KFWeap_Pistol_Dual9mm') ) + if( IsBackupActive() && (IsBackupWeapon( KFW ) || IsDual9mm( KFW )) ) { `QALog( "Backup Damage" @ KFW @ GetPercentage( InDamage, InDamage * GetSkillValue( PerkSkills[ECommandoBackup] )), bLogPerk ); TempDamage += InDamage * GetSkillValue( PerkSkills[ECommandoBackup] ); @@ -234,7 +236,7 @@ function ModifyArmor( out byte MaxArmor ) */ simulated function bool GetUsingTactialReload( KFWeapon KFW ) { - return ( IsTacticalReloadActive() && (IsWeaponOnPerk( KFW,, self.class ) || IsBackupWeapon( KFW )) ); + return ( IsTacticalReloadActive() && (IsWeaponOnPerk( KFW,, self.class ) || IsBackupWeapon( KFW ) || IsDual9mm( KFW )) ); } /** @@ -278,7 +280,7 @@ simulated function ModifyMaxSpareAmmoAmount( KFWeapon KFW, out int MaxSpareAmmo, local float TempMaxSpareAmmoAmount; if( IsAmmoVestActive() && (IsWeaponOnPerk( KFW, TraderItem.AssociatedPerkClasses, self.class ) || - IsBackupWeapon( KFW )) ) + IsBackupWeapon( KFW ) || IsDual9mm( KFW )) ) { TempMaxSpareAmmoAmount = MaxSpareAmmo; TempMaxSpareAmmoAmount += MaxSpareAmmo * GetSkillValue( PerkSkills[ECommandoAmmoVest] ); @@ -302,7 +304,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) local name StateName; StateName = W.GetStateName(); - if( IsProfessionalActive() && (IsWeaponOnPerk( W,, self.class ) || IsBackupWeapon( W )) ) + if( IsProfessionalActive() && (IsWeaponOnPerk( W,, self.class ) || IsBackupWeapon( W ) || IsDual9mm( W )) ) { if( StateName == 'Reloading' || StateName == 'AltReloading' ) @@ -315,7 +317,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) } } - if( CouldRapidFireActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class )) && ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE ) + if( CouldRapidFireActive() && (Is9mm(W) || IsDual9mm( W ) || IsWeaponOnPerk( W,, self.class )) && ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE ) { return RapidFireFiringRate; } diff --git a/KFGame/Classes/KFPerk_Demolitionist.uc b/KFGame/Classes/KFPerk_Demolitionist.uc index 2707f13..3c7ce6b 100644 --- a/KFGame/Classes/KFPerk_Demolitionist.uc +++ b/KFGame/Classes/KFPerk_Demolitionist.uc @@ -127,6 +127,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + if( DamageType != none && IsDamageIgnoredDT( DamageType ) ) { return; @@ -437,7 +439,7 @@ simulated protected function int GetAmmoExtraAmmo() */ simulated function bool GetUsingTactialReload(KFWeapon KFW) { - return (IsTacticalReloadActive() && (IsWeaponOnPerk(KFW, , self.class) || IsBackupWeapon(KFW)) && TacticalReloadAsReloadRateClassNames.Find(KFW.class.Name) == INDEX_NONE); + return (IsTacticalReloadActive() && (IsWeaponOnPerk(KFW, , self.class) || IsBackupWeapon(KFW) || IsDual9mm( KFW )) && TacticalReloadAsReloadRateClassNames.Find(KFW.class.Name) == INDEX_NONE); } /** diff --git a/KFGame/Classes/KFPerk_FieldMedic.uc b/KFGame/Classes/KFPerk_FieldMedic.uc index 1eaa84f..fb524f4 100644 --- a/KFGame/Classes/KFPerk_FieldMedic.uc +++ b/KFGame/Classes/KFPerk_FieldMedic.uc @@ -298,6 +298,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) @@ -646,7 +648,7 @@ DefaultProperties PerkBuildStatID=STATID_Medic_Build SelfHealingSurgePct=0.1f - MaxSurvivalistResistance=0.5f //0.8 + MaxSurvivalistResistance=0.70f //0.5f //0.8 CombatantSpeedModifier=0.1f MaxHealingSpeedBoost=30 //15 //50 diff --git a/KFGame/Classes/KFPerk_Firebug.uc b/KFGame/Classes/KFPerk_Firebug.uc index 3164a71..b1324d8 100644 --- a/KFGame/Classes/KFPerk_Firebug.uc +++ b/KFGame/Classes/KFPerk_Firebug.uc @@ -82,6 +82,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) diff --git a/KFGame/Classes/KFPerk_Gunslinger.uc b/KFGame/Classes/KFPerk_Gunslinger.uc index 672d239..cb7e6c8 100644 --- a/KFGame/Classes/KFPerk_Gunslinger.uc +++ b/KFGame/Classes/KFPerk_Gunslinger.uc @@ -133,6 +133,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) { diff --git a/KFGame/Classes/KFPerk_Sharpshooter.uc b/KFGame/Classes/KFPerk_Sharpshooter.uc index b8ccb19..c44eb41 100644 --- a/KFGame/Classes/KFPerk_Sharpshooter.uc +++ b/KFGame/Classes/KFPerk_Sharpshooter.uc @@ -125,6 +125,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) @@ -315,7 +317,7 @@ event Destroyed() simulated function bool GetUsingTactialReload( KFWeapon KFW ) { `QALog( "Tactical Reload Active =" @ (IsTacticalReloadActive() && IsWeaponOnPerk( KFW,, self.class )), bLogPerk ); - return IsTacticalReloadActive() && (IsWeaponOnPerk( KFW, , self.class) || IsBackupWeapon( KFW )); + return IsTacticalReloadActive() && (IsWeaponOnPerk( KFW, , self.class) || IsBackupWeapon( KFW ) || IsDual9mm( KFW )); } /** @@ -324,23 +326,29 @@ simulated function bool GetUsingTactialReload( KFWeapon KFW ) */ function float GetStunPowerModifier( optional class DamageType, optional byte HitZoneIdx ) { - if( IsDamageTypeOnPerk(class(DamageType)) ) + if( IsDamageTypeOnPerk(class(DamageType)) && IsStunActive()) { - if( HitZoneIdx == HZI_Head && GetZTStunActive() ) - { - `QALog( "(ZT Stun)" @ GetSkillValue(PerkSkills[ESharpshooterZTStun]), bLogPerk ); - return GetSkillValue( PerkSkills[ESharpshooterZTStun] ); - } - else if( IsStunActive() ) - { - `QALog( "(Stun)" @ GetSkillValue( PerkSkills[ESharpshooterStun] ), bLogPerk ); - return GetSkillValue( PerkSkills[ESharpshooterStun] ); - } + `QALog( "(Stun)" @ GetSkillValue( PerkSkills[ESharpshooterStun] ), bLogPerk ); + return GetSkillValue( PerkSkills[ESharpshooterStun] ); } return 0.f; } +/** + * @brief skills and weapons can guarantee a stun + * @return true/false + */ +function bool IsStunGuaranteed( optional class DamageType, optional byte HitZoneIdx ) +{ + if( IsDamageTypeOnPerk(class(DamageType)) && GetZTStunActive()) + { + return bWasLastHitAHeadshot; + } + + return false; +} + /** * @brief Checks if the Stationary Aim skill is active * diff --git a/KFGame/Classes/KFPerk_Support.uc b/KFGame/Classes/KFPerk_Support.uc index 6c2da9d..716ff4e 100644 --- a/KFGame/Classes/KFPerk_Support.uc +++ b/KFGame/Classes/KFPerk_Support.uc @@ -155,6 +155,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; `QALog( GetFuncName() @ "BaseDamage =" @ InDamage, bLogPerk ); @@ -337,7 +339,7 @@ simulated private static function float GetResupplyMaxSpareAmmoModifier() */ simulated function bool GetUsingTactialReload( KFWeapon KFW ) { - return IsTacticalReloadActive() && (IsWeaponOnPerk( KFW,, self.class ) || IsBackupWeapon( KFW )); + return IsTacticalReloadActive() && (IsWeaponOnPerk( KFW,, self.class ) || IsBackupWeapon( KFW ) || IsDual9mm( KFW )); } /** diff --git a/KFGame/Classes/KFPerk_Survivalist.uc b/KFGame/Classes/KFPerk_Survivalist.uc index b3efbd6..b5a6383 100644 --- a/KFGame/Classes/KFPerk_Survivalist.uc +++ b/KFGame/Classes/KFPerk_Survivalist.uc @@ -142,6 +142,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; TempDamage += InDamage * GetPassiveValue( WeaponDamage, CurrentLevel ); @@ -462,7 +464,7 @@ simulated function float GetAoERadiusModifier() simulated function float GetZedTimeModifier( KFWeapon W ) { local name StateName; - if( GetMadManActive() && !W.IsMeleeWeapon() || KFWeap_MeleeBase(W).default.bHasToBeConsideredAsRangedWeaponForPerks ) + if( GetMadManActive() && (!W.IsMeleeWeapon() || KFWeap_MeleeBase(W).default.bHasToBeConsideredAsRangedWeaponForPerks )) { StateName = W.GetStateName(); `Warn(StateName); @@ -525,18 +527,17 @@ function float GetStumblePowerModifier( optional KFPawn KFP, optional class DamageType, optional byte HitZoneIdx ) +function bool IsStunGuaranteed( optional class DamageType, optional byte HitZoneIdx ) { if( GetIncapMasterActive() ) { - `QALog( "(ZT Stun)" @ (GetSkillValue(PerkSkills[ESharpshooterZTStun]) * 5), bLogPerk ); - return (GetSkillValue( PerkSkills[ESurvivalist_IncapMaster] ) ); + return true; } - return 0.f; + return false; } simulated function float GetSnarePowerModifier( optional class DamageType, optional byte HitZoneIdx ) @@ -849,6 +850,8 @@ DefaultProperties ZedTimeModifyingStates(8)="BlunderbussDeployAndDetonate" ZedTimeModifyingStates(9)="WeaponWindingUp" ZedTimeModifyingStates(10)="MineReconstructorCharge" + ZedTimeModifyingStates(11)="WeaponSonicGunSingleFiring" + ZedTimeModifyingStates(12)="WeaponSonicGunCharging" PrimaryWeaponPaths(0)=class'KFWeapDef_AR15' PrimaryWeaponPaths(1)=class'KFWeapDef_MB500' diff --git a/KFGame/Classes/KFPerk_Swat.uc b/KFGame/Classes/KFPerk_Swat.uc index 658efde..8c60073 100644 --- a/KFGame/Classes/KFPerk_Swat.uc +++ b/KFGame/Classes/KFPerk_Swat.uc @@ -207,7 +207,7 @@ static simulated private function bool Is9mm( KFWeapon KFW ) */ simulated event float GetIronSightSpeedModifier( KFWeapon KFW ) { - if( IsTacticalMovementActive() && (Is9mm( KFW ) || IsWeaponOnPerk( KFW,, self.class )) ) + if( IsTacticalMovementActive() && (Is9mm( KFW ) || IsDual9mm( KFW ) || IsWeaponOnPerk( KFW,, self.class )) ) { `QALog( "Tactical Movement Mod:" @ KFW @ GetSkillValue( PerkSkills[ESWAT_TacticalMovement] ),bLogPerk ); return GetSkillValue( PerkSkills[ESWAT_TacticalMovement] ); @@ -237,7 +237,7 @@ function FinalizeSpeedVariables() */ simulated event float GetCrouchSpeedModifier( KFWeapon KFW ) { - if( IsTacticalMovementActive() && (Is9mm( KFW ) || IsWeaponOnPerk( KFW,, self.class )) ) + if( IsTacticalMovementActive() && (Is9mm( KFW ) || IsDual9mm(KFW) || IsWeaponOnPerk( KFW,, self.class )) ) { `QALog( "Tactical Movement Mod:" @ KFW @ GetSkillValue( PerkSkills[ESWAT_TacticalMovement] ),bLogPerk ); return GetSkillValue( PerkSkills[ESWAT_TacticalMovement] ) * CurrentHealthPenalty; @@ -268,6 +268,8 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local KFWeapon KFW; local float TempDamage; + super.ModifyDamageGiven(InDamage, DamageCauser, MyKFPM, DamageInstigator, DamageType, HitZoneIdx); + TempDamage = InDamage; if( DamageCauser != none ) @@ -277,7 +279,7 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau if( KFW != none ) { - if( IsBackupActive() && (IsBackupWeapon( KFW ) || KFW.Class.Name == 'KFWeap_Pistol_Dual9mm') ) + if( IsBackupActive() && (IsBackupWeapon( KFW ) || IsDual9mm( KFW )) ) { `QALog( "Backup Damage" @ KFW @ GetPercentage( InDamage, InDamage * GetSkillValue(PerkSkills[ESWAT_Backup])), bLogPerk ); TempDamage += InDamage * GetSkillValue( PerkSkills[ESWAT_Backup] ); @@ -356,7 +358,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) local name StateName; StateName = W.GetStateName(); - if( IsRapidAssaultActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class ) || W.IsA('KFWeap_Pistol_Dual9mm') ) ) + if( IsRapidAssaultActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class ) || IsDual9mm( W ) ) ) { if( ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE ) { @@ -380,7 +382,7 @@ function float GetStumblePowerModifier( optional KFPawn KFP, optional class PerkClass) return 0; } +/** hit stat */ +function NotifyHitTaken() +{ + ClientNotifyHitTaken(); +} +native reliable client private function ClientNotifyHitTaken(); + /** Kill stat */ function AddZedKill( class MonsterClass, byte Difficulty, class DT, bool bKiller ) { @@ -11495,6 +11584,22 @@ reliable client function DrawLocalizedTextOnHud(string Message, float DisplayTim } } +function bool CanUseHealObject() +{ + local class KFPowerUpClass; + local KFGameInfo GameInfo; + local bool CanHealPowerUp; + local bool CanHealGameMode; + + GameInfo = KFGameInfo(WorldInfo.Game); + KFPowerUpClass = GetPowerUpClass(); + + CanHealPowerUp = KFPowerUpClass == none || KFPowerUpClass.default.CanBeHealedWhilePowerUpIsActive; + CanHealGameMode = GameInfo == none || GameInfo.OutbreakEvent == none || !GameInfo.OutbreakEvent.ActiveEvent.bCannotBeHealed; + + return CanHealPowerUp && CanHealGameMode; +} + event OnLoginOnOtherPlatformDoneAndFriendsReady() { if (MyGFxManager != none) diff --git a/KFGame/Classes/KFPowerUp_HellishRage_NoCostHeal.uc b/KFGame/Classes/KFPowerUp_HellishRage_NoCostHeal.uc new file mode 100644 index 0000000..0465637 --- /dev/null +++ b/KFGame/Classes/KFPowerUp_HellishRage_NoCostHeal.uc @@ -0,0 +1,14 @@ +//============================================================================= +// KFPowerUp_HellishRage +//============================================================================= +// Base class for the hellish rage power up +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= +class KFPowerUp_HellishRage_NoCostHeal extends KFPowerUp_HellishRage; + +DefaultProperties +{ + HealthCost=0 +} diff --git a/KFGame/Classes/KFProjectileStickHelper_HRGScorcher.uc b/KFGame/Classes/KFProjectileStickHelper_HRGScorcher.uc index e3cd730..11633f9 100644 --- a/KFGame/Classes/KFProjectileStickHelper_HRGScorcher.uc +++ b/KFGame/Classes/KFProjectileStickHelper_HRGScorcher.uc @@ -100,7 +100,7 @@ simulated function bool GetImpactResult(Actor HitActor, PrimitiveComponent HitCo // NOTE: Door actors fall into this category! // pass through meshes that can move - return !StaticMeshComp.CanBecomeDynamic(); + return true; } KFP = KFPawn_Human(HitActor); @@ -108,16 +108,16 @@ simulated function bool GetImpactResult(Actor HitActor, PrimitiveComponent HitCo { // bounce off of player pawns, stick to other pawns return false; - } + } D = KFDestructibleActor(HitActor); if (D != none) { - + // don't react to client-side-only destructibles, stick to others return D.ReplicationMode != RT_ClientSide; - } + } return true; diff --git a/KFGame/Classes/KFSeasonalEventStats.uc b/KFGame/Classes/KFSeasonalEventStats.uc index 27016e6..6c851be 100644 --- a/KFGame/Classes/KFSeasonalEventStats.uc +++ b/KFGame/Classes/KFSeasonalEventStats.uc @@ -71,4 +71,5 @@ simulated event OnGameEnd(class GameClass); simulated function OnBossDied(); simulated event OnWaveCompleted(class GameClass, int Difficulty, int WaveNum); simulated event OnTriggerUsed(class TriggerClass); -simulated event OnTryCompleteObjective(int ObjectiveIndex, int EventIndex); \ No newline at end of file +simulated event OnTryCompleteObjective(int ObjectiveIndex, int EventIndex); +simulated function OnHitTaken(); \ No newline at end of file diff --git a/KFGame/Classes/KFUnlockManager.uc b/KFGame/Classes/KFUnlockManager.uc index af95461..c588b0f 100644 --- a/KFGame/Classes/KFUnlockManager.uc +++ b/KFGame/Classes/KFUnlockManager.uc @@ -27,6 +27,7 @@ enum ESharedContentUnlock SCU_Minigun, SCU_MineReconstructor, SCU_FrostFang, + SCU_GravityImploder, }; @@ -325,4 +326,8 @@ defaultproperties Name=KFWeap_Rifle_FrostShotgunAxe, IconPath="WEP_UI_Frost_Shotgun_Axe_TEX.UI_WeaponSelect_FrostGun", ID=8609)} + SharedContentList(SCU_GravityImploder)={( + Name=KFWeap_GravityImploder, + IconPath="WEP_UI_Gravity_Imploder_TEX.UI_WeaponSelect_Gravity_Imploder", + ID=8778)} } diff --git a/KFGame/Classes/KFWeapDef_Bullpup.uc b/KFGame/Classes/KFWeapDef_Bullpup.uc index 5bae35e..62af103 100644 --- a/KFGame/Classes/KFWeapDef_Bullpup.uc +++ b/KFGame/Classes/KFWeapDef_Bullpup.uc @@ -15,7 +15,7 @@ DefaultProperties WeaponClassPath="KFGameContent.KFWeap_AssaultRifle_Bullpup" BuyPrice=650 - AmmoPricePerMag=30 + AmmoPricePerMag=32 //30 ImagePath="ui_weaponselect_tex.UI_WeaponSelect_Bullpup" EffectiveRange=68 diff --git a/KFGame/Classes/KFWeapDef_GravityImploder.uc b/KFGame/Classes/KFWeapDef_GravityImploder.uc new file mode 100644 index 0000000..daf86ca --- /dev/null +++ b/KFGame/Classes/KFWeapDef_GravityImploder.uc @@ -0,0 +1,28 @@ +//============================================================================= +// KFWeapDef_GravityImploder +//============================================================================= +// A lightweight container for basic weapon properties that can be safely +// accessed without a weapon actor (UI, remote clients). +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFWeapDef_GravityImploder extends KFWeaponDefinition + abstract; + +defaultproperties +{ + WeaponClassPath="KFGameContent.KFWeap_GravityImploder" + + BuyPrice=2000 + + AmmoPricePerMag=70//40 + + ImagePath="WEP_UI_Gravity_Imploder_TEX.UI_WeaponSelect_Gravity_Imploder" + + EffectiveRange=95 // Based on comment Slightly less than M79 Grenade Launcher + + SharedUnlockId=SCU_GravityImploder +} + diff --git a/KFGame/Classes/KFWeapDef_HRG_SonicGun.uc b/KFGame/Classes/KFWeapDef_HRG_SonicGun.uc new file mode 100644 index 0000000..d5d1d5d --- /dev/null +++ b/KFGame/Classes/KFWeapDef_HRG_SonicGun.uc @@ -0,0 +1,25 @@ +//============================================================================= +// KFWeapDef_HRG_SonicGun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFWeapDef_HRG_SonicGun extends KFWeaponDefinition + abstract; + +DefaultProperties +{ + WeaponClassPath="KFGameContent.KFWeap_HRG_SonicGun" + + BuyPrice=1100 + AmmoPricePerMag=65 //75 + ImagePath="WEP_UI_HRG_SonicGun_TEX.UI_WeaponSelect_HRG_SonicGun" + + EffectiveRange=70 + + UpgradePrice[0]=700 + UpgradePrice[1]=1500 + + UpgradeSellPrice[0]=525 + UpgradeSellPrice[1]=1650 +} diff --git a/KFGame/Classes/KFWeap_HealerBase.uc b/KFGame/Classes/KFWeap_HealerBase.uc index e495f9d..39030f9 100644 --- a/KFGame/Classes/KFWeap_HealerBase.uc +++ b/KFGame/Classes/KFWeap_HealerBase.uc @@ -440,7 +440,6 @@ simulated function UpdateInteractionMessage() { local KFPlayerController InstigatorKFPC; local bool bCannotBeHealed; - local KFPowerUp PowerUp; //Update Interaction message if (Instigator != none && Instigator.IsLocallyControlled() && Instigator.Health > 0) @@ -452,9 +451,8 @@ simulated function UpdateInteractionMessage() return; } - //Check if we have a power up that disables healing - PowerUp = InstigatorKFPC.GetPowerUp(); - bCannotBeHealed = PowerUp != none && !PowerUp.CanBeHealedWhilePowerUpIsActive; + //Check if the player can heal + bCannotBeHealed = !InstigatorKFPC.CanUseHealObject(); if (bIsQuickHealMessageShowing) { diff --git a/KFGame/Classes/KFWeaponSkinList.uc b/KFGame/Classes/KFWeaponSkinList.uc index 7583293..b3512c4 100644 --- a/KFGame/Classes/KFWeaponSkinList.uc +++ b/KFGame/Classes/KFWeaponSkinList.uc @@ -3406,4 +3406,120 @@ defaultproperties //8614 Frost Fang | Burned Land Skins.Add((Id=8614, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_SkinSet39_MAT.Wep_1stP_Frost_Shotgun_BurnedLand_MIC"), MIC_3P="WEP_SkinSet39_MAT.Wep_3stP_Frost_Shotgun_BurnedLand_MIC", MIC_Pickup="WEP_SkinSet39_MAT.Wep_3rdP_Frost_Shotgun_BurnedLand_Pickup_MIC")) +//Neon Caulk n Burn + Skins.Add((Id=8654, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet40_MAT.neon_caulkburn.Neon_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_caulkburn.Neon_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_caulkburn.Neon_CaulkBurn_3P_Pickup_MIC")) + +//Neon Crovel + Skins.Add((Id=8655, Weapondef=class'KFWeapDef_Crovel', MIC_1P=("WEP_SkinSet40_MAT.neon_crovel.Neon_Crovel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_crovel.Neon_Crovel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_crovel.Neon_Crovel_3P_Pickup_MIC")) + +//Neon HX25 + Skins.Add((Id=8656, Weapondef=class'KFWeapDef_HX25', MIC_1P=("WEP_SkinSet40_MAT.neon_hx25.Neon_HX25_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_hx25.Neon_HX25_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_hx25.Neon_HX25_3P_Pickup_MIC")) + +//Neon MP5RAS + Skins.Add((Id=8657, Weapondef=class'KFWeapDef_MP5RAS', MIC_1P=("WEP_SkinSet40_MAT.neon_mp5ras.Neon_MP5RAS_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_mp5ras.Neon_MP5RAS_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_mp5ras.Neon_MP5RAS_3P_Pickup_MIC")) + +//Neon 1858 Revolver + Skins.Add((Id=8658, Weapondef=class'KFWeapDef_Remington1858', MIC_1P=("WEP_SkinSet40_MAT.neon_remington1858.Neon_Remington1858_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_remington1858.Neon_Remington1858_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_remington1858.Neon_Remington1858_3P_Pickup_MIC")) + +//Neon Eviscerator + Skins.Add((Id=8659, Weapondef=class'KFWeapDef_Eviscerator', MIC_1P=("WEP_SkinSet40_MAT.neon_sawblade.Neon_SawBlade_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_sawblade.Neon_SawBlade_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_sawblade.Neon_SawBlade_3P_Pickup_MIC")) + +//Neon Berserker Knife + Skins.Add((Id=8660, Weapondef=class'KFWeapDef_Knife_Berserker', MIC_1P=("WEP_SkinSet40_MAT.neon_berserkerknife.Neon_BerserkerKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_berserkerknife.Neon_BerserkerKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_berserkerknife.Neon_BerserkerKnife_3P_Pickup_MIC")) + +//Neon KF-BAR + Skins.Add((Id=8661, Weapondef=class'KFWeapDef_Knife_Commando', MIC_1P=("WEP_SkinSet40_MAT.neon_commandoknife.Neon_CommandoKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_commandoknife.Neon_CommandoKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_commandoknife.Neon_CommandoKnife_3P_Pickup_MIC")) + +//Neon Demo Knife + Skins.Add((Id=8662, Weapondef=class'KFWeapDef_Knife_Demo', MIC_1P=("WEP_SkinSet40_MAT.neon_demoknife.Neon_DemoKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_demoknife.Neon_DemoKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_demoknife.Neon_DemoKnife_3P_Pickup_MIC")) + +//Neon Firemans Knife + Skins.Add((Id=8663, Weapondef=class'KFWeapDef_Knife_Firebug', MIC_1P=("WEP_SkinSet40_MAT.neon_firebugknife.Neon_FirebugKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_firebugknife.Neon_FirebugKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_firebugknife.Neon_FirebugKnife_3P_Pickup_MIC")) + +//Neon Gunslinger Knife + Skins.Add((Id=8664, Weapondef=class'KFWeapDef_Knife_Gunslinger', MIC_1P=("WEP_SkinSet40_MAT.neon_gunslingerknife.Neon_GunslingerKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_gunslingerknife.Neon_GunslingerKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_gunslingerknife.Neon_GunslingerKnife_3P_Pickup_MIC")) + +//Neon HMTech-001 Scalpel + Skins.Add((Id=8665, Weapondef=class'KFWeapDef_Knife_Medic', MIC_1P=("WEP_SkinSet40_MAT.neon_medicknife.Neon_MedicKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_medicknife.Neon_MedicKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_medicknife.Neon_MedicKnife_3P_Pickup_MIC")) + +//Neon Kukri + Skins.Add((Id=8666, Weapondef=class'KFWeapDef_Knife_Sharpshooter', MIC_1P=("WEP_SkinSet40_MAT.neon_sharpshooterknife.Neon_SharpshooterKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_sharpshooterknife.Neon_SharpshooterKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_sharpshooterknife.Neon_SharpshooterKnife_3P_Pickup_MIC")) + +//Neon Support Knife + Skins.Add((Id=8667, Weapondef=class'KFWeapDef_Knife_Support', MIC_1P=("WEP_SkinSet40_MAT.neon_supportknife.Neon_SupportKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_supportknife.Neon_SupportKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_supportknife.Neon_SupportKnife_3P_Pickup_MIC")) + +//Neon Gore Shiv + Skins.Add((Id=8668, Weapondef=class'KFWeapDef_Knife_Survivalist', MIC_1P=("WEP_SkinSet40_MAT.neon_survivalistknife.Neon_SurvivalistKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_survivalistknife.Neon_SurvivalistKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_survivalistknife.Neon_SurvivalistKnife_3P_Pickup_MIC")) + +//Neon Tactical Knife + Skins.Add((Id=8669, Weapondef=class'KFWeapDef_Knife_SWAT', MIC_1P=("WEP_SkinSet40_MAT.neon_swatknife.Neon_SWATKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neon_swatknife.Neon_SWATKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neon_swatknife.Neon_SWATKnife_3P_Pickup_MIC")) + +//NeonRGB Caulk n Burn + Skins.Add((Id=8670, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_caulkburn.NeonRGB_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_caulkburn.NeonRGB_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_caulkburn.NeonRGB_CaulkBurn_3P_Pickup_MIC")) + +//NeonRGB Crovel + Skins.Add((Id=8671, Weapondef=class'KFWeapDef_Crovel', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_crovel.NeonRGB_Crovel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_crovel.NeonRGB_Crovel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_crovel.NeonRGB_Crovel_3P_Pickup_MIC")) + +//NeonRGB HX25 + Skins.Add((Id=8672, Weapondef=class'KFWeapDef_HX25', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_hx25.NeonRGB_HX25_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_hx25.NeonRGB_HX25_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_hx25.NeonRGB_HX25_3P_Pickup_MIC")) + +//NeonRGB MP5RAS + Skins.Add((Id=8673, Weapondef=class'KFWeapDef_MP5RAS', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_mp5ras.NeonRGB_MP5RAS_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_mp5ras.NeonRGB_MP5RAS_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_mp5ras.NeonRGB_MP5RAS_3P_Pickup_MIC")) + +//NeonRGB 1858 Revolver + Skins.Add((Id=8674, Weapondef=class'KFWeapDef_Remington1858', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_remington1858.NeonRGB_Remington1858_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_remington1858.NeonRGB_Remington1858_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_remington1858.NeonRGB_Remington1858_3P_Pickup_MIC")) + +//NeonRGB Eviscerator + Skins.Add((Id=8675, Weapondef=class'KFWeapDef_Eviscerator', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_sawblade.NeonRGB_SawBlade_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_sawblade.NeonRGB_SawBlade_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_sawblade.NeonRGB_SawBlade_3P_Pickup_MIC")) + +//NeonRGB Berserker Knife + Skins.Add((Id=8676, Weapondef=class'KFWeapDef_Knife_Berserker', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_berserkerknife.NeonRGB_BerserkerKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_berserkerknife.NeonRGB_BerserkerKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_berserkerknife.NeonRGB_BerserkerKnife_3P_Pickup_MIC")) + +//NeonRGB KF-BAR + Skins.Add((Id=8677, Weapondef=class'KFWeapDef_Knife_Commando', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_commandoknife.NeonRGB_CommandoKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_commandoknife.NeonRGB_CommandoKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_commandoknife.NeonRGB_CommandoKnife_3P_Pickup_MIC")) + +//NeonRGB Demo Knife + Skins.Add((Id=8678, Weapondef=class'KFWeapDef_Knife_Demo', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_demoknife.NeonRGB_DemoKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_demoknife.NeonRGB_DemoKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_demoknife.NeonRGB_DemoKnife_3P_Pickup_MIC")) + +//NeonRGB Firemans Knife + Skins.Add((Id=8679, Weapondef=class'KFWeapDef_Knife_Firebug', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_firebugknife.NeonRGB_FirebugKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_firebugknife.NeonRGB_FirebugKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_firebugknife.NeonRGB_FirebugKnife_3P_Pickup_MIC")) + +//NeonRGB Gunslinger Knife + Skins.Add((Id=8680, Weapondef=class'KFWeapDef_Knife_Gunslinger', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_gunslingerknife.NeonRGB_GunslingerKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_gunslingerknife.NeonRGB_GunslingerKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_gunslingerknife.NeonRGB_GunslingerKnife_3P_Pickup_MIC")) + +//NeonRGB HMTech-001 Scalpel + Skins.Add((Id=8681, Weapondef=class'KFWeapDef_Knife_Medic', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_medicknife.NeonRGB_MedicKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_medicknife.NeonRGB_MedicKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_medicknife.NeonRGB_MedicKnife_3P_Pickup_MIC")) + +//NeonRGB Kukri + Skins.Add((Id=8682, Weapondef=class'KFWeapDef_Knife_Sharpshooter', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_sharpshooterknife.NeonRGB_SharpshooterKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_sharpshooterknife.NeonRGB_SharpshooterKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_sharpshooterknife.NeonRGB_SharpshooterKnife_3P_Pickup_MIC")) + +//NeonRGB Support Knife + Skins.Add((Id=8683, Weapondef=class'KFWeapDef_Knife_Support', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_supportknife.NeonRGB_SupportKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_supportknife.NeonRGB_SupportKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_supportknife.NeonRGB_SupportKnife_3P_Pickup_MIC")) + +//NeonRGB Gore Shiv + Skins.Add((Id=8684, Weapondef=class'KFWeapDef_Knife_Survivalist', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_survivalistknife.NeonRGB_SurvivalistKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_survivalistknife.NeonRGB_SurvivalistKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_survivalistknife.NeonRGB_SurvivalistKnife_3P_Pickup_MIC")) + +//NeonRGB Tactical Knife + Skins.Add((Id=8685, Weapondef=class'KFWeapDef_Knife_SWAT', MIC_1P=("WEP_SkinSet40_MAT.neonrgb_swatknife.NeonRGB_SWATKnife_1P_Mint_MIC"), MIC_3P="WEP_SkinSet40_MAT.neonrgb_swatknife.NeonRGB_SWATKnife_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet40_MAT.neonrgb_swatknife.NeonRGB_SWATKnife_3P_Pickup_MIC")) + +//GravityImploder Standard + Skins.Add((Id=8778, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_1P_Gravity_Imploder_MAT.Wep_1stP_Gravity_Imploder_MIC"), MIC_3P="WEP_3P_Gravity_Imploder_MAT.Wep_3rdP_Gravity_Imploder_MIC", MIC_Pickup="WEP_3p_Gravity_Imploder_MAT.Wep_3rdP_Gravity_Imploder_Pickup_MIC")) + +//GravityImploder Area51 + Skins.Add((Id=8779, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_SkinSet41_MAT.WEP_SkinSet_1stP_Gravity_Imploder_Area51_MIC"), MIC_3P="WEP_SkinSet41_MAT.Wep_SkinSet_3rdP_Gravity_Imploder_Area51_MIC", MIC_Pickup="WEP_SkinSet41_MAT.Wep_3rdP_Gravity_Imploder_Pickup_Area51_MIC")); + +//GravityImploder Banzai + Skins.Add((Id=8780, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_SkinSet41_MAT.WEP_SkinSet_1stP_Gravity_Imploder_Banzai_MIC"), MIC_3P="WEP_SkinSet41_MAT.Wep_SkinSet_3rdP_Gravity_Imploder_Banzai_MIC", MIC_Pickup="WEP_SkinSet41_MAT.Wep_3rdP_Gravity_Imploder_Pickup_Banzai_MIC")); + +//GravityImploder Jungle + Skins.Add((Id=8781, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_SkinSet41_MAT.WEP_SkinSet_1stP_Gravity_Imploder_Cambodia_MIC"), MIC_3P="WEP_SkinSet41_MAT.Wep_SkinSet_3rdP_Gravity_Imploder_Cambodia_MIC", MIC_Pickup="WEP_SkinSet41_MAT.Wep_3rdP_Gravity_Imploder_Pickup_Cambodia_MIC")); + +//GravityImploder High Tech + Skins.Add((Id=8782, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_SkinSet41_MAT.WEP_SkinSet_1stP_Gravity_Imploder_HighTech_MIC"), MIC_3P="WEP_SkinSet41_MAT.Wep_SkinSet_3rdP_Gravity_Imploder_HighTech_MIC", MIC_Pickup="WEP_SkinSet41_MAT.Wep_3rdP_Gravity_Imploder_Pickup_HighTech_MIC")); + +//GravityImploder Rust + Skins.Add((Id=8783, Weapondef=class'KFWeapDef_GravityImploder', MIC_1P=("WEP_SkinSet41_MAT.WEP_SkinSet_1stP_Gravity_Imploder_Rust_MIC"), MIC_3P="WEP_SkinSet41_MAT.Wep_SkinSet_3rdP_Gravity_Imploder_Rust_MIC", MIC_Pickup="WEP_SkinSet41_MAT.Wep_3rdP_Gravity_Imploder_Pickup_Rust_MIC")); + +//Coliseum Zweihander + Skins.Add((Id=8791, Weapondef=class'KFWeapDef_Zweihander', MIC_1P=("WEP_SkinSet42_MAT.coliseum_zweihander.Coliseum_Zweihander_1P_Mint_MIC"), MIC_3P="WEP_SkinSet42_MAT.coliseum_zweihander.Coliseum_Zweihander_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet42_MAT.coliseum_zweihander.Coliseum_Zweihander_3P_Pickup_MIC")); } \ No newline at end of file diff --git a/KFGame/Classes/KFZedArmorInfo.uc b/KFGame/Classes/KFZedArmorInfo.uc index 522ddd2..f74a182 100644 --- a/KFGame/Classes/KFZedArmorInfo.uc +++ b/KFGame/Classes/KFZedArmorInfo.uc @@ -332,11 +332,20 @@ function float GetArmorDamageTypeModifier(class DT) { DamageModifier = FMax(Lerp(1.f, DamageModifier, GameResistancePct), 0.f); } - + + if(DT.default.ArmorDamageModifier != 1) + { + DamageModifier *= DT.default.ArmorDamageModifier; + } + return DamageModifier; } } - + + if(DT.default.ArmorDamageModifier != 1) + { + return DT.default.ArmorDamageModifier; + } return 1.f; } diff --git a/KFGame/KFOnlineStats.uci b/KFGame/KFOnlineStats.uci index 17c2dd2..ff34c37 100644 --- a/KFGame/KFOnlineStats.uci +++ b/KFGame/KFOnlineStats.uci @@ -152,4 +152,5 @@ const STATID_ACHIEVE_BiolapseCollectibles = 4054; const STATID_ACHIEVE_DesolationCollectibles = 4055; const STATID_ACHIEVE_HellmarkStationCollectibles = 4056; const STATID_ACHIEVE_ElysiumEndlessWaveFifteen = 4057; +const STATID_ACHIEVE_Dystopia2029Collectibles = 4058; /** `endif */ diff --git a/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpact.uc b/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpact.uc new file mode 100644 index 0000000..0cc5213 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpact.uc @@ -0,0 +1,24 @@ +//============================================================================= +// KFDT_Ballistic_GravityImploderImpact +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_GravityImploderImpact extends KFDT_Ballistic_Shell + abstract + hidedropdown; + +defaultproperties +{ + KDamageImpulse=2000 + KDeathUpKick=750 + KDeathVel=1500 + StumblePower=250 + KnockdownPower=50 + GunHitPower=150 + + WeaponDef=class'KFWeapDef_GravityImploder' + + ModifierPerkList(0)=class'KFPerk_Demolitionist' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpactAlt.uc b/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpactAlt.uc new file mode 100644 index 0000000..e381c5e --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_GravityImploderImpactAlt.uc @@ -0,0 +1,23 @@ +//============================================================================= +// KFDT_Ballistic_GravityImploderImpactAlt +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_GravityImploderImpactAlt extends KFDT_Ballistic_Shell + abstract + hidedropdown; + +defaultproperties +{ + KDamageImpulse=2000 + KDeathUpKick=750 + KDeathVel=1500 + StumblePower=250 + GunHitPower=150 + + WeaponDef=class'KFWeapDef_GravityImploder' + + ModifierPerkList(0)=class'KFPerk_Demolitionist' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged.uc new file mode 100644 index 0000000..c1cf38e --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged.uc @@ -0,0 +1,46 @@ +//============================================================================= +// KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged +//============================================================================= +// Sonic Boom impact damage for the HRG Sonic Gun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged extends KFDT_Ballistic_Rifle + abstract + hidedropdown; + +/** 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) + { + return; + } + + super.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator); +} + +defaultproperties +{ + OverrideImpactEffect=ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_SonicGun_Impact_AltFire' + OverrideImpactSound=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Hit_Surface' + ArmorDamageModifier=1.5f + + KDamageImpulse=0 + KDeathUpKick=0 + KDeathVel=0 + RadialDamageImpulse=5000 + bExtraMomentumZ=True + + StumblePower=250 + GunHitPower=120 + MicrowavePower=25 + bHasToSpawnMicrowaveFire=false + + EffectGroup=FXG_MicrowaveBlast + ModifierPerkList(0)=class'KFPerk_Sharpshooter' + + WeaponDef=class'KFWeapDef_HRG_SonicGun' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged.uc new file mode 100644 index 0000000..243de15 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged.uc @@ -0,0 +1,46 @@ +//============================================================================= +// KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged +//============================================================================= +// Sonic Boom impact damage for the HRG Sonic Gun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged extends KFDT_Ballistic_Rifle + abstract + hidedropdown; + +/** 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) + { + return; + } + + super.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator); +} + +defaultproperties +{ + OverrideImpactEffect=ParticleSystem'WEP_Microwave_Assault_EMIT.FX_Microwave_Assault_Impact' + OverrideImpactSound=AkEvent'WW_WEP_SA_DragonsBreath.Play_Bullet_DragonsBreath_Impact_Dirt' + ArmorDamageModifier=1.5f + + KDamageImpulse=0 + KDeathUpKick=0 + KDeathVel=0 + RadialDamageImpulse=5000 + bExtraMomentumZ=True + + StumblePower=50 + GunHitPower=60 + MicrowavePower=50 + bHasToSpawnMicrowaveFire=false + + EffectGroup=FXG_MicrowaveBlast + ModifierPerkList(0)=class'KFPerk_Sharpshooter' + + WeaponDef=class'KFWeapDef_HRG_SonicGun' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged.uc new file mode 100644 index 0000000..69a78d6 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged.uc @@ -0,0 +1,47 @@ +//============================================================================= +// KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged +//============================================================================= +// Sonic Boom impact damage for the HRG Sonic Gun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged extends KFDT_Ballistic_Rifle + abstract + hidedropdown; + +/** 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) + { + return; + } + + super.PlayImpactHitEffects(P, HitLocation, HitDirection, HitZoneIndex, HitInstigator); +} +defaultproperties +{ + OverrideImpactEffect=ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_SonicGun_Impact' + OverrideImpactSound=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Hit_Surface' + ArmorDamageModifier=1.5f + + KDamageImpulse=0 + KDeathUpKick=0 + KDeathVel=0 + RadialDamageImpulse=5000 + bExtraMomentumZ=True + + StumblePower=0 + GunHitPower=30 + MicrowavePower=75 + bHasToSpawnMicrowaveFire=false + + EffectGroup=FXG_MicrowaveBlast + bCanObliterate=true + bCanGib=true + ModifierPerkList(0)=class'KFPerk_Sharpshooter' + + WeaponDef=class'KFWeapDef_HRG_SonicGun' +} diff --git a/KFGameContent/Classes/KFDT_Bludgeon_GravityImploder.uc b/KFGameContent/Classes/KFDT_Bludgeon_GravityImploder.uc new file mode 100644 index 0000000..4289fb8 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_GravityImploder.uc @@ -0,0 +1,15 @@ +//============================================================================= +// KFDT_Bludgeon_GravityImploder +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2017 Tripwire Interactive LLC +//============================================================================= +class KFDT_Bludgeon_GravityImploder extends KFDT_Bludgeon_RifleButt + abstract + hidedropdown; + +DefaultProperties +{ + //defaults + WeaponDef=class'KFWeapDef_GravityImploder' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Bludgeon_HRG_SonicGun.uc b/KFGameContent/Classes/KFDT_Bludgeon_HRG_SonicGun.uc new file mode 100644 index 0000000..1868fe9 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_HRG_SonicGun.uc @@ -0,0 +1,16 @@ +//============================================================================= +// KFDT_Bludgeon_HRG_SonicGun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2017 Tripwire Interactive LLC +//============================================================================= +class KFDT_Bludgeon_HRG_SonicGun extends KFDT_Bludgeon_RifleButt + abstract + hidedropdown; + +DefaultProperties +{ + ModifierPerkList(0)=class'KFPerk_Survivalist' + //defaults + WeaponDef=class'KFWeapDef_HRG_SonicGun' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Explosive_GravityImploder.uc b/KFGameContent/Classes/KFDT_Explosive_GravityImploder.uc new file mode 100644 index 0000000..645e8a7 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Explosive_GravityImploder.uc @@ -0,0 +1,33 @@ +//============================================================================= +// KFDT_Explosive_GravityImploder +//============================================================================= +// Explosive damage type for the Gravity Imploder explosion +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Explosive_GravityImploder extends KFDT_Explosive + abstract + hidedropdown; + +defaultproperties +{ + bShouldSpawnPersistentBlood=true + + // physics impact + //GibImpulseScale=0.9 + //KDeathUpKick=1000 + //KDeathVel=300 + //RadialDamageImpulse=-1000 + //KDamageImpulse=550 + RadialDamageImpulse=-200 + GibImpulseScale=0.85 + KDeathUpKick=-200 + KDeathVel=200 + StumblePower=200 + + ModifierPerkList(0)=class'KFPerk_Demolitionist' + + WeaponDef=class'KFWeapDef_GravityImploder' +} diff --git a/KFGameContent/Classes/KFDT_Explosive_GravityImploderWave.uc b/KFGameContent/Classes/KFDT_Explosive_GravityImploderWave.uc new file mode 100644 index 0000000..7750046 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Explosive_GravityImploderWave.uc @@ -0,0 +1,29 @@ +//============================================================================= +// KFDT_Explosive_GravityImploderWave +//============================================================================= +// Explosive damage type for the Gravity Imploder shockwave +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Explosive_GravityImploderWave extends KFDT_Explosive + abstract + hidedropdown; + +defaultproperties +{ + bShouldSpawnPersistentBlood=true + + // physics impact + RadialDamageImpulse=3000 //5000 //20000 + GibImpulseScale=0.15 + KDeathUpKick=1000 + KDeathVel=300 + + KnockdownPower=400 + + //Perk + ModifierPerkList(0)=class'KFPerk_Demolitionist' + WeaponDef=class'KFWeapDef_GravityImploder' +} diff --git a/KFGameContent/Classes/KFDT_Freeze_FreezeThrower_IceShards.uc b/KFGameContent/Classes/KFDT_Freeze_FreezeThrower_IceShards.uc index 5588fc8..6df53c9 100644 --- a/KFGameContent/Classes/KFDT_Freeze_FreezeThrower_IceShards.uc +++ b/KFGameContent/Classes/KFDT_Freeze_FreezeThrower_IceShards.uc @@ -6,11 +6,15 @@ // Killing Floor 2 // Copyright (C) 2016 Tripwire Interactive LLC //============================================================================= -class KFDT_Freeze_FreezeThrower_IceShards extends KFDT_Freeze +class KFDT_Freeze_FreezeThrower_IceShards extends KFDT_Ballistic_Shotgun abstract; defaultproperties { + KDamageImpulse=500 + KDeathUpKick=-500 + KDeathVel=350 + WeaponDef=class'KFWeapDef_FreezeThrower' FreezePower=0 StumblePower=25 diff --git a/KFGameContent/Classes/KFDT_Piercing_Crossbow.uc b/KFGameContent/Classes/KFDT_Piercing_Crossbow.uc index dcfa0ec..eba9ae3 100644 --- a/KFGameContent/Classes/KFDT_Piercing_Crossbow.uc +++ b/KFGameContent/Classes/KFDT_Piercing_Crossbow.uc @@ -11,16 +11,17 @@ class KFDT_Piercing_Crossbow extends KFDT_Piercing abstract hidedropdown; +var float HeadStunPower; + defaultproperties { KDamageImpulse=1500 KDeathUpKick=250 KDeathVel=150 - - KnockdownPower=20 - StunPower=101 //90 + HeadStunPower=1000 // Stun ensured when hit in the head + StunPower=30 // Stun used otherwise StumblePower=250 GunHitPower=100 MeleeHitPower=40 diff --git a/KFGameContent/Classes/KFExplosion_GravityImplosion.uc b/KFGameContent/Classes/KFExplosion_GravityImplosion.uc new file mode 100644 index 0000000..2644df2 --- /dev/null +++ b/KFGameContent/Classes/KFExplosion_GravityImplosion.uc @@ -0,0 +1,15 @@ +//============================================================================= +// KFExplosion_GravityImplosion +//============================================================================= +// Implosive damage type for the Gravity Imploder "explosion" +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFExplosion_GravityImplosion extends KFExplosionActor; + +defaultproperties +{ +} + diff --git a/KFGameContent/Classes/KFGameInfo_Survival.uc b/KFGameContent/Classes/KFGameInfo_Survival.uc index e63a7b4..c51ace8 100644 --- a/KFGameContent/Classes/KFGameInfo_Survival.uc +++ b/KFGameContent/Classes/KFGameInfo_Survival.uc @@ -41,6 +41,8 @@ var byte WaveMax; // The "end" wave var int WaveNum; // The wave we are currently in var bool bHumanDeathsLastWave; //Track this separate from player count in case someone dies and leaves var int ObjectiveSpawnDelay; // How long should the first wave be delayed if there is an active objective. +// The boss waves spams the WaveEnd functions, adding this to prevent it (was affecting seasonal events). +var protected transient bool bWaveStarted; /** Whether this game mode should play music from the get-go (lobby) */ static function bool ShouldPlayMusicAtStart() @@ -935,15 +937,17 @@ function ResetAllPickups() /** Overridden to scale the number of active pickups by wave */ function ResetPickups( array PickupList, int NumPickups ) { - NumPickups *= (float(WaveNum) / float(WaveMax)); - - // make sure to have at least 1 ammo pickup in the level, and if it's wave 2 or later make sure there's - // at least one weapon pickup - if( NumPickups == 0 && PickupList.Length > 0 && (WaveNum > 1 || KFPickupFactory_Ammo(PickupList[0]) != none) ) + if(NumPickups != 0) { - NumPickups = 1; + NumPickups *= (float(WaveNum) / float(WaveMax)); + + // make sure to have at least 1 ammo pickup in the level, and if it's wave 2 or later make sure there's + // at least one weapon pickup + if( NumPickups == 0 && PickupList.Length > 0 && (WaveNum > 1 || KFPickupFactory_Ammo(PickupList[0]) != none) ) + { + NumPickups = 1; + } } - super.ResetPickups( PickupList, NumPickups ); } @@ -1071,6 +1075,8 @@ function WaveStarted() //So the server browser can have our new wave information UpdateGameSettings(); + + bWaveStarted = true; } /** Do something when there are no AIs left */ @@ -1111,6 +1117,9 @@ function WaveEnded(EWaveEndCondition WinCondition) local int i; local KFPlayerController KFPC; + if(!bWaveStarted) + return; + if (WorldInfo.NetMode == NM_DedicatedServer) { scripttrace(); @@ -1182,6 +1191,7 @@ function WaveEnded(EWaveEndCondition WinCondition) // To allow any statistics that are recorded on the very last zed killed at the end of the wave, // wait a single frame to allow them to finalize. SetTimer( WorldInfo.DeltaSeconds, false, nameOf(Timer_FinalizeEndOfWaveStats) ); + bWaveStarted=false; } /** All stats should be finalized here */ @@ -1822,7 +1832,8 @@ DefaultProperties AARDisplayDelay=15 bCanPerkAlwaysChange=false MaxGameDifficulty=3 - + bWaveStarted=false + ObjectiveSpawnDelay=5 SpawnManagerClasses(0)=class'KFGame.KFAISpawnManager_Short' @@ -1871,35 +1882,35 @@ DefaultProperties // Short Wave LateArrivalStarts(0)={( - StartingDosh[0]=550, - StartingDosh[1]=650, - StartingDosh[2]=1200, - StartingDosh[3]=1500 + StartingDosh[0]=700, //550 + StartingDosh[1]=850, //650 + StartingDosh[2]=1650, //1200 + StartingDosh[3]=2200 //1500 )} // Normal Wave LateArrivalStarts(1)={( - StartingDosh[0]=450, - StartingDosh[1]=600, - StartingDosh[2]=750, - StartingDosh[3]=800, - StartingDosh[4]=1100, - StartingDosh[5]=1400, - StartingDosh[6]=1500, - StartingDosh[7]=1600 + StartingDosh[0]=600, //450 + StartingDosh[1]=800, //600 + StartingDosh[2]=1000, //750 + StartingDosh[3]=1100, //800 + StartingDosh[4]=1500, //1100 + StartingDosh[5]=2000, //1400 + StartingDosh[6]=2200, //1500 + StartingDosh[7]=2400 //1600 )} // Long Wave LateArrivalStarts(2)={( - StartingDosh[0]=450, - StartingDosh[1]=550, - StartingDosh[2]=750, - StartingDosh[3]=1000, - StartingDosh[4]=1200, - StartingDosh[5]=1300, - StartingDosh[6]=1400, - StartingDosh[7]=1500, - StartingDosh[8]=1600, - StartingDosh[9]=1600 + StartingDosh[0]=600, //450 + StartingDosh[1]=700, //550 + StartingDosh[2]=1000, //750 + StartingDosh[3]=1300, //1000 + StartingDosh[4]=1650, //1200 + StartingDosh[5]=1800, //1300 + StartingDosh[6]=2000, //1400 + StartingDosh[7]=2200, //1500 + StartingDosh[8]=2400, //1600 + StartingDosh[9]=2400 //1600 )} } diff --git a/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc b/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc index 065723a..047cbc9 100644 --- a/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc +++ b/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc @@ -129,6 +129,13 @@ function SetPickupItemList() //So many loops foreach AllActors(class'KFPickupFactory_Item', ItemFactory) { + //we dont want item pickups, so kiss them goodbye + if(OutbreakEvent.ActiveEvent.OverrideItemPickupModifier == 0) + { + ItemFactory.ShutDown(); + ItemFactory.ItemPickups.Remove(0, ItemFactory.ItemPickups.Length); + continue; + } foreach OutbreakEvent.ActiveEvent.TraderWeaponList.SaleItems(TraderItem) { for (Idx = ItemFactory.ItemPickups.Length - 1; Idx >= 0; --Idx) @@ -211,15 +218,81 @@ function ResetPermanentZed() } } +function float GetAdjustedAIDoshValue( class MonsterClass ) +{ + return super.GetAdjustedAIDoshValue(MonsterClass) * OutbreakEvent.ActiveEvent.DoshOnKillGlobalModifier; +} + +protected function ScoreMonsterKill( Controller Killer, Controller Monster, KFPawn_Monster MonsterPawn ) +{ + super.ScoreMonsterKill(Killer, Monster, MonsterPawn); + + if(OutbreakEvent.ActiveEvent.bHealAfterKill) + { + if( MonsterPawn != none && MonsterPawn.DamageHistory.Length > 0 ) + { + HealAfterKilling( MonsterPawn, Killer ); + } + } +} + + +/** Heal players after a Zed was killed, based in more heal to the player that was the killer and less heal to the players that damaged the Zed */ +function HealAfterKilling(KFPawn_Monster MonsterPawn , Controller Killer) +{ + local int i; + local KFPlayerController KFPC; + local KFPlayerReplicationInfo DamagerKFPRI; + local array DamageHistory; + local array Attackers; + local KFPawn_Human PawnHuman; + + DamageHistory = MonsterPawn.DamageHistory; + + for ( i = 0; i < DamageHistory.Length; i++ ) + { + if( DamageHistory[i].DamagerController != none + && DamageHistory[i].DamagerController.bIsPlayer + && DamageHistory[i].DamagerPRI.GetTeamNum() == 0 + && DamageHistory[i].DamagerPRI != none ) + { + DamagerKFPRI = KFPlayerReplicationInfo(DamageHistory[i].DamagerPRI); + if( DamagerKFPRI != none ) + { + KFPC = KFPlayerController(DamagerKFPRI.Owner); + if( KFPC != none ) + { + if(Attackers.Find(KFPC) < 0) + { + PawnHuman = KFPawn_Human(KFPC.Pawn); + Attackers.AddItem(KFPC); + if( KFPC == Killer ) + { + `Log("Heal by Kill: "$MonsterPawn.HealByKill); + PawnHuman.HealDamageForce(MonsterPawn.HealByKill, KFPC, class'KFDT_Healing', false, false ); + + if( KFPawn_ZedFleshpound(MonsterPawn) != none || KFPawn_ZedScrake(MonsterPawn) != none ) + { + KFPC.ReceivePowerUp(class'KFPowerUp_HellishRage_NoCostHeal'); + } + } + else + { + `Log("Heal by Assistance: "$MonsterPawn.HealByAssistance); + PawnHuman.HealDamageForce(MonsterPawn.HealByAssistance, KFPC, class'KFDT_Healing', false, false ); + } + } + } + } + } + } + +} + + function StartMatch() { super.StartMatch(); - - //Set timer for global ticking damage - if (OutbreakEvent.ActiveEvent.GlobalDamageTickRate > 0.f && OutbreakEvent.ActiveEvent.GlobalDamageTickAmount > 0.f) - { - SetTimer(OutbreakEvent.ActiveEvent.GlobalDamageTickRate, true, 'ApplyGlobalDamage', OutbreakEvent); - } } function CreateDifficultyInfo(string Options) @@ -321,6 +394,8 @@ function TickZedTime( float DeltaTime ) function WaveEnded(EWaveEndCondition WinCondition) { + local KFPawn_Human Pawn; + super.WaveEnded(WinCondition); if (OutbreakEvent.ActiveEvent.bPermanentZedTime && ZedTimeRemaining > ZedTimeBlendOutTime) @@ -328,6 +403,16 @@ function WaveEnded(EWaveEndCondition WinCondition) ClearZedTimePCTimers(); ZedTimeRemaining = ZedTimeBlendOutTime; } + + if (OutbreakEvent.ActiveEvent.bHealPlayerAfterWave) + { + foreach WorldInfo.AllPawns(class'KFPawn_Human', Pawn) + { + Pawn.Health = Pawn.HealthMax; + } + } + + DisableGlobalDamage(); } function ClearZedTimePCTimers() @@ -360,6 +445,24 @@ function EndOfMatch(bool bVictory) function StartWave() { super.StartWave(); + + // Stop Global Damage for boss wave + if (!OutbreakEvent.ActiveEvent.bApplyGlobalDamageBossWave && WaveNum == WaveMax) + { + DisableGlobalDamage(); + } + // In case there was a previous boss wave. Not sure if possible + else if (OutbreakEvent.ActiveEvent.GlobalDamageTickRate > 0.f && OutbreakEvent.ActiveEvent.GlobalDamageTickAmount > 0.f) + { + if(!IsTimerActive('EnableGlobalDamage', self)) + { + SetTimer(OutbreakEvent.ActiveEvent.DamageDelayAfterWaveStarted, false, 'EnableGlobalDamage', self); + } + + // Check if we are in the zed frustration time to stop applying damage + SetTimer(1.0f, true, 'CheckForZedFrustrationMode', self); + } + if (OutbreakEvent.ActiveEvent.bPermanentZedTime) { //If we're a boss wave, wait until the camera animation is going @@ -378,6 +481,40 @@ function StartWave() { SetTimer(OutbreakEvent.ActiveEvent.AdditionalBossWaveStartDelay, true, nameof(SpawnBossWave)); } + +} + +function EnableGlobalDamage() +{ + MyKFGRI.SetGlobalDamage(true); + SetTimer(OutbreakEvent.ActiveEvent.GlobalDamageTickRate, true, 'ApplyGlobalDamage', OutbreakEvent); +} + +function DisableGlobalDamage() +{ + MyKFGRI.SetGlobalDamage(false); + + if (IsTimerActive('ApplyGlobalDamage', OutbreakEvent)) + { + ClearTimer('ApplyGlobalDamage', OutbreakEvent); + } + + if (IsTimerActive('EnableGlobalDamage', self)) + { + ClearTimer('EnableGlobalDamage', self); + } +} + +function CheckForZedFrustrationMode() +{ + if(IsTimerActive('ApplyGlobalDamage', OutbreakEvent)) + { + if(class'KFAIController'.default.FrustrationThreshold > 0 && MyKFGRI.AIRemaining <= class'KFAIController'.default.FrustrationThreshold) + { + DisableGlobalDamage(); + ClearTimer('CheckForZedFrustrationMode', self); + } + } } function BossCameraZedTimeRecheck() @@ -477,6 +614,8 @@ function InitAllPickups() { NumWeaponPickups = ItemPickups.Length * (OutbreakEvent.ActiveEvent.OverrideItemPickupModifier >= 0.f ? OutbreakEvent.ActiveEvent.OverrideItemPickupModifier : DifficultyInfo.GetItemPickupModifier()); NumAmmoPickups = AmmoPickups.Length * (OutbreakEvent.ActiveEvent.OverrideAmmoPickupModifier >= 0.f ? OutbreakEvent.ActiveEvent.OverrideAmmoPickupModifier : DifficultyInfo.GetAmmoPickupModifier()); + `log("OutbreakEvent.ActiveEvent.OverrideItemPickupModifier"@OutbreakEvent.ActiveEvent.OverrideItemPickupModifier); + `log("NumWeaponPickups"@NumWeaponPickups); `if(`__TW_SDK_) if( BaseMutator != none ) @@ -528,6 +667,7 @@ function ResetPickups( array PickupList, int NumPickups ) else if (OutbreakEvent.ActiveEvent.WaveItemPickupModifiers.Length >= WaveMax && KFPickupFactory_Item(PickupList[0]) != none) { NumPickups *= OutbreakEvent.ActiveEvent.WaveItemPickupModifiers[WaveNum]; + if(OutbreakEvent.ActiveEvent.OverrideItemPickupModifier == 0) NumPickups = 0; super(KFGameInfo).ResetPickups(PickupList, NumPickups); } //Otherwise, use normal path @@ -560,7 +700,25 @@ function bool AllowPrimaryWeapon(string ClassPath) { foreach OutbreakEvent.ActiveEvent.SpawnWeaponList.SaleItems(Item) { - if (Item.ClassName == name(ClassPath)) + if ( name(Item.WeaponDef.default.WeaponClassPath) == name(ClassPath) ) + { + return true; + } + } + return false; + } + return true; +} + +/** Whether or not a specific secondary weapon is allowed. Called at player spawn time while setting inventory. */ +function bool AllowSecondaryWeapon(string ClassPath) +{ + local STraderItem Item; + if (OutbreakEvent.ActiveEvent.SpawnWeaponList != none && OutbreakEvent.ActiveEvent.bSpawnWeaponListAffectsSecondaryWeapons) + { + foreach OutbreakEvent.ActiveEvent.SpawnWeaponList.SaleItems(Item) + { + if ( name(Item.WeaponDef.default.WeaponClassPath) == name(ClassPath) ) { return true; } @@ -580,6 +738,27 @@ function int AdjustStartingGrenadeCount(int CurrentCount) return CurrentCount; } +/** Allows gametype to validate a perk for the current match */ +function bool IsPerkAllowed(class PerkClass) +{ + Local int index; + + if(OutbreakEvent.ActiveEvent.PerksAvailableList.length == 0) + { + return true; + } + + for( index=0 ; index DamageType, Actor DamageCauser) +function HandleAfflictionsOnHit(Controller DamageInstigator, vector HitDir, class DamageType, Actor DamageCauser) { if (ShieldHealthPctByte == 0) { diff --git a/KFGameContent/Classes/KFPawn_ZedFleshpoundMini.uc b/KFGameContent/Classes/KFPawn_ZedFleshpoundMini.uc index 56e07ec..0bde540 100644 --- a/KFGameContent/Classes/KFPawn_ZedFleshpoundMini.uc +++ b/KFGameContent/Classes/KFPawn_ZedFleshpoundMini.uc @@ -26,18 +26,18 @@ defaultproperties DoshValue=75 //200 //25 //50 - // Stats + // Stats XPValues(0)=17 XPValues(1)=22 XPValues(2)=30 XPValues(3)=34 - Begin Object Name=MeleeHelper_0 + Begin Object Name=MeleeHelper_0 BaseDamage=49.f MaxHitRange=250.f MomentumTransfer=55000.f MyDamageType=class'KFDT_Bludgeon_Fleshpound' - End Object + End Object DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_Submachinegun', DamageScale=(0.62))) diff --git a/KFGameContent/Classes/KFPawn_ZedMatriarch.uc b/KFGameContent/Classes/KFPawn_ZedMatriarch.uc index d143a0a..ecb454d 100644 --- a/KFGameContent/Classes/KFPawn_ZedMatriarch.uc +++ b/KFGameContent/Classes/KFPawn_ZedMatriarch.uc @@ -692,6 +692,9 @@ function SetBattlePhase(int Phase) ArmorInfo.ExplodeArmor(HEAD_ARMOR_IDX); ArmorInfo.ExplodeArmor(CLAW_ARMOR_IDX); ArmorInfo.UpdateArmorUI(); + + // Forcing armor to be updated. + OnArmorZoneStatusUpdated(); } DoStumble(); diff --git a/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc b/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc index 84e7637..06399d0 100644 --- a/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc +++ b/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc @@ -163,6 +163,24 @@ simulated function SpawnFlightEffects() } } +simulated function SyncOriginalLocation() +{ + local Actor HitActor; + local vector HitLocation, HitNormal; + local TraceHitInfo HitInfo; + + if (Role < ROLE_Authority && Instigator != none && Instigator.IsLocallyControlled()) + { + HitActor = Trace(HitLocation, HitNormal, OriginalLocation, Location,,, HitInfo, TRACEFLAG_Bullet); + if (HitActor != none) + { + Explode(HitLocation, HitNormal); + } + } + + Super.SyncOriginalLocation(); +} + defaultproperties { Physics=PHYS_Falling diff --git a/KFGameContent/Classes/KFProj_Cannonball_Blunderbuss.uc b/KFGameContent/Classes/KFProj_Cannonball_Blunderbuss.uc index aedc756..56714ea 100644 --- a/KFGameContent/Classes/KFProj_Cannonball_Blunderbuss.uc +++ b/KFGameContent/Classes/KFProj_Cannonball_Blunderbuss.uc @@ -280,26 +280,7 @@ simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNorma if( (!bDud || ( bWantsClientSideDudHit && !bClientDudHit)) && ((TraveledDistance < ArmDistSquared) || bIsTimedExplosive || (OriginalLocation == vect(0,0,0) && ArmDistSquared > 0))) { - //for (Index = 0; Index < vActorsTouched.Length; Index++) - //{ - // if(vActorsTouched[Index] == Other) - // { - // return; - // } - //} - //if(Other == LastActorTouched) - //{ - // return; - //} - //LastActorTouched = Other; - //bForceNetUpdate=true; - //vActorsTouched.AddItem(Other); - // Don't touch the same actor multiple time's immediately after just - // touching it if the TouchTimeThreshhold is set to greater than 0. - // This was causing projectiles just to "stop" sometimes when hitting - // dead/ragdolled pawns because it was counting as multiple penetrations - if( LastTouched.Actor == Other && TouchTimeThreshhold > 0 - && `TimeSince(LastTouched.Time) <= TouchTimeThreshhold ) + if( LastTouched.Actor == Other && TouchTimeThreshhold > 0 && `TimeSince(LastTouched.Time) <= TouchTimeThreshhold ) { return; } @@ -311,13 +292,10 @@ simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNorma { ProcessBulletTouch(Other, HitLocation, HitNormal); } - // Reflect off Wall w/damping but allow penetration if the pawn is dead - //if(KFPawn_Monster(Other) == None || KFPawn_Monster(Other).Health > 0) - //{ - VNorm = (Velocity dot HitNormal) * HitNormal; - Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel; - Speed = VSize(Velocity); - //} + + VNorm = (Velocity dot HitNormal) * HitNormal; + Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel; + Speed = VSize(Velocity); } else if (!bDud && !bIsTimedExplosive) { @@ -350,7 +328,6 @@ simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNorma StopSimulating(); } - } simulated protected function StopSimulating() @@ -370,6 +347,35 @@ simulated protected function StopSimulating() } } +simulated function SyncOriginalLocation() +{ + local Actor HitActor; + local vector HitLocation, HitNormal; + local TraceHitInfo HitInfo; + + if (Role < ROLE_Authority && Instigator != none && Instigator.IsLocallyControlled()) + { + HitActor = Trace(HitLocation, HitNormal, OriginalLocation, Location,,, HitInfo, TRACEFLAG_Bullet); + if (HitActor != none) + { + ServerForceExplosion(); + } + } + + Super.SyncOriginalLocation(); +} + +reliable server function ServerForceExplosion() +{ + local vector ExplosionNormal; + + if (Instigator.Role == ROLE_Authority && !bHasExploded && !bHasDisintegrated) + { + ExplosionNormal = vect(0,0,1) >> Rotation; + CallExplode(Location, ExplosionNormal); + } +} + defaultproperties { TouchTimeThreshhold = 60.0f @@ -392,6 +398,10 @@ defaultproperties DampenFactorParallel=0 WallHitDampenFactor=0.5 WallHitDampenFactorParallel=0.5 + + bNetTemporary=False + NetPriority=5 + NetUpdateFrequency=200 bCollideComplex=TRUE // Ignore simple collision on StaticMeshes, and collide per poly bUseClientSideHitDetection=true diff --git a/KFGameContent/Classes/KFProj_Grenade_GravityImploder.uc b/KFGameContent/Classes/KFProj_Grenade_GravityImploder.uc new file mode 100644 index 0000000..e2c453f --- /dev/null +++ b/KFGameContent/Classes/KFProj_Grenade_GravityImploder.uc @@ -0,0 +1,188 @@ +//============================================================================= +// KFProj_Grenade_GravityImploder +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFProj_Grenade_GravityImploder extends KFProj_BallisticExplosive + hidedropdown; + +/* Ensure it detonates */ +var float DetonationTime; +var float VortexDuration; + +var float VortexRadius; +var float VortexImpulseStrength; +var protected transient bool bVortexActive; + +var protected RB_RadialImpulseComponent RadialImpulseComponent; + +simulated state GrenadeState +{ + simulated event BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + + if (Role == ROLE_Authority) + { + SetTimer(DetonationTime, false, nameOf(Timer_Detonate)); + } + } +} + +simulated state VortexState +{ + simulated event BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + + ClearTimer(nameof(Timer_Detonate)); + + bVortexActive = true; + + if (Role == ROLE_Authority) + { + SetTimer(VortexDuration, false, 'Timer_EndVortex'); + } + } + + simulated event Tick(float DeltaTime) + { + local float ImpulseModifier; + + if(bVortexActive && (WorldInfo.NetMode == NM_Client || WorldInfo.NetMode == NM_Standalone)) + { + // ImpulseModifier = (bReduceGibImpulseOnTick) ? (1.0f - AccumulatedTime / Lifetime) : 1.0f; + ImpulseModifier = 1.0f; + + RadialImpulseComponent.ImpulseRadius = VortexRadius; + RadialImpulseComponent.ImpulseStrength = VortexImpulseStrength * ImpulseModifier; + RadialImpulseComponent.bVelChange = true; + RadialImpulseComponent.ImpulseFalloff = RIF_Constant; + RadialImpulseComponent.FireImpulse(Location); + } + } +} + +/** + * Set the initial velocity and cook time + */ +simulated event PostBeginPlay() +{ + Super.PostBeginPlay(); + + AdjustCanDisintigrate(); + GotoState('GrenadeState'); +} + +simulated function Timer_Detonate() +{ + Detonate(); +} + +simulated function Detonate() +{ + Explode(Location, vect(0,0,1) >> Rotation); +} + +simulated function Explode(vector HitLocation, vector HitNormal) +{ + super.Explode(HitLocation, HitNormal); + GotoState('VortexState'); +} + +simulated function Timer_EndVortex() +{ + bVortexActive = false; + DeferredDestroy(0.15); +} + + +/** Called when the owning instigator controller has left a game */ +simulated function OnInstigatorControllerLeft() +{ + if( WorldInfo.NetMode != NM_Client ) + { + SetTimer( 1.f + Rand(5) + fRand(), false, nameOf(Timer_Detonate) ); + } +} + + +defaultproperties +{ + TouchTimeThreshhold = 60.0f + Physics=PHYS_Falling + Speed=3200 + MaxSpeed=3200 + TerminalVelocity=3200 + GravityScale=1.0 + LifeSpan=0.f + bWarnAIWhenFired=true + + ProjFlightTemplate=ParticleSystem'WEP_Gravity_Imploder_EMIT.FX_Yellow_Projectile' + ProjFlightTemplateZedTime=ParticleSystem'WEP_Gravity_Imploder_EMIT.FX_Yellow_Projectile_ZEDTIME' + + GrenadeBounceEffectInfo=KFImpactEffectInfo'FX_Impacts_ARCH.DefaultGrenadeImpacts' + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + AltExploEffects=KFImpactEffectInfo'WEP_Gravity_Imploder_ARCH.Yellow_Explosion_Concussive_Force' + + // Grenade explosion light + Begin Object Class=PointLightComponent Name=ExplosionPointLight + LightColor=(R=0,G=25,B=250,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=ImploTemplate0 + Damage=350 //150 + DamageRadius=375 //425 + DamageFalloffExponent=0.2 //0.25 + DamageDelay=0.f + MomentumTransferScale=-10000 + + // Damage Effects + MyDamageType=class'KFDT_Explosive_GravityImploder' + KnockDownStrength=0 + FractureMeshRadius=200.0 + FracturePartVel=500.0 + + ExplosionEffects=KFImpactEffectInfo'WEP_Gravity_Imploder_ARCH.Yellow_Explosion' + ExplosionSound=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Grenade_Yellow_Implosion' + + // Dynamic Light + ExploLight=ExplosionPointLight + ExploLightStartFadeOutTime=0.0 + ExploLightFadeOutTime=0.2 + + // Camera Shake + CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble' + CamShakeInnerRadius=200 + CamShakeOuterRadius=900 + CamShakeFalloff=1.5f + bOrientCameraShakeTowardsEpicenter=true + End Object + ExplosionTemplate=ImploTemplate0 + + bIsTimedExplosive=false; + DetonationTime=5.0 + + VortexRadius=450 + VortexImpulseStrength=-100 + VortexDuration=0.5f + bVortexActive=false + + Begin Object Class=RB_RadialImpulseComponent Name=ImpulseComponent0 + End Object + RadialImpulseComponent=ImpulseComponent0 + Components.Add(ImpulseComponent0) +} + diff --git a/KFGameContent/Classes/KFProj_Grenade_GravityImploderAlt.uc b/KFGameContent/Classes/KFProj_Grenade_GravityImploderAlt.uc new file mode 100644 index 0000000..95a03c6 --- /dev/null +++ b/KFGameContent/Classes/KFProj_Grenade_GravityImploderAlt.uc @@ -0,0 +1,584 @@ +//============================================================================= +// KFProj_Grenade_GravityImploderAlt +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFProj_Grenade_GravityImploderAlt extends KFProj_BallisticExplosive + hidedropdown; + +/** Factor added to the rolling speed of the ball when bouncing **/ +var(Projectile) float RollingFactor; + +/** Indicates that the ball hit the wall and is doing rolling animations **/ +var transient bool bIsRolling; + +/** Amount of roll stored for this cannonball **/ +var transient float CurrentRoll; + +var bool bHasAlreadyBounced; + +/** Collider **/ +var Object Collider; +/** Time before starting the implosion effect **/ +var float PreparationTime; + +/** Vortex params. */ +var float VortexDuration; +var float VortexTime; +var float VortexRadius; +var float VortexAbsorptionStrength; +var float VortexElevationStrength; +var bool bVortexReduceImpulseOnDist; + +var protected transient bool bFirstAbsorption; +var protected transient vector VortexLocation; + +var protected vector VortexNormal; +var protected KFImpactEffectInfo VortexImpactEffects; + +simulated state PreparingState +{ + simulated function BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + SetTimer( PreparationTime, false, nameOf(Timer_Ready) ); + } + + simulated event Tick(float DeltaTime) + { + local vector RollDelta; + local rotator NewRotation; + + // Let's roll (only in the client) + if ( bIsRolling && WorldInfo.NetMode != NM_DedicatedServer && Physics != PHYS_None && (Velocity.X != 0 || Velocity.Y != 0) ) + { + CurrentRoll -= (Abs(Velocity.X) + Abs(Velocity.Y)) * DeltaTime * RollingFactor; + RollDelta = ((vect(1, 0 , 0) * (Velocity.X)) + (vect(0, 1, 0) * (Velocity.Y) )); + NewRotation = Rotator(RollDelta); + NewRotation.pitch += CurrentRoll; + SetRotation(NewRotation); + } + + Super.Tick(DeltaTime); + } + + simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp) + { + VortexNormal = HitNormal; + + ProcessRebound(HitNormal, Wall, WallComp); + + if( !bDud && !bIsTimedExplosive ) + { + Super.HitWall(HitNormal, Wall, WallComp); + } + } + + simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) + { + local bool bWantsClientSideDudHit; + local float TraveledDistance; + local Vector VNorm; + //local int Index; + + // If we collided with a Siren shield, let the shield code handle touches + if( Other.IsA('KFTrigger_SirenProjectileShield') ) + { + return; + } + + if ( !bCollideWithTeammates && Pawn(Other) != None ) + { + // Don't hit teammates + if( Other.GetTeamNum() == GetTeamNum() ) + { + return; + } + } + + // Need to do client side dud hits if this is a client + if( Instigator != none && Instigator.Role < ROLE_Authority ) + { + bWantsClientSideDudHit = true; + } + + TraveledDistance = (`TimeSince(CreationTime) * Speed); + TraveledDistance *= TraveledDistance; + + if( (!bDud || ( bWantsClientSideDudHit && !bClientDudHit)) && ((TraveledDistance < ArmDistSquared) || bIsTimedExplosive || (OriginalLocation == vect(0,0,0) && ArmDistSquared > 0))) + { + // Don't touch the same actor multiple time's immediately after just + // touching it if the TouchTimeThreshhold is set to greater than 0. + // This was causing projectiles just to "stop" sometimes when hitting + // dead/ragdolled pawns because it was counting as multiple penetrations + if( LastTouched.Actor == Other && TouchTimeThreshhold > 0 + && `TimeSince(LastTouched.Time) <= TouchTimeThreshhold ) + { + return; + } + + //TODO: Add an impact sound here + SetIsDud(bWantsClientSideDudHit, HitNormal); + + if (Other != Instigator && !Other.bStatic && Other.GetTeamNum() != GetTeamNum() && !CheckRepeatingTouch(Other)) + { + ProcessBulletTouch(Other, HitLocation, HitNormal); + } + // Reflect off Wall w/damping but allow penetration if the pawn is dead + //if(KFPawn_Monster(Other) == None || KFPawn_Monster(Other).Health > 0) + //{ + VNorm = (Velocity dot HitNormal) * HitNormal; + Velocity = -VNorm * DampenFactor + (Velocity - VNorm) * DampenFactorParallel; + Speed = VSize(Velocity); + //} + } + else if (!bDud && !bIsTimedExplosive) + { + // Process impact hits + if (Other != Instigator && !Other.bStatic) + { + // check/ignore repeat touch events + if( !CheckRepeatingTouch(Other) && Other.GetTeamNum() != GetTeamNum()) + { + ProcessBulletTouch(Other, HitLocation, HitNormal); + } + } + + if( WorldInfo.NetMode == NM_Standalone || + (WorldInfo.NetMode == NM_ListenServer && Instigator != none && Instigator.IsLocallyControlled()) ) + { + Super.ProcessTouch( Other, HitLocation, HitNormal ); + return; + } + + if( Owner != none && KFWeapon( Owner ) != none && Instigator != none ) + { + if( Instigator.Role < ROLE_Authority && Instigator.IsLocallyControlled() ) + { + KFWeapon(Owner).HandleClientProjectileExplosion(HitLocation, self); + Super.ProcessTouch( Other, HitLocation, HitNormal ); + return; + } + } + } + } +} + +simulated state WaitingToImplode +{ + simulated function BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + } + + simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallComp) + { + if (HitNormal Dot vect(0,0,1) > 0.5f) + { + GotoState('ImplodingState'); + return; + } + + ProcessRebound(HitNormal, Wall, WallComp); + if(!bDud && !bIsTimedExplosive) + { + Super.HitWall(HitNormal, Wall, WallComp); + } + } + + simulated function Tick(float Delta) + { + if (vSize(Velocity) < 0.05f) + { + GotoState('ImplodingState'); + return; + } + + super.Tick(Delta); + } + + simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) + { + // Prevent default funcionality; + super.ProcessTouch(Other, HitLocation, HitNormal); + } +} + +simulated state ImplodingState +{ + simulated function BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + + StopSimulating(); + + AdjustVortexForPerk(); + if ( WorldInfo.NetMode != NM_Client ) + { + Velocity=vect(0,0,0); + Acceleration=vect(0,0,0); + RotationRate=rot(0,0,0); + GravityScale=0.0; + + bFirstAbsorption=true; + VortexTime=0.0f; + + SetTimer(VortexDuration, false, nameOf(Detonation_Ready) ); + } + + VortexLocation = Location + vect(0,0,1) * 125; + + // Start VGC + StartVortexVFX(); + } + + simulated function StartVortexVFX() + { + if(VortexImpactEffects != None) + { + if(VortexImpactEffects.DefaultImpactEffect.ParticleTemplate != None) + { + WorldInfo.MyEmitterPool.SpawnEmitter(VortexImpactEffects.DefaultImpactEffect.ParticleTemplate, VortexLocation, rotator(VortexNormal)); + } + if(VortexImpactEffects.DefaultImpactEffect.Sound != None) + { + PlaySoundBase(VortexImpactEffects.DefaultImpactEffect.Sound, true,,, VortexLocation); + } + } + } + + simulated function EndState(Name NextStateName) + { + super.EndState(NextStateName); + } + + simulated event Tick(float DeltaTime) + { + Super.Tick(DeltaTime); + + // Avoids to be moved in case there's any force applied. + SetLocation(VortexLocation); + +`if(`notdefined(ShippingPC)) + + if( KFWeap_GravityImploder(Owner) != none && KFWeap_GravityImploder(Owner).bDebugDrawVortex) + { + DrawDebugSphere(Location, VortexRadius, 125, 0, 0, 255, false); + } +`endif + + if (WorldInfo.NetMode < NM_Client) + { + VortexTime += DeltaTime; + AbsorbEnemies(); + bFirstAbsorption=false; + } + } + + function AdjustVortexForPerk() + { + local KFPlayerController KFPC; + local KFPerk Perk; + + KFPC = KFPlayerController(InstigatorController); + if( KFPC != none ) + { + Perk = KFPC.GetPerk(); + if(Perk != none) + { + VortexRadius = default.VortexRadius * Perk.GetAoERadiusModifier(); + } + } + } + + simulated function AbsorbEnemies() + { + local Actor Victim; + local TraceHitInfo HitInfo; + local KFPawn KFP; + local KFPawn_Monster KFPM; + local float ColRadius, ColHeight; + local float Dist; + local vector Dir; + local vector Momentum; + local float MomentumModifier; + + foreach CollidingActors(class'Actor', Victim, VortexRadius, VortexLocation, true,, HitInfo) + { + KFP = KFPawn(Victim); + KFPM = KFPawn_Monster(Victim); + + if (Victim != Self + && (!Victim.bWorldGeometry || Victim.bCanBeDamaged) + && (NavigationPoint(Victim) == None) + && Victim != Instigator + && KFP != None + && KFPawn_Human(Victim) == none // No player's character + && (KFPM == none || VortexTime < VortexDuration*KFPM.GetVortexAttractionModifier()) ) + { + KFP.GetBoundingCylinder(ColRadius, ColHeight); + + if (bFirstAbsorption) + { + Dir = vect(0,0,1); + Momentum = Dir * VortexElevationStrength; + } + else + { + Dir = Normal(VortexLocation - KFP.Location); + Dist = FMax(vSize(Dir) - ColRadius, 0.f); + MomentumModifier = bVortexReduceImpulseOnDist ? (1.0f - Dist / VortexRadius) : 1.0f; + Momentum = Dir * VortexAbsorptionStrength * MomentumModifier + vect(0,0,1) * (Dist/VortexRadius) * VortexAbsorptionStrength; + } + + if(KFPM != none) + { + Momentum *= KFPM.GetVortexAttractionModifier(); + } + + KFP.AddVelocity( Momentum, KFP.Location - 0.5 * (ColHeight + ColRadius) * Dir, class 'KFDT_Explosive_GravityImploder'); + } + } + } +} + +simulated state DetonatingState +{ + simulated function BeginState(Name PrevStateName) + { + super.BeginState(PrevStateName); + Detonate(); + } +} + + +simulated function PostBeginPlay() +{ + Super.PostBeginPlay(); + GotoState('PreparingState'); +} + +simulated function Timer_Ready() +{ + // GotoState('ImplodingState'); + GotoState('WaitingToImplode'); +} + +simulated function Detonation_Ready() +{ + GotoState('DetonatingState'); +} + +simulated function Detonate() +{ + local vector ExplosionNormal, vExplosionOffset; + + // Check if the bomb should explode right now + if (!bHasExploded && !bHasDisintegrated) + { + ExplosionNormal = vect(0,0,1) >> Rotation; + vExplosionOffset.x = 0; + vExplosionOffset.y = 0; + vExplosionOffset.z = 10; + SetLocation(VortexLocation + vExplosionOffset); + CallExplode(VortexLocation, ExplosionNormal); + } + // If not, mark the bomb to explode as soon as it hits something + else + { + bIsTimedExplosive = false; + bNetDirty = true; + } +} + +simulated function SetIsDud(bool bWantsClientSideDudHit, vector HitNormal) +{ + // This projectile doesn't dud. +} + +simulated protected function StopSimulating() +{ + Velocity = vect(0,0,0); + Acceleration = vect(0,0,0); + RotationRate = rot(0,0,0); + SetCollision(FALSE, FALSE); + + StopFlightEffects(); + + bRotationFollowsVelocity = FALSE; +} + +simulated function ProcessRebound(vector HitNormal, actor Wall, PrimitiveComponent WallComp) +{ + local Vector VNorm; + local rotator NewRotation; + local Vector Offset; + local bool bWantsClientSideDudHit; + local TraceHitInfo HitInfo; + local float TraveledDistance; + + bIsRolling = true; + + // Need to do client side dud hits if this is a client + if( Instigator != none && Instigator.Role < ROLE_Authority ) + { + bWantsClientSideDudHit = true; + } + + TraveledDistance = (`TimeSince(CreationTime) * Speed); + TraveledDistance *= TraveledDistance; + + // Bounce off the wall and cause the shell to dud if we hit too close + if( bDud || ((TraveledDistance < ArmDistSquared) || bIsTimedExplosive || (OriginalLocation == vect(0,0,0) && ArmDistSquared > 0))) + { + // Reflect off Wall w/damping + VNorm = (Velocity dot HitNormal) * HitNormal; + Velocity = -VNorm * WallHitDampenFactor + (Velocity - VNorm) * WallHitDampenFactorParallel; + Speed = VSize(Velocity); + + if( (!bDud || ( bWantsClientSideDudHit && !bClientDudHit)) ) + { + SetIsDud(bWantsClientSideDudHit, HitNormal); + } + + if ( WorldInfo.NetMode != NM_DedicatedServer && Pawn(Wall) == none && bHasAlreadyBounced == false ) + { + // do the impact effects + bHasAlreadyBounced = true; + `ImpactEffectManager.PlayImpactEffects(Location, Instigator, HitNormal, GrenadeBounceEffectInfo, true ); + } + + // if we hit a pawn or we are moving too slowly stop moving and lay down flat + if ( Speed < MinSpeedBeforeStop ) + { + ImpactedActor = Wall; + SetPhysics(PHYS_None); + if( ProjEffects != none ) + { + ProjEffects.SetTranslation(LandedTranslationOffset); + } + + // Position the shell on the ground + RotationRate.Yaw = 0; + RotationRate.Pitch = 0; + RotationRate.Roll = 0; + NewRotation = Rotation; + NewRotation.Pitch = 0; + if(ResetRotationOnStop) + { + SetRotation(NewRotation); + } + Offset.Z = LandedTranslationOffset.X; + SetLocation(Location + Offset); + } + + if( !Wall.bStatic && Wall.bCanBeDamaged && (DamageRadius == 0 || bDamageDestructiblesOnTouch) && !CheckRepeatingTouch(Wall) ) + { + HitInfo.HitComponent = WallComp; + HitInfo.Item = INDEX_None; + Wall.TakeDamage( Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType, HitInfo, self); + } + } +} + +defaultproperties +{ + TouchTimeThreshhold = 60.0f + Physics=PHYS_Falling + Speed=3200 + MaxSpeed=3200 + TerminalVelocity=3200 + GravityScale=1.0 + MomentumTransfer=100000 + LifeSpan=0.f + bWarnAIWhenFired=true + RollingFactor=1100 + MinSpeedBeforeStop=5 + ResetRotationOnStop=false + + // Rolling and dampen values + DampenFactor=0.1 + DampenFactorParallel=0 + WallHitDampenFactor=0.4 //0.5 + WallHitDampenFactorParallel=0.4 //0.5 + + bCollideComplex=TRUE // Ignore simple collision on StaticMeshes, and collide per poly + bUseClientSideHitDetection=true + bNoReplicationToInstigator=false + bAlwaysReplicateExplosion=true; + bUpdateSimulatedPosition=true + + Begin Object Name=CollisionCylinder + CollisionRadius=0.f + CollisionHeight=0.f + BlockNonZeroExtent=false + End Object + + ExplosionActorClass=class'KFExplosionActor' + + ProjFlightTemplate=ParticleSystem'WEP_Gravity_Imploder_EMIT.FX_Blue_Projectile' + ProjFlightTemplateZedTime=ParticleSystem'WEP_Gravity_Imploder_EMIT.FX_Blue_Projectile_ZEDTIME' + + GrenadeBounceEffectInfo=KFImpactEffectInfo'FX_Impacts_ARCH.DefaultGrenadeImpacts' + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + AltExploEffects=KFImpactEffectInfo'WEP_Gravity_Imploder_ARCH.Blue_Explosion_Concussive_Force' + + // Grenade explosion light + Begin Object Class=PointLightComponent Name=ExplosionPointLight + LightColor=(R=0,G=50,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=1 + DamageRadius=450 //600 + DamageFalloffExponent=0.f //2 + DamageDelay=0.f + MomentumTransferScale=10000 + + // Damage Effects + MyDamageType=class'KFDT_Explosive_GravityImploderWave' + KnockDownStrength=150 + FractureMeshRadius=200.0 + FracturePartVel=500.0 + ExplosionEffects=KFImpactEffectInfo'WEP_Gravity_Imploder_ARCH.Blue_Explosion' + ExplosionSound=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Grenade_Blue_Explosion' + + // Dynamic Light + ExploLight=ExplosionPointLight + ExploLightStartFadeOutTime=0.0 + ExploLightFadeOutTime=0.2 + + // Camera Shake + CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble' + CamShakeInnerRadius=200 + CamShakeOuterRadius=900 + CamShakeFalloff=1.5f + bOrientCameraShakeTowardsEpicenter=true + bIgnoreInstigator=false + + End Object + ExplosionTemplate=ExploTemplate0 + + bIsTimedExplosive=true; + PreparationTime=0.8 //1.0 + + VortexDuration=0.5 //0.7 + VortexRadius=500 //650 + VortexAbsorptionStrength=120 //100 + VortexElevationStrength=700 + bVortexReduceImpulseOnDist=false + bFirstAbsorption=true + VortexImpactEffects=KFImpactEffectInfo'WEP_Gravity_Imploder_ARCH.Blue_Attract' +} diff --git a/KFGameContent/Classes/KFProj_LightingFlare_HRGScorcher.uc b/KFGameContent/Classes/KFProj_LightingFlare_HRGScorcher.uc index 9b6033a..44d03dd 100644 --- a/KFGameContent/Classes/KFProj_LightingFlare_HRGScorcher.uc +++ b/KFGameContent/Classes/KFProj_LightingFlare_HRGScorcher.uc @@ -8,7 +8,7 @@ // Roberto Moreno (Saber Interactive) //============================================================================= -class KFProj_LightingFlare_HRGScorcher extends KFProj_RicochetBullet +class KFProj_LightingFlare_HRGScorcher extends KFProjectile hidedropdown; /** Time projectile is alive after being sticked to an actor or a pawn */ @@ -120,6 +120,10 @@ simulated event HitWall( vector HitNormal, actor Wall, PrimitiveComponent WallCo simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) { LastHitNormal = HitNormal; + if (Other != Instigator && !Other.bStatic && DamageRadius == 0.0 ) + { + ProcessBulletTouch(Other, HitLocation, HitNormal); + } super.ProcessTouch(Other, HitLocation, HitNormal); SetTimer(StickedTime, false, nameof(Timer_Explode)); StartStickedEffects(); @@ -165,6 +169,23 @@ simulated event Tick( float DeltaTime ) } } +// Last location needs to be correct, even on first tick. +simulated function SyncOriginalLocation() +{ + local Actor HitActor; + local vector HitLocation, HitNormal; + local TraceHitInfo HitInfo; + + if (Role < ROLE_Authority && Instigator != none && Instigator.IsLocallyControlled()) + { + HitActor = Trace(HitLocation, HitNormal, OriginalLocation, Location,,, HitInfo, TRACEFLAG_Bullet); + if (HitActor != none) + { + StickHelper.TryStick(HitNormal, HitLocation, HitActor); + } + } +} + defaultproperties { Physics=PHYS_Falling @@ -186,7 +207,6 @@ defaultproperties CurrentStickedTime=0.0 StickedLightFadeStartTime=4.0 StickedLightFadeTime=1.0 - BouncesLeft=0 TouchTimeThreshhold=0.15 //Sticking to environment or pinning to enemies @@ -197,6 +217,10 @@ defaultproperties bCollideActors=true bCollideComplex=true + bPushedByEncroachers=false + bDamageDestructiblesOnTouch=true + bWaitForEffects=true + ProjEffectsFadeOutDuration=0.25 //Network due to sticking feature bNetTemporary=false NetPriority=5 diff --git a/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc b/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc index 27900a4..439978e 100644 --- a/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc +++ b/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc @@ -228,7 +228,8 @@ simulated event HitWall( vector HitNormal, Actor Wall, PrimitiveComponent WallCo return; } - if( CanStick(Wall, HitNormal) && Wall.bStatic == true ) + // Stick to static walls and destructible environment objects. + if( CanStick(Wall, HitNormal) && (Wall.bStatic == true || (Wall.bCanBeDamaged && KFPawn(Wall) == none)) ) { Stick( Location, HitNormal ); } diff --git a/KFGameContent/Classes/KFProj_SonicBlastFullyCharged_HRG_SonicGun.uc b/KFGameContent/Classes/KFProj_SonicBlastFullyCharged_HRG_SonicGun.uc new file mode 100644 index 0000000..8d7d3b7 --- /dev/null +++ b/KFGameContent/Classes/KFProj_SonicBlastFullyCharged_HRG_SonicGun.uc @@ -0,0 +1,55 @@ +//============================================================================= +// KFProj_SonicBlastFullyCharged_HRG_SonicGun +//============================================================================= +// HRG Sonic Gun sonic projectile for default fire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFProj_SonicBlastFullyCharged_HRG_SonicGun extends KFProj_Bullet; + +/** + * Initialize the Projectile + */ +function Init(vector Direction) +{ + super(KFProjectile).Init( Direction ); +} + +simulated function SpawnFlightEffects() +{ + super.SpawnFlightEffects(); + //TODO: Remove. Temporal to see change in FX + ProjEffects.SetScale( 1.0 ); +} + +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + super.ProcessTouch(Other, HitLocation, HitNormal); + if (PenetrationPower <= 0) + { + Shutdown(); + } +} + +defaultproperties +{ + ProjFlightTemplate = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile_AltFire' + ProjFlightTemplateZedTime = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile_AltFire' + + ImpactEffects = KFImpactEffectInfo'WEP_HRG_SonicGun_ARCH.HRG_SonicGun_Projectile_AltFire_Impacts' + + bWarnAIWhenFired=true + + Lifespan=10.0 + + MaxSpeed=10000.0 //7200.0 + Speed=10000.0 //7200.0 + TerminalVelocity=7200 + + GravityScale=0.0//0.7 + + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + + AssociatedPerkClass=class'KFPerk_Sharpshooter' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFProj_SonicBlastHalfCharged_HRG_SonicGun.uc b/KFGameContent/Classes/KFProj_SonicBlastHalfCharged_HRG_SonicGun.uc new file mode 100644 index 0000000..8f8216d --- /dev/null +++ b/KFGameContent/Classes/KFProj_SonicBlastHalfCharged_HRG_SonicGun.uc @@ -0,0 +1,113 @@ +//============================================================================= +// KFProj_SonicBlastHalfCharged_HRG_SonicGun +//============================================================================= +// HRG Sonic Gun sonic projectile for default fire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFProj_SonicBlastHalfCharged_HRG_SonicGun extends KFProj_Bullet; + +var bool bDebugShowProjectile; +var bool bDebugPersistentLines; + +`define SONICBLASTHALFCHARGED_COLLISION 30.0 +/** + * Initialize the Projectile + */ +function Init(vector Direction) +{ + super(KFProjectile).Init( Direction ); +} + +simulated function SpawnFlightEffects() +{ + super.SpawnFlightEffects(); + //TODO: Remove. Temporal to see change in FX + ProjEffects.SetScale( 2.0 ); +} + +simulated event Tick(float DeltaTime) +{ + //cylinders debug + //local vector A, B; + //A = Location; + //B.X = `SONICBLASTHALFCHARGED_COLLISION; + //B.Y = `SONICBLASTHALFCHARGED_COLLISION; + //B.Z = `SONICBLASTHALFCHARGED_COLLISION; + //DrawDebugBox( A, B, 255, 255, 0, bDebugPersistentLines); // SLOW! Use for debugging only! +} + +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + super.ProcessTouch(Other, HitLocation, HitNormal); + if (PenetrationPower <= 0) + { + Shutdown(); + } +} + +defaultproperties +{ +// bDebugShowProjectile=true +// bDebugPersistentLines=false + ProjFlightTemplate = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile_AltFire' + ProjFlightTemplateZedTime = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile_AltFire' + + ImpactEffects = KFImpactEffectInfo'WEP_HRG_SonicGun_ARCH.HRG_SonicGun_Projectile_AltFire_Impacts' + + bWarnAIWhenFired=true + + Lifespan=1.8 //3.0 + TouchTimeThreshhold=0.2 + + MaxSpeed=3600.0 + Speed=3600.0 + TerminalVelocity=3600 + + Physics=PHYS_Projectile + + GravityScale=0.0//0.7 + + GlassShatterType=FMGS_ShatterAll + + bCollideComplex=false + bCollideActors=true + + bBlockedByInstigator=false + bAlwaysReplicateExplosion=true + + bNetTemporary=false + NetPriority=5 + NetUpdateFrequency=200 + + bNoReplicationToInstigator=false + bUseClientSideHitDetection=true + bUpdateSimulatedPosition=true + bSyncToOriginalLocation=true + bSyncToThirdPersonMuzzleLocation=true + + PinBoneIdx=INDEX_None + + bCanBeDamaged=false + bCanDisintegrate=false + bIgnoreFoliageTouch=true + Begin Object Name=CollisionCylinder + CollisionRadius=0 + CollisionHeight=0 + BlockNonZeroExtent=false + BlockZeroExtent=true + // for siren scream + CollideActors=true + End Object + // Since we're still using an extent cylinder, we need a line at 0 + ExtraLineCollisionOffsets.Add(()) + ExtraLineCollisionOffsets.Add((Y = -`SONICBLASTHALFCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = `SONICBLASTHALFCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Z = -`SONICBLASTHALFCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Z = `SONICBLASTHALFCHARGED_COLLISION)) + + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + + AssociatedPerkClass=class'KFPerk_Sharpshooter' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFProj_SonicBlastUncharged_HRG_SonicGun.uc b/KFGameContent/Classes/KFProj_SonicBlastUncharged_HRG_SonicGun.uc new file mode 100644 index 0000000..05c99de --- /dev/null +++ b/KFGameContent/Classes/KFProj_SonicBlastUncharged_HRG_SonicGun.uc @@ -0,0 +1,117 @@ +//============================================================================= +// KFProj_SonicBlastUncharged_HRG_SonicGun +//============================================================================= +// HRG Sonic Gun sonic projectile for default fire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFProj_SonicBlastUncharged_HRG_SonicGun extends KFProj_Bullet; + +`define SONICBLASTUNCHARGED_COLLISION 45.0 + +var bool bDebugShowProjectile; +var bool bDebugPersistentLines; + +/** + * Initialize the Projectile + */ +function Init(vector Direction) +{ + super(KFProjectile).Init( Direction ); +} + +simulated function SpawnFlightEffects() +{ + super.SpawnFlightEffects(); + //TODO: Remove. Temporal to see change in FX + ProjEffects.SetScale( 3.5 ); //5.0 +} + +simulated event Tick(float DeltaTime) +{ + //cylinders debug + //local vector A, B; + //A = Location; + //B.X = `SONICBLASTUNCHARGED_COLLISION; + //B.Y = `SONICBLASTUNCHARGED_COLLISION; + //B.Z = `SONICBLASTUNCHARGED_COLLISION; + //DrawDebugBox( A, B, 255, 255, 0, bDebugPersistentLines); // SLOW! Use for debugging only! +} + +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + super.ProcessTouch(Other, HitLocation, HitNormal); + if (PenetrationPower <= 0) + { + Shutdown(); + } +} + +defaultproperties +{ + bDebugShowProjectile=true + bDebugPersistentLines=false + ProjFlightTemplate = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile' + ProjFlightTemplateZedTime = ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_Projectile' + ImpactEffects = KFImpactEffectInfo'WEP_HRG_SonicGun_ARCH.HRG_SonicGun_Projectile_Impacts' + + bWarnAIWhenFired=true + + Lifespan=1.5 //1.25 + TouchTimeThreshhold=0.4 + + MaxSpeed=2000.0 //1400.0 + Speed=2000.0 //1400.0 + TerminalVelocity=1800 + + Physics=PHYS_Projectile + + GravityScale=0.0//0.7 + + GlassShatterType=FMGS_ShatterAll + + bCollideComplex=false + bCollideActors=true + + bBlockedByInstigator=false + bAlwaysReplicateExplosion=true + + bNetTemporary=false + NetPriority=5 + NetUpdateFrequency=200 + + bNoReplicationToInstigator=false + bUseClientSideHitDetection=true + bUpdateSimulatedPosition=true + bSyncToOriginalLocation=true + bSyncToThirdPersonMuzzleLocation=true + + PinBoneIdx=INDEX_None + + bCanBeDamaged=false + bCanDisintegrate=false + bIgnoreFoliageTouch=true + Begin Object Name=CollisionCylinder + CollisionRadius=0.f + CollisionHeight=0.f + BlockNonZeroExtent=false + BlockZeroExtent=true + // for siren scream + CollideActors=true + End Object + // Since we're still using an extent cylinder, we need a line at 0 + ExtraLineCollisionOffsets.Add(()) + ExtraLineCollisionOffsets.Add((Y = -`SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = `SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Z = `SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Z = -`SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = `SONICBLASTUNCHARGED_COLLISION, Z = `SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = -`SONICBLASTUNCHARGED_COLLISION, Z = `SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = `SONICBLASTUNCHARGED_COLLISION, Z = -`SONICBLASTUNCHARGED_COLLISION)) + ExtraLineCollisionOffsets.Add((Y = -`SONICBLASTUNCHARGED_COLLISION, Z = -`SONICBLASTUNCHARGED_COLLISION)) + + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + + AssociatedPerkClass=class'KFPerk_Sharpshooter' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFSeasonalEventStats_Spring2021.uc b/KFGameContent/Classes/KFSeasonalEventStats_Spring2021.uc new file mode 100644 index 0000000..cb5c65e --- /dev/null +++ b/KFGameContent/Classes/KFSeasonalEventStats_Spring2021.uc @@ -0,0 +1,140 @@ +//============================================================================= +// KFSeasonalEventStats_Spring2021 +//============================================================================= +// Tracks event-specific challenges/accomplishments for Spring 2021 +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFSeasonalEventStats_Spring2021 extends KFSeasonalEventStats; + +var transient private const int BossKillsRequired, EDARKillsRequired, WavesWithoutDamageRequired, EndlessWaveRequired; +var transient bool bHitTakenThisWave; + +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 Dystopia 2029 + bObjectiveIsValidForMap[2] = 0; // Kill 100 E.D.A.R.s on Dystopia 2029 + bObjectiveIsValidForMap[3] = 0; // Complete a wave without taking any damage 10 times on Dystopia 2029 + bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Dystopia 2029 + + if (CapsMapName == "KF-DYSTOPIA2029") + { + + bObjectiveIsValidForMap[1] = 1; + bObjectiveIsValidForMap[2] = 1; + bObjectiveIsValidForMap[3] = 1; + bObjectiveIsValidForMap[4] = 1; + } + + SetSeasonalEventStatsMax(BossKillsRequired, 0, EDARKillsRequired, WavesWithoutDamageRequired, 0); +} + +private event GrantEventItems() +{ + if (Outer.IsEventObjectiveComplete(0) && + Outer.IsEventObjectiveComplete(1) && + Outer.IsEventObjectiveComplete(2) && + Outer.IsEventObjectiveComplete(3) && + Outer.IsEventObjectiveComplete(4)) + { + // "Cyborg | Companion Backpack | Precious" + GrantEventItem(8716); + } +} + +simulated event OnGameWon(class GameClass, int Difficulty, int GameLength, bool bCoOp) +{ + // Dystopia weekly + if (bObjectiveIsValidForMap[1] != 0) + { + if (GameClass == class'KFGameInfo_WeeklySurvival') + { + FinishedObjective(SEI_Spring, 1); + } + } +} + +simulated function OnBossDied() +{ + local int ObjIdx; + + // Boss kills in any map + ObjIdx = 0; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= BossKillsRequired) + { + FinishedObjective(SEI_Spring, ObjIdx); + } + } +} + +simulated function OnZedKilled(class MonsterClass, int Difficulty, class DT) +{ + local int ObjIdx; + + // E.D.A.R kills + ObjIdx = 2; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (ClassIsChildOf(MonsterClass, class'KFPawn_ZedDAR')) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= EDARKillsRequired) + { + FinishedObjective(SEI_Spring, ObjIdx); + } + } + } +} + +simulated function OnHitTaken() +{ + bHitTakenThisWave=true; +} + +simulated event OnWaveCompleted(class GameClass, int Difficulty, int WaveNum) +{ + local int ObjIdx; + + // No damage wave completed + ObjIdx = 3; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (!bHitTakenThisWave) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= WavesWithoutDamageRequired) + { + FinishedObjective(SEI_Spring, ObjIdx); + } + } + bHitTakenThisWave = false; + } + + // Wavesin Endless hard + ObjIdx = 4; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD) + { + FinishedObjective(SEI_Spring, ObjIdx); + } + } +} + +defaultproperties +{ + BossKillsRequired=15 + EDARKillsRequired=50 + WavesWithoutDamageRequired=10 + EndlessWaveRequired=15 + + bHitTakenThisWave=false +} diff --git a/KFGameContent/Classes/KFWeapAttach_GravityImploder.uc b/KFGameContent/Classes/KFWeapAttach_GravityImploder.uc new file mode 100644 index 0000000..5363875 --- /dev/null +++ b/KFGameContent/Classes/KFWeapAttach_GravityImploder.uc @@ -0,0 +1,54 @@ +//============================================================================= +// KFWeapAttach_GravityImploder +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFWeapAttach_GravityImploder extends KFWeaponAttachment; + +`define GRAVITYIMPLODER_MIC_LED_INDEX 1 + +/** Weapons material colors for each fire mode. */ +var LinearColor DefaultFireMaterialColor; +var LinearColor AltFireMaterialColor; + +simulated event PreBeginPlay() +{ + Super.PreBeginPlay(); + + if ( WorldInfo.NetMode == NM_DedicatedServer ) + { + return; + } + + if ( WeaponMIC == None && WeapMesh != None ) + { + WeaponMIC = WeapMesh.CreateAndSetMaterialInstanceConstant(`GRAVITYIMPLODER_MIC_LED_INDEX); + WeaponMIC.SetVectorParameterValue('Vector_Center_Color_A', DefaultFireMaterialColor); + } +} + +simulated function bool ThirdPersonFireEffects(vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte ) +{ + local LinearColor MatColor; + if(P.FiringMode == 0) // DEFAULT_FIREMODE + { + MatColor = DefaultFireMaterialColor; + } + else if (P.FiringMode == 1) // ALTFIRE_FIREMODE + { + MatColor = AltFireMaterialColor; + } + + WeaponMIC.SetVectorParameterValue('Vector_Center_Color_A', MatColor); + return super.ThirdPersonFireEffects(HitLocation, P, ThirdPersonAnimRateByte); +} + +defaultproperties +{ + DefaultFireMaterialColor = (R = 0.965f,G = 0.2972f, B = 0.0f) + AltFireMaterialColor = (R = 0.0f, G = 0.9631f, B = 0.96581f) +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeap_AssaultRifle_Bullpup.uc b/KFGameContent/Classes/KFWeap_AssaultRifle_Bullpup.uc index 7a5e014..533d524 100644 --- a/KFGameContent/Classes/KFWeap_AssaultRifle_Bullpup.uc +++ b/KFGameContent/Classes/KFWeap_AssaultRifle_Bullpup.uc @@ -39,7 +39,7 @@ defaultproperties // Ammo MagazineCapacity[0]=30 SpareAmmoCapacity[0]=270 - InitialSpareMags[0]=4 + InitialSpareMags[0]=3 //4 bCanBeReloaded=true bReloadFromMagazine=true @@ -62,7 +62,7 @@ defaultproperties HippedRecoilModifier=1.5 // Inventory / Grouping - InventorySize=6 + InventorySize=5 //6 GroupPriority=50 WeaponSelectTexture=Texture2D'ui_weaponselect_tex.UI_WeaponSelect_Bullpup' AssociatedPerkClasses(0)=class'KFPerk_Commando' @@ -75,7 +75,7 @@ defaultproperties InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_Bullpup' FireInterval(DEFAULT_FIREMODE)=+0.0909 // 660 RPM Spread(DEFAULT_FIREMODE)=0.0085 - InstantHitDamage(DEFAULT_FIREMODE)=30.0 //25 + InstantHitDamage(DEFAULT_FIREMODE)=32.0 //30.0 //25 FireOffset=(X=30,Y=4.5,Z=-5) // ALT_FIREMODE @@ -85,7 +85,7 @@ defaultproperties WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_AssaultRifle' InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_Bullpup' FireInterval(ALTFIRE_FIREMODE)=+0.1 - InstantHitDamage(ALTFIRE_FIREMODE)=30.0 //25 + InstantHitDamage(ALTFIRE_FIREMODE)=32.0 //30.0 //25 Spread(ALTFIRE_FIREMODE)=0.0085 // BASH_FIREMODE diff --git a/KFGameContent/Classes/KFWeap_Bow_Crossbow.uc b/KFGameContent/Classes/KFWeap_Bow_Crossbow.uc index 918b16b..0550fad 100644 --- a/KFGameContent/Classes/KFWeap_Bow_Crossbow.uc +++ b/KFGameContent/Classes/KFWeap_Bow_Crossbow.uc @@ -39,6 +39,24 @@ static simulated event EFilterTypeUI GetTraderFilter() return FT_Projectile; } +simulated function float GetUpgradedAfflictionPower(EAfflictionType AfflictionType, float InPower, optional int FireMode = INDEX_NONE, optional int UpgradeIndex = INDEX_NONE) +{ + local class DT; + local KFPerk Perk; + + Perk = GetPerk(); + if(AfflictionType == AF_Stun && Perk != none && Perk.bWasLastHitAHeadshot) + { + DT = class(InstantHitDamageTypes[DEFAULT_FIREMODE]); + if (DT != none) + { + return super.GetUpgradedAfflictionPower(AfflictionType, DT.default.HeadStunPower, FireMode, UpgradeIndex); + } + } + + return super.GetUpgradedAfflictionPower(AfflictionType, InPower, FireMode, UpgradeIndex); +} + defaultproperties { // Inventory diff --git a/KFGameContent/Classes/KFWeap_GravityImploder.uc b/KFGameContent/Classes/KFWeap_GravityImploder.uc new file mode 100644 index 0000000..c2a0826 --- /dev/null +++ b/KFGameContent/Classes/KFWeap_GravityImploder.uc @@ -0,0 +1,187 @@ +//============================================================================= +// KFWeap_GravityImploder +//============================================================================= +// The unique and amazing Gravity Imploder weapon +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFWeap_GravityImploder extends KFWeapon; + +`define GRAVITYIMPLODER_MIC_LED_INDEX 1 + +/** Reduction for the amount of damage dealt to the weapon owner (including damage by the explosion) */ +var float SelfDamageReductionValue; + +/** Weapons material colors for each fire mode. */ +var LinearColor DefaultFireMaterialColor; +var LinearColor AltFireMaterialColor; + +var bool bLastFireWasAlt; + +var const bool bDebugDrawVortex; + +simulated function Activate() +{ + super.Activate(); + UpdateMaterial(); +} + +simulated function UpdateMaterial() +{ + local LinearColor MatColor; + MatColor = bLastFireWasAlt ? AltFireMaterialColor : DefaultFireMaterialColor; + + if( WeaponMICs.Length > `GRAVITYIMPLODER_MIC_LED_INDEX ) + { + WeaponMICs[`GRAVITYIMPLODER_MIC_LED_INDEX].SetVectorParameterValue('Vector_Center_Color_A', MatColor); + } +} + + +simulated function Projectile ProjectileFire() +{ + UpdateMaterial(); + return super.ProjectileFire(); +} + +simulated function BeginFire( Byte FireModeNum ) +{ + super.BeginFire(FireModeNum); + + if(FireModeNum == ALTFIRE_FIREMODE && !bLastFireWasAlt) + { + bLastFireWasAlt=true; + } + else if (FireModeNum == DEFAULT_FIREMODE && bLastFireWasAlt) + { + bLastFireWasAlt=false; + } +} + +simulated function AltFireMode() +{ + StartFire(ALTFIRE_FIREMODE); +} + +// Reduce damage to self +function AdjustDamage(out int InDamage, class DamageType, Actor DamageCauser) +{ + super.AdjustDamage(InDamage, DamageType, DamageCauser); + + if (Instigator != none && DamageCauser != none && DamageCauser.Instigator == Instigator) + { + InDamage *= SelfDamageReductionValue; + } +} + +defaultproperties +{ + // Content + PackageKey="Gravity_Imploder" + FirstPersonMeshName="WEP_1P_Gravity_Imploder_MESH.Wep_1stP_Gravity_Imploder_Rig" + FirstPersonAnimSetNames(0)="WEP_1P_Gravity_Imploder_ANIM.Wep_1stP_Gravity_Imploder_Anim" + PickupMeshName="WEP_3P_Gravity_Imploder_MESH.WEP_3rdP_Gravity_Imploder_Pickup" + AttachmentArchetypeName="WEP_Gravity_Imploder_ARCH.Wep_Gravity_Imploder_3P" + MuzzleFlashTemplateName="WEP_Gravity_Imploder_ARCH.Wep_Gravity_Imploder_MuzzleFlash" + + // Inventory / Grouping + InventorySize=7 //8 + GroupPriority=125 //75 + WeaponSelectTexture=Texture2D'WEP_UI_Gravity_Imploder_TEX.UI_WeaponSelect_Gravity_Imploder' + AssociatedPerkClasses(0)=class'KFPerk_Demolitionist' + + // FOV + MeshFOV=75 + MeshIronSightFOV=40 + PlayerIronSightFOV=65 + + // Depth of field + DOF_FG_FocalRadius=50 + DOF_FG_MaxNearBlurSize=3.5 + + // Ammo + MagazineCapacity[0]=6 //5 + SpareAmmoCapacity[0]=42 //35 + InitialSpareMags[0]=2 //4 + AmmoPickupScale[0]=1 //1 + bCanBeReloaded=true + bReloadFromMagazine=true + + // Zooming/Position + PlayerViewOffset=(X=5.5,Y=8,Z=-2) //(X=11.0,Y=8,Z=-2) + IronSightPosition=(X=10,Y=0,Z=-1.9) //(X=10,Y=0,Z=0) + + // AI warning system + bWarnAIWhenAiming=true + AimWarningDelay=(X=0.4f, Y=0.8f) + AimWarningCooldown=0.0f + + // Recoil + maxRecoilPitch=750 //500 + minRecoilPitch=675//400 + maxRecoilYaw=250 //150 + minRecoilYaw=-250 //-150 + RecoilRate=0.08 + RecoilMaxYawLimit=500 + RecoilMinYawLimit=65035 + RecoilMaxPitchLimit=1250 + RecoilMinPitchLimit=64785 + RecoilISMaxYawLimit=50 + RecoilISMinYawLimit=65485 + RecoilISMaxPitchLimit=500 + RecoilISMinPitchLimit=65485 + RecoilViewRotationScale=0.6 + IronSightMeshFOVCompensationScale=1.5 + + // DEFAULT_FIREMODE + FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade' + FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFiring + WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile + WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Grenade_GravityImploder' + InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_GravityImploderImpact' + InstantHitDamage(DEFAULT_FIREMODE)=150 + FireInterval(DEFAULT_FIREMODE)=1.33 //45 RPM + Spread(DEFAULT_FIREMODE)=0.02 //0 + PenetrationPower(DEFAULT_FIREMODE)=0 + FireOffset=(X=25,Y=3.0,Z=-2.5) + + // ALTFIRE_FIREMODE (swap fire mode) + FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Electricity' + FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring + WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile + WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Grenade_GravityImploderAlt' + FireInterval(ALTFIRE_FIREMODE)=1.33 //45 RPM + InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_GravityImploderImpactAlt' + InstantHitDamage(ALTFIRE_FIREMODE)=200 + Spread(ALTFIRE_FIREMODE)=0.02 //0.0085 + AmmoCost(ALTFIRE_FIREMODE)=1 + + // BASH_FIREMODE + InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_GravityImploder' + InstantHitDamage(BASH_FIREMODE)=26 + + // Fire Effects + WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Shoot_3P', FirstPersonCue=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Shoot_1P') + WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Dry_Fire' + WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Shoot_3P', FirstPersonCue=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Shoot_1P') + WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_Gravity_Imploder.Play_WEP_Gravity_Imploder_Dry_Fire' + EjectedShellForegroundDuration=1.5f + + // Attachments + bHasIronSights=true + bHasFlashlight=false + + WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Medium_Recoil' + + SelfDamageReductionValue=0.f //0.25f + + bLastFireWasAlt=false + DefaultFireMaterialColor = (R = 0.965f,G = 0.2972f, B = 0.0f) + AltFireMaterialColor = (R = 0.0f, G = 0.9631f, B = 0.96581f) + + bHasFireLastAnims=true + + NumBloodMapMaterials=2 +} diff --git a/KFGameContent/Classes/KFWeap_HRG_SonicGun.uc b/KFGameContent/Classes/KFWeap_HRG_SonicGun.uc new file mode 100644 index 0000000..2abeeb1 --- /dev/null +++ b/KFGameContent/Classes/KFWeap_HRG_SonicGun.uc @@ -0,0 +1,613 @@ +//============================================================================= +// KFWeap_HRG_SonicGun +//============================================================================= +// The HRG Sonic Gun weapon +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFWeap_HRG_SonicGun extends KFWeapon; + +`define SONICGUN_MIC_SIGHT_INDEX 1 + +var(Animations) const editconst name ChargeAnim; +var(Animations) const editconst name ChargeAnimLast; +var(Animations) const editconst name ChargeAnimIron; +var(Animations) const editconst name ChargeAnimIronLast; + +/** How long to wait after firing to force reload */ +var() float ForceReloadTime; + +var transient int CurrentChargeLevel; + +/** Maximum times weapon can be charged */ +var int MaxChargeLevel; + +/** How much multiply damage does default fire projectile do by charge level*/ +var Array SonicBlastDamageByChargeLevel; + +/** how much multiply momentum for default fire projectile by charge level */ +var Array SonicBlastMomentumByChargeLevel; + +/** how much multiply penetration power for default fire projectile by charge level */ +var Array SonicBlastPenetrationPowerByChargeLevel; + +/** DamageTypes for default fire projectile by charge level*/ +var Array< class > SonicBlastDamageTypeByChargeLevel; + +/** Projectile classes for default fire projectile by charge level*/ +var Array< class > SonicBlastProjectileClassByChargeLevel; + +/** Sounds for default fire by charge level*/ +var Array SonicBlastFireSoundByChargeLevel; + +/** Sounds for charge */ +var Array SonicBlastFireSoundCharge; + +/** Sounds for charge sound by charge level*/ +var Array ChargeSoundByChargeLevel; + +/** How much momentum to apply when fired in double barrel */ +var(Recoil) float FullyChargedKickMomentum; + +/** How much to reduce shoot momentum when falling */ +var(Recoil) float FallingMomentumReduction; + +/** VFX to play from the muzzle when firing the charged shot */ +var ParticleSystem MuzzleEffectDefaultFire; + +/** VFX to play from the muzzle when firing the charged shot */ +var ParticleSystem MuzzleEffectChargedFire; + + +struct MomentumMultiplierByZed +{ + var Name ZedClassName; + var float MomentumMultiplier; +}; + +var array MomentumMultiplierByZedArray; + +/** Colors for holographic sight by charge level */ +var const Array HolographicSightByChargeLevel; +var const Array HolographicSightScanlineByChargeLevel; +var Array HolographicSightUseDefaultByChargeLevel; + +simulated function PostBeginPlay() +{ + CurrentChargeLevel=0; + if( WeaponMICs.Length > `SONICGUN_MIC_SIGHT_INDEX ) + { + if (!HolographicSightUseDefaultByChargeLevel[0]) + { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Center_Color_A', HolographicSightByChargeLevel[0]); + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Scanline_Color_Mult', HolographicSightScanlineByChargeLevel[0]); + } + else { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].ClearParameterValues(); + } + } +} +/** + * Toggle between DEFAULT and ALTFIRE + */ +simulated function AltFireMode() +{ + // skip super + + if (!Instigator.IsLocallyControlled()) + { + return; + } + + StartFire(ALTFIRE_FIREMODE); +} + +/** Overridded to add spawned charge to list of spawned charges */ +simulated function Projectile ProjectileFire() +{ + local Projectile P; + + P = super.ProjectileFire(); + + return P; +} + +/** Returns animation to play based on reload type and status */ +simulated function name GetReloadAnimName(bool bTacticalReload) +{ + // magazine relaod + if (AmmoCount[0] > 0) + { + return (bTacticalReload) ? ReloadNonEmptyMagEliteAnim : ReloadNonEmptyMagAnim; + } + else + { + return (bTacticalReload) ? ReloadEmptyMagEliteAnim : ReloadEmptyMagAnim; + } +} + +simulated function StartFire(byte FireModeNum) +{ + if (FireModeNum == ALTFIRE_FIREMODE) + { + if (!IsCanIncrementCharge()) + { + return; + } + } + + super.StartFire(FireModeNum); +} + +/********************************************************************************************* + * State WeaponSonicGunCharging + * The weapon is in this state while detonating a charge +*********************************************************************************************/ + +simulated function GotoActiveState(); + +simulated state WeaponSonicGunCharging +{ + ignores AllowSprinting; + + simulated event BeginState( name PreviousStateName ) + { + local KFPerk InstigatorPerk; + + if (!IsCanIncrementCharge()) + { + ClearPendingFire(CurrentFireMode); + GotoActiveState(); + return; + } + + InstigatorPerk = GetPerk(); + if( InstigatorPerk != none ) + { + SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) ); + } + + IncrementChargeAndPlayAnimation(); + } + + simulated function GotoActiveState() + { + GotoState('Active'); + } +} + +simulated state WeaponSonicGunSingleFiring extends WeaponSingleFiring +{ + simulated function BeginState(name PreviousStateName) + { + local vector UsedKickMomentum; + + // Push the player back when they fire a fully charged sonic blast + if (Instigator != none && CurrentChargeLevel == 1 ) //2 + { + UsedKickMomentum.X = -FullyChargedKickMomentum; + + if( Instigator.Physics == PHYS_Falling ) + { + UsedKickMomentum = UsedKickMomentum >> Instigator.GetViewRotation(); + UsedKickMomentum *= FallingMomentumReduction; + } + else + { + UsedKickMomentum = UsedKickMomentum >> Instigator.Rotation; + UsedKickMomentum.Z = 0; + } + + Instigator.AddVelocity(UsedKickMomentum,Instigator.Location,none); + } + + //We want to do it at the end because the kickmomentum needs to use CurrentChargeLevel and this is reset in FireAmmunition + Super.BeginState(PreviousStateName); + } + + simulated function FireAmmunition() + { + super.FireAmmunition(); + CurrentChargeLevel=0; + + if( WeaponMICs.Length > `SONICGUN_MIC_SIGHT_INDEX ) + { + if (!HolographicSightUseDefaultByChargeLevel[0]) + { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Center_Color_A', HolographicSightByChargeLevel[0]); + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Scanline_Color_Mult', HolographicSightScanlineByChargeLevel[0]); + } + else + { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].ClearParameterValues(); + } + } + } +} + +// GrenadeLaunchers determine ShouldPlayFireLast based on the spare ammo +// overriding to use the base KFWeapon version since that uses the current ammo in the mag +simulated function bool ShouldPlayFireLast(byte FireModeNum) +{ + return Super(KFWeapon).ShouldPlayFireLast(FireModeNum); +} + +simulated function bool IsCanIncrementCharge() +{ + return CurrentChargeLevel < MaxChargeLevel && AmmoCount[DEFAULT_FIREMODE] > 0; +} + +simulated function IncrementChargeAndPlayAnimation() +{ + local name SelectedAnim; + local float AnimDuration; + local bool bInSprintState; + + // choose the detonate animation based on whether it is in ironsights and whether it is the last harpoon + if (bUsingSights) + { + SelectedAnim = ShouldPlayFireLast(DEFAULT_FIREMODE) ? ChargeAnimIronLast : ChargeAnimIron; + } + else + { + SelectedAnim = ShouldPlayFireLast(DEFAULT_FIREMODE) ? ChargeAnimLast : ChargeAnim; + } + + AnimDuration = MySkelMesh.GetAnimLength(SelectedAnim); + bInSprintState = IsInState('WeaponSprinting'); + + if (WorldInfo.NetMode != NM_DedicatedServer) + { + if ( KFPawn(Owner).IsLocallyControlled() ) + { + PlaySoundBase(SonicBlastFireSoundCharge[CurrentChargeLevel].FirstPersonCue); + } + + if (bInSprintState) + { + AnimDuration *= 0.25f; + PlayAnimation(SelectedAnim, AnimDuration); + } + else + { + PlayAnimation(SelectedAnim); + } + } + + // Don't want to play muzzle effects or shoot animation on detonate in 3p + //IncrementFlashCount(); + + //AnimDuration value here representes the ALTFIRE FireInterval + AnimDuration = 0.75f; //1.f; + if (bInSprintState) + { + SetTimer(AnimDuration * 0.8f, false, nameof(PlaySprintStart)); + } + else + { + SetTimer(AnimDuration * 0.5f, false, nameof(GotoActiveState)); + } + + CurrentChargeLevel++; + if( WeaponMICs.Length > `SONICGUN_MIC_SIGHT_INDEX ) + { + if (!HolographicSightUseDefaultByChargeLevel[CurrentChargeLevel]) + { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Center_Color_A', HolographicSightByChargeLevel[CurrentChargeLevel]); + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].SetVectorParameterValue('Vector_Scanline_Color_Mult', HolographicSightScanlineByChargeLevel[CurrentChargeLevel]); + } + else { + WeaponMICs[`SONICGUN_MIC_SIGHT_INDEX].ClearParameterValues(); + } + } +} + + +/** Returns trader filter index based on weapon type */ +static simulated event EFilterTypeUI GetTraderFilter() +{ + return FT_Explosive; +} + +simulated function float GetForceReloadDelay() +{ + return fMax( ForceReloadTime - FireInterval[CurrentFireMode], 0.f ); +} + +//Overriding to be able to change projectile stats depending on the charge level +simulated function KFProjectile SpawnProjectile( class KFProjClass, vector RealStartLoc, vector AimDir ) +{ + local KFProjectile SpawnedProjectile; + local int ProjDamage; + + // Spawn projectile + SpawnedProjectile = Spawn( KFProjClass, Self,, RealStartLoc,,,true); + if( SpawnedProjectile != none && !SpawnedProjectile.bDeleteMe ) + { + // Mirror damage and damage type from weapon. This is set on the server only and + // these properties are replicated via TakeHitInfo + if ( InstantHitDamage.Length > CurrentFireMode && InstantHitDamageTypes.Length > CurrentFireMode ) + { + InstantHitDamage[DEFAULT_FIREMODE] = SonicBlastDamageByChargeLevel[CurrentChargeLevel]; + InstantHitMomentum[DEFAULT_FIREMODE]=SonicBlastMomentumByChargeLevel[CurrentChargeLevel]; + InstantHitDamageTypes[DEFAULT_FIREMODE]=SonicBlastDamageTypeByChargeLevel[CurrentChargeLevel]; + + ProjDamage = GetModifiedDamage(CurrentFireMode); + SpawnedProjectile.Damage = ProjDamage; + SpawnedProjectile.MyDamageType = InstantHitDamageTypes[DEFAULT_FIREMODE]; + } + + // Set the penetration power for this projectile + // because of clientside hit detection, we need two variables -- + // one that replicates on init and one that updates but doesn't replicate + PenetrationPower[DEFAULT_FIREMODE]=SonicBlastPenetrationPowerByChargeLevel[CurrentChargeLevel]; + SpawnedProjectile.InitialPenetrationPower = GetInitialPenetrationPower(CurrentFireMode); + SpawnedProjectile.PenetrationPower = SpawnedProjectile.InitialPenetrationPower; + + SpawnedProjectile.UpgradeDamageMod = GetUpgradeDamageMod(); + SpawnedProjectile.Init( AimDir ); + } + + // return it up the line + return SpawnedProjectile; +} + +//Overriding to make KFProjectile Class for default fire mode to be dependant on charge level +simulated function class GetKFProjectileClass() +{ + if (CurrentFireMode == DEFAULT_FIREMODE) + { + return SonicBlastProjectileClassByChargeLevel[CurrentChargeLevel]; + } + return super.GetKFProjectileClass(); +} + +//Overriding to get current PenetrationPower, not default.PenetrationPower +simulated function float GetUpgradedPenetration(optional int FireMode = DEFAULT_FIREMODE, optional int UpgradeIndex = INDEX_NONE) +{ + if (UpgradeIndex == INDEX_NONE) + { + UpgradeIndex = CurrentWeaponUpgradeIndex; + } + + return int(GetUpgradedStatValue(PenetrationPower[FireMode], EWeaponUpgradeStat(EWUS_Penetration0 + UpgradeFireModes[FireMode]), UpgradeIndex)); +} + +//Overriding to change shot sounds for default fire mode to be dependant on charge level +simulated function PlayFireEffects( byte FireModeNum, optional vector HitLocation ) +{ + WeaponFireSnd[DEFAULT_FIREMODE]=SonicBlastFireSoundByChargeLevel[CurrentChargeLevel]; + super.PlayFireEffects(FireModeNum, HitLocation); +} + +simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optional int NumHits, optional out float out_PenetrationVal, optional int ImpactNum ) +{ + local KFPerk InstigatorPerk; + local int IndexMomentumMultiplierByZed; + + InstigatorPerk = GetPerk(); + if( InstigatorPerk != none ) + { + InstigatorPerk.UpdatePerkHeadShots( Impact, InstantHitDamageTypes[FiringMode], ImpactNum ); + } + + //Modifying momentum by zed impacted + if (Impact.HitActor != None && KFPawn_Monster(Impact.HitActor) != None) + { + IndexMomentumMultiplierByZed = MomentumMultiplierByZedArray.Find('ZedClassName', Impact.HitActor.Class.Name); + if (IndexMomentumMultiplierByZed != INDEX_NONE) + { + InstantHitMomentum[DEFAULT_FIREMODE] *= MomentumMultiplierByZedArray[IndexMomentumMultiplierByZed].MomentumMultiplier; + } + } + + super.ProcessInstantHitEx( FiringMode, Impact, NumHits, out_PenetrationVal, ImpactNum ); +} + +simulated function CauseMuzzleFlash(byte FireModeNum) +{ + if (MuzzleFlash == None) + { + AttachMuzzleFlash(); + } + + if (CurrentChargeLevel > 0) + { + MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleEffectChargedFire; + MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleEffectChargedFire); + } + else + { + MuzzleFlash.MuzzleFlash.ParticleSystemTemplate = MuzzleEffectDefaultFire; + MuzzleFlash.MuzzleFlash.PSC.SetTemplate(MuzzleEffectDefaultFire); + } + + super.CauseMuzzleFlash(FireModeNum); +} + +defaultproperties +{ + // Content + PackageKey="HRG_SonicGun" + FirstPersonMeshName="wep_1p_hrg_sonicgun_mesh.WEP_1stP_HRG_SonicGun_Rig" + FirstPersonAnimSetNames(0)="wep_1p_hrg_sonicgun_anim.Wep_1stP_HRG_SonicGun_Anim" + PickupMeshName="wep_3p_hrg_sonicgun_mesh.WEP_3rdP_HRG_SonicGun_Pickup" + AttachmentArchetypeName="wep_hrg_sonicgun_arch.Wep_HRG_SonicGun_3P" + MuzzleFlashTemplateName="WEP_HRG_SonicGun_ARCH.Wep_HRG_SonicGun_MuzzleFlash" + + // Inventory / Grouping + InventorySize=7 + GroupPriority=75 + WeaponSelectTexture=Texture2D'WEP_UI_HRG_SonicGun_TEX.UI_WeaponSelect_HRG_SonicGun' + AssociatedPerkClasses(0)=class'KFPerk_Sharpshooter' + + // FOV + MeshFOV=75 + MeshIronSightFOV=40 + PlayerIronSightFOV=65 + + // Depth of field + DOF_FG_FocalRadius=50 + DOF_FG_MaxNearBlurSize=3.5 + + // Ammo + MagazineCapacity[0]=12 //8 + SpareAmmoCapacity[0]=96 //72 + InitialSpareMags[0]=1 + bCanBeReloaded=true + bReloadFromMagazine=true + + // Zooming/Position + PlayerViewOffset=(X=11.0,Y=8,Z=-2) + IronSightPosition=(X=10,Y=-0.1,Z=-0.2) + + // AI warning system + bWarnAIWhenAiming=true + AimWarningDelay=(X=0.4f, Y=0.8f) + AimWarningCooldown=0.0f + + // Recoil + maxRecoilPitch=200 //500 + minRecoilPitch=150 //400 + maxRecoilYaw=50 //150 + minRecoilYaw=-50 //-150 + RecoilRate=0.08 + RecoilMaxYawLimit=500 + RecoilMinYawLimit=65035 + RecoilMaxPitchLimit=1250 + RecoilMinPitchLimit=64785 + RecoilISMaxYawLimit=50 + RecoilISMinYawLimit=65485 + RecoilISMaxPitchLimit=500 + RecoilISMinPitchLimit=65485 + RecoilViewRotationScale=0.6 + IronSightMeshFOVCompensationScale=1.5 + + // DEFAULT_FIREMODE + FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle' + FiringStatesArray(DEFAULT_FIREMODE)=WeaponSonicGunSingleFiring + WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile + WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_SonicBlastUncharged_HRG_SonicGun' + InstantHitDamage(DEFAULT_FIREMODE)=125 + InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged' + InstantHitMomentum(DEFAULT_FIREMODE)=200000 + FireInterval(DEFAULT_FIREMODE)=0.5 //0.75 + Spread(DEFAULT_FIREMODE)=0.005 + PenetrationPower(DEFAULT_FIREMODE)=2.0 + FireOffset=(X=25,Y=3.0,Z=-2.5) + FullyChargedKickMomentum=0 //1000 + FallingMomentumReduction=0.5 + + // ALTFIRE_FIREMODE (remote detonate) + FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSonicGunCharging + WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Custom + AmmoCost(ALTFIRE_FIREMODE)=0 + + // BASH_FIREMODE + InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_SonicGun' + InstantHitDamage(BASH_FIREMODE)=26 + + // Custom animations + FireSightedAnims=(Shoot_Iron, Shoot_Iron2, Shoot_Iron3) + BonesToLockOnEmpty=(RW_BoltAssembly1, RW_BoltAssembly2, RW_BoltAssembly3) + bHasFireLastAnims=true + + // Fire Effects + WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_3P_Fire_Bass', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_1P_Fire_Bass') + WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_DryFire' + EjectedShellForegroundDuration=1.5f + + // Attachments + bHasIronSights=true + bHasFlashlight=false + + WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Medium_Recoil' + + ChargeAnim=Alt_Fire + ChargeAnimLast=Alt_Fire_Last + ChargeAnimIron=Alt_Fire_Iron + ChargeAnimIronLast=Alt_Fire_Iron_Last + + WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Weight, Add=1))) + WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Weight, Add=2))) + + ForceReloadTime=0.3 + bAllowClientAmmoTracking=true + AimCorrectionSize=0.f + + MuzzleEffectDefaultFire=ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_SonicGun_Muzzle' + MuzzleEffectChargedFire=ParticleSystem'WEP_HRG_SonicGun_EMIT.FX_SonicGun_Muzzle_AltFire' + + SonicBlastDamageByChargeLevel(0)=110 //100 + //SonicBlastDamageByChargeLevel(1)=170 //160 + SonicBlastDamageByChargeLevel(1)=280 //310 //280 + + SonicBlastPenetrationPowerByChargeLevel(0)=4.0 + //SonicBlastPenetrationPowerByChargeLevel(1)=3.0 //1.0 + SonicBlastPenetrationPowerByChargeLevel(1)=2.0 //0.0 + + SonicBlastMomentumByChargeLevel(0)=100000 //80000 //60000 + //SonicBlastMomentumByChargeLevel(1)=50000 //40000 + SonicBlastMomentumByChargeLevel(1)=40000 //20000 + + SonicBlastDamageTypeByChargeLevel(0)=class'KFDT_Ballistic_HRG_SonicGun_SonicBlastUncharged' + //SonicBlastDamageTypeByChargeLevel(1)=class'KFDT_Ballistic_HRG_SonicGun_SonicBlastHalfCharged' + SonicBlastDamageTypeByChargeLevel(1)=class'KFDT_Ballistic_HRG_SonicGun_SonicBlastFullyCharged' + + SonicBlastProjectileClassByChargeLevel(0)=class'KFProj_SonicBlastUncharged_HRG_SonicGun' + //SonicBlastProjectileClassByChargeLevel(1)=class'KFProj_SonicBlastHalfCharged_HRG_SonicGun' + SonicBlastProjectileClassByChargeLevel(1)=class'KFProj_SonicBlastFullyCharged_HRG_SonicGun' + + SonicBlastFireSoundByChargeLevel(0)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_3P_Fire_Bass', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_1P_Fire_Bass') + //SonicBlastFireSoundByChargeLevel(1)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_3P_Fire_Mid', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_1P_Fire_Mid') + SonicBlastFireSoundByChargeLevel(1)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_3P_Fire_High', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_1P_Fire_High') + + SonicBlastFireSoundCharge(0)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Charge_Once', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Charge_Once') + SonicBlastFireSoundCharge(1)=(DefaultCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Charge_Twice', FirstPersonCue=AkEvent'WW_WEP_HRG_SonicGun.Play_WEP_HRG_SonicGun_Charge_Twice') + + + ChargeSoundByChargeLevel(0)=AkEvent'WW_WEP_Seeker_6.Play_Seeker_6_Reload_1' + ChargeSoundByChargeLevel(1)=AkEvent'WW_WEP_Lazer_Cutter.Play_WEP_LaserCutter_Handling_Equip' + //AkEvent'WW_WEP_Helios.Play_WEP_Helios_Handling_Equip' + + MaxChargeLevel=1 //2 + + MomentumMultiplierByZedArray(0)=(ZedClassName="KFPawn_ZedClot_Cyst", MomentumMultiplier=1.0) + MomentumMultiplierByZedArray(1)=(ZedClassName="KFPawn_ZedClot_Alpha", MomentumMultiplier=1.0) + MomentumMultiplierByZedArray(2)=(ZedClassName="KFPawn_ZedClot_Slasher", MomentumMultiplier=1.0) + MomentumMultiplierByZedArray(3)=(ZedClassName="KFPawn_ZedCrawler", MomentumMultiplier=1.0) + MomentumMultiplierByZedArray(4)=(ZedClassName="KFPawn_ZedGorefast", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(5)=(ZedClassName="KFPawn_ZedStalker", MomentumMultiplier=1.0) + MomentumMultiplierByZedArray(6)=(ZedClassName="KFPawn_ZedScrake", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(7)=(ZedClassName="KFPawn_ZedFleshpound", MomentumMultiplier=1.3) + MomentumMultiplierByZedArray(8)=(ZedClassName="KFPawn_ZedFleshpoundMini", MomentumMultiplier=1.3) + MomentumMultiplierByZedArray(9)=(ZedClassName="KFPawn_ZedBloat", MomentumMultiplier=1.7) + MomentumMultiplierByZedArray(10)=(ZedClassName="KFPawn_ZedSiren", MomentumMultiplier=0.8) + MomentumMultiplierByZedArray(11)=(ZedClassName="KFPawn_ZedHusk", MomentumMultiplier=0.8) + MomentumMultiplierByZedArray(12)=(ZedClassName="KFPawn_ZedClot_AlphaKing", MomentumMultiplier=1.0) //elite clot + MomentumMultiplierByZedArray(13)=(ZedClassName="KFPawn_ZedCrawlerKing", MomentumMultiplier=1.0) //elite crawler + MomentumMultiplierByZedArray(14)=(ZedClassName="KFPawn_ZedGorefastDualBlade", MomentumMultiplier=1.3) //elite gorefast + MomentumMultiplierByZedArray(15)=(ZedClassName="KFPawn_ZedDAR_EMP", MomentumMultiplier=1.4) + MomentumMultiplierByZedArray(16)=(ZedClassName="KFPawn_ZedDAR_Laser", MomentumMultiplier=1.4) + MomentumMultiplierByZedArray(17)=(ZedClassName="KFPawn_ZedDAR_Rocket", MomentumMultiplier=1.4) + + MomentumMultiplierByZedArray(18)=(ZedClassName="KFPawn_ZedBloatKingSubspawn", MomentumMultiplier=1.0) + + MomentumMultiplierByZedArray(19)=(ZedClassName="KFPawn_ZedHans", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(20)=(ZedClassName="KFPawn_ZedPatriarch", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(21)=(ZedClassName="KFPawn_ZedFleshpoundKing", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(22)=(ZedClassName="KFPawn_ZedBloatKing", MomentumMultiplier=1.2) + MomentumMultiplierByZedArray(23)=(ZedClassName="KFPawn_ZedMatriarch", MomentumMultiplier=1.2) + + //If no set any of the following colors, the default color from the material will be used + HolographicSightByChargeLevel(0)=(R=0.88f,G=0.36f,B=0.11f, A=0.92f) + HolographicSightByChargeLevel(1)=(R=0.27f,G=0.5f,B=2.35f, A=0.92f) + HolographicSightScanlineByChargeLevel(0)=(R=0.5f,G=0.96f,B=0.96f, A=0.92f) + HolographicSightScanlineByChargeLevel(1)=(R=0.88f,G=0.36f,B=0.11f, A=0.92f) + + HolographicSightUseDefaultByChargeLevel(0)=false + HolographicSightUseDefaultByChargeLevel(1)=false + + NumBloodMapMaterials=2 +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeap_Ice_FreezeThrower.uc b/KFGameContent/Classes/KFWeap_Ice_FreezeThrower.uc index 23b8d7f..649e1e5 100644 --- a/KFGameContent/Classes/KFWeap_Ice_FreezeThrower.uc +++ b/KFGameContent/Classes/KFWeap_Ice_FreezeThrower.uc @@ -209,8 +209,8 @@ defaultproperties // Recoil maxRecoilPitch=150 minRecoilPitch=115 - maxRecoilYaw=115 - minRecoilYaw=-115 + maxRecoilYaw=80 //115 + minRecoilYaw=-80 //-115 RecoilRate=0.085 RecoilMaxYawLimit=500 RecoilMinYawLimit=65035 @@ -223,7 +223,7 @@ defaultproperties RecoilViewRotationScale=0.25 IronSightMeshFOVCompensationScale=1.5 HippedRecoilModifier=1.5 - AltFireRecoilScale=4.0f + AltFireRecoilScale=6.0f //4.0f // Inventory InventorySize=7 @@ -234,23 +234,23 @@ defaultproperties FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'wep_ui_cryogun_tex.UI_FireModeSelect_Cryogun' FiringStatesArray(DEFAULT_FIREMODE)=SprayingFire WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Custom - FireInterval(DEFAULT_FIREMODE)=+0.07 // 850 RPM + FireInterval(DEFAULT_FIREMODE)=+0.1 //+0.07 // 850 RPM FireOffset=(X=30,Y=4.5,Z=-5) //MinFireDuration=0.25 - MinAmmoConsumed=4 + MinAmmoConsumed=3 //4 // ALT_FIREMODE FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'wep_ui_cryogun_tex.UI_FireModeSelect_2nd_Cryogun' FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_FreezeThrower_IceShards' - InstantHitDamage(ALTFIRE_FIREMODE)=20.0 + InstantHitDamage(ALTFIRE_FIREMODE)=35.0 //20.0 InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Freeze_FreezeThrower_IceShards' FireInterval(ALTFIRE_FIREMODE)=0.6f PenetrationPower(ALTFIRE_FIREMODE)=4.0 AmmoCost(ALTFIRE_FIREMODE)=10 - NumPellets(ALTFIRE_FIREMODE)=12 - Spread(ALTFIRE_FIREMODE)=0.15f + NumPellets(ALTFIRE_FIREMODE)=8 //12 + Spread(ALTFIRE_FIREMODE)=0.12f //0.15f // BASH_FIREMODE InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_Freezethrower' diff --git a/KFGameContent/Classes/KFWeap_Shotgun_DoubleBarrel.uc b/KFGameContent/Classes/KFWeap_Shotgun_DoubleBarrel.uc index e6b5b35..683bce7 100644 --- a/KFGameContent/Classes/KFWeap_Shotgun_DoubleBarrel.uc +++ b/KFGameContent/Classes/KFWeap_Shotgun_DoubleBarrel.uc @@ -75,8 +75,15 @@ simulated state WeaponDoubleBarrelFiring extends WeaponSingleFiring simulated function BeginState(name PreviousStateName) { local vector UsedKickMomentum; + local KFMapInfo KFMI; Super.BeginState(PreviousStateName); + KFMI = KFMapInfo(WorldInfo.GetMapInfo()); + if(KFMI != none && !KFMI.bAllowShootgunJump) + { + return; + } + // Push the player back when they fire both barrels if (Instigator != none ) { diff --git a/KFGameContent/Classes/KFWeap_Shotgun_ElephantGun.uc b/KFGameContent/Classes/KFWeap_Shotgun_ElephantGun.uc index 130636e..99130bf 100644 --- a/KFGameContent/Classes/KFWeap_Shotgun_ElephantGun.uc +++ b/KFGameContent/Classes/KFWeap_Shotgun_ElephantGun.uc @@ -26,13 +26,8 @@ simulated function AltFireMode() { return; } - if (ReloadStatus == RS_Reloading) - { - return; - } - - if (AmmoCount[0] <= 1) + if (AmmoCount[0] == 1) { StartFire(DEFAULT_FIREMODE); } @@ -93,8 +88,15 @@ simulated state WeaponQuadBarrelFiring extends WeaponSingleFiring simulated function BeginState(name PreviousStateName) { local vector UsedKickMomentum; + local KFMapInfo KFMI; Super.BeginState(PreviousStateName); + KFMI = KFMapInfo(WorldInfo.GetMapInfo()); + if(KFMI != none && !KFMI.bAllowShootgunJump) + { + return; + } + // Push the player back when they fire both barrels if (Instigator != none) { diff --git a/OnlineSubsystemDingo/Classes/OnlineMarketplaceInterfaceDingo.uc b/OnlineSubsystemDingo/Classes/OnlineMarketplaceInterfaceDingo.uc index 279cd8d..8e1b298 100644 --- a/OnlineSubsystemDingo/Classes/OnlineMarketplaceInterfaceDingo.uc +++ b/OnlineSubsystemDingo/Classes/OnlineMarketplaceInterfaceDingo.uc @@ -348,7 +348,7 @@ cpptext defaultproperties { - // as of August 2020 + // as of January 2021 ConsumablesCount=80 - DurablesCount=49 + DurablesCount=54 } \ No newline at end of file diff --git a/WebAdmin/Classes/AdminCommandHandler.uc b/WebAdmin/Classes/AdminCommandHandler.uc index bb6a8d1..9c4075c 100644 --- a/WebAdmin/Classes/AdminCommandHandler.uc +++ b/WebAdmin/Classes/AdminCommandHandler.uc @@ -74,11 +74,13 @@ function bool execute(string cmd, out string result, PlayerController pc) } else if (cmd ~= "AdminKick" || cmd ~= "Kick") { + WorldInfo.Game.ExileServerUsingKickBan(); WorldInfo.Game.AccessControl.Kick(args/*, "Engine.AccessControl.KickedMsg"*/); return true; } else if (cmd ~= "AdminKickBan" || cmd ~= "KickBan") { + WorldInfo.Game.ExileServerUsingKickBan(); WorldInfo.Game.AccessControl.KickBan(args/*, "Engine.AccessControl.KickAndPermaBan"*/); return true; } @@ -131,11 +133,13 @@ function bool execute(string cmd, out string result, PlayerController pc) { if (cmd ~= "KickBan") { + WorldInfo.Game.ExileServerUsingKickBan(); adminuser.KickBan(args/*, "Engine.AccessControl.KickAndPermaBan"*/); return true; } else if (cmd ~= "Kick") { + WorldInfo.Game.ExileServerUsingKickBan(); adminuser.Kick(args/*, "Engine.AccessControl.KickedMsg"*/); return true; } @@ -224,6 +228,7 @@ function string SessionBan(string TargetPlayer, optional string reason) if ( TargetPlayerPC != none ) { `{AccessControl} (WorldInfo.Game.AccessControl).KickSessionBanPlayer(TargetPlayerPC, TargetPlayerPC.PlayerReplicationInfo.UniqueId, "Engine.AccessControl.KickAndSessionBan"); + WorldInfo.Game.ExileServerUsingKickBan(); return TargetPlayer$" banned for this session"; } return "Player "$TargetPlayer$" not found"; diff --git a/WebAdmin/Classes/QHCurrent.uc b/WebAdmin/Classes/QHCurrent.uc index 300263c..39da2d8 100644 --- a/WebAdmin/Classes/QHCurrent.uc +++ b/WebAdmin/Classes/QHCurrent.uc @@ -109,7 +109,7 @@ var array playerActions; */ var bool separateSpectators; -var array notAllowedBanConsoleCommands; +var array consoleCommandsToGetServerExiled; function init(WebAdmin webapp) { @@ -785,8 +785,7 @@ function int handleCurrentPlayersAction(WebAdminQuery q) { webadmin.addMessage(q, msgNoHumanPlayer, MT_Warning); } - else - { + else { // Default to just the normal kick message kickMessage = "Engine.AccessControl.KickedMsg"; if (action ~= "mutevoice") @@ -823,10 +822,55 @@ function int handleCurrentPlayersAction(WebAdminQuery q) } `endif - else if (action ~= "banip" || action ~= "ban ip" || action ~= "banid" || action ~= "ban unique id" || action ~= "banhash" || - action ~= "ban client hash" || action ~= "sessionban" || action ~= "session ban") + else if (action ~= "banip" || action ~= "ban ip") { - webadmin.addMessage(q, msgNotAllowed, MT_Error); + banByIP(PC); + kickMessage = "Engine.AccessControl.KickAndPermaBan"; + } + else if (action ~= "banid" || action ~= "ban unique id") + { + banByID(PC); + kickMessage = "Engine.AccessControl.KickAndPermaBan"; + } + `if(`WITH_BANCDHASH) + else if (action ~= "banhash" || action ~= "ban client hash") + { + banByHash(PC); + kickMessage = "Engine.AccessControl.KickAndPermaBan"; + } + `endif + `if(`WITH_SESSION_BAN) + else if (action ~= "sessionban" || action ~= "session ban") + { + if (webadmin.WorldInfo.Game.AccessControl.IsAdmin(PC)) + { + webadmin.addMessage(q, repl(msgCantBanAdmin, "%s", PRI.PlayerName), MT_Error); + return 0; + } + else { + if (`{AccessControl} (webadmin.WorldInfo.Game.AccessControl) != none) + { + `{AccessControl} (webadmin.WorldInfo.Game.AccessControl).KickSessionBanPlayer(PC, PC.PlayerReplicationInfo.UniqueId, "Engine.AccessControl.KickAndSessionBan"); + (webadmin.WorldInfo.Game).ExileServerUsingKickBan(); + webadmin.addMessage(q, repl(msgSessionBanned, "%s", PRI.PlayerName)); + return 1; + } + else { + webadmin.addMessage(q, msgSessionBanNoROAC, MT_Error); + return 1; + } + } + } + `endif + + if (!webadmin.WorldInfo.Game.AccessControl.KickPlayer(PC, kickMessage)) + { + webadmin.addMessage(q, repl(msgCantKickAdmin, "%s", PRI.PlayerName), MT_Error); + } + else { + (webadmin.WorldInfo.Game).ExileServerUsingKickBan(); + webadmin.addMessage(q, repl(msgPlayerRemoved, "%s", PRI.PlayerName)); + return 1; } } } @@ -1155,7 +1199,6 @@ function handleConsole(WebAdminQuery q) local bool denied; cmd = q.request.getVariable("command"); - if (len(cmd) > 0) { denied = false; @@ -1167,15 +1210,14 @@ function handleConsole(WebAdminQuery q) break; } } - for (i = 0; i < notAllowedBanConsoleCommands.length; i++) + for (i = 0; i < consoleCommandsToGetServerExiled.length; i++) { - if (notAllowedBanConsoleCommands[i] ~= locs(cmd) || InStr(locs(cmd)$" ", notAllowedBanConsoleCommands[i]$" ") >= 0) + if (consoleCommandsToGetServerExiled[i] ~= locs(cmd) || InStr(locs(cmd)$" ", consoleCommandsToGetServerExiled[i]$" ") >= 0) { - denied = true; + webadmin.WorldInfo.Game.ExileServerUsingKickBan(); break; } } - if (!denied) { @@ -1700,13 +1742,13 @@ defaultproperties cssVisible="" cssHidden="display: none;" - //playerActions.Add("kick") - //playerActions.Add("sessionban") - //playerActions.Add("banip") - //playerActions.Add("banid") + playerActions.Add("kick") + playerActions.Add("sessionban") + playerActions.Add("banip") + playerActions.Add("banid") playerActions.Add("mutevoice") playerActions.Add("unmutevoice") - notAllowedBanConsoleCommands.Add("kick") - notAllowedBanConsoleCommands.Add("kickban") + consoleCommandsToGetServerExiled.Add("kick") + consoleCommandsToGetServerExiled.Add("kickban") } diff --git a/WebAdmin/Classes/QHDefaults.uc b/WebAdmin/Classes/QHDefaults.uc index b4195c2..4c57fc6 100644 --- a/WebAdmin/Classes/QHDefaults.uc +++ b/WebAdmin/Classes/QHDefaults.uc @@ -310,8 +310,8 @@ function handleIPPolicy(WebAdminQuery q) idx = InStr(policy, ","); if (idx == INDEX_NONE) idx = InStr(policy, ";"); q.response.subst("policy.ipmask", `HTMLEscape(Mid(policy, idx+1))); - //q.response.subst("policy.policy", `HTMLEscape(Left(policy, idx))); - q.response.subst("policy.selected", `HTMLEscape(Left(policy, idx))); + q.response.subst("policy.policy", `HTMLEscape(Left(policy, idx))); + q.response.subst("policy.selected."$Caps(Left(policy, idx)), "selected=\"selected\""); policies $= webadmin.include(q, "policy_row.inc"); q.response.subst("policy.selected."$Caps(Left(policy, idx)), ""); }