diff --git a/Engine/Classes/OnlineSubsystem.uc b/Engine/Classes/OnlineSubsystem.uc index 0b20fbe..49a2182 100644 --- a/Engine/Classes/OnlineSubsystem.uc +++ b/Engine/Classes/OnlineSubsystem.uc @@ -1516,6 +1516,9 @@ struct native ItemProperties var int AltPerkId; //index bassed off our array var int WeaponType; var int FilterIdIndex; + var bool ItemOnSale; + var string BasePrice; + var string DiscountRate; structcpptext { @@ -1537,6 +1540,9 @@ struct native ItemProperties }; var array ItemPropertiesList; +var bool bSalesEvent; +var bool bSalesEventChecked; + struct native ExchangeRule { var int Definition; diff --git a/KFGame/Classes/KFCharacterInfo_Human.uc b/KFGame/Classes/KFCharacterInfo_Human.uc index 95a2de2..b149919 100644 --- a/KFGame/Classes/KFCharacterInfo_Human.uc +++ b/KFGame/Classes/KFCharacterInfo_Human.uc @@ -358,7 +358,7 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic { NumberOfCosmetics++; bMaskHeadMesh = bMaskHeadMesh || CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh; - + // Attach all saved attachments to the character SetAttachmentMeshAndSkin( CosmeticMeshIdx, @@ -368,21 +368,21 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic } // Check again for all cosmetic in case one of them was removed, this will fix problems with masked heads - for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ ) + /*for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ ) { CosmeticMeshIdx = KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx]; if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE) { NumberOfCosmeticsPostRemoval++; } - } - + }*/ + // If the number of cosmetics changed, made a new set of the mesh/cosmetics recursively and return - if(NumberOfCosmeticsPostRemoval != NumberOfCosmetics) + /*if(NumberOfCosmeticsPostRemoval != NumberOfCosmetics) { SetCharacterMeshFromArch( KFP, KFPRI ); return; - } + }*/ InitCharacterMICs(KFP, bMaskHeadMesh); } @@ -781,7 +781,6 @@ private function SetAttachmentMeshAndSkin( local string CharAttachmentMeshName; local name CharAttachmentSocketName; local int AttachmentSlotIndex; - if (KFP.WorldInfo.NetMode == NM_DedicatedServer) { return; @@ -791,7 +790,6 @@ private function SetAttachmentMeshAndSkin( //DetachConflictingAttachments(CurrentAttachmentMeshIndex, KFP, KFPRI); // Get a slot where this attachment could fit AttachmentSlotIndex = GetAttachmentSlotIndex(CurrentAttachmentMeshIndex, KFP, KFPRI); - if (AttachmentSlotIndex == INDEX_NONE) { return; @@ -880,11 +878,11 @@ private function SetAttachmentMeshAndSkin( * Removes any attachments that exist in the same socket or have overriding cases * Network: Local Player */ -function DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI) +function array DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI, optional out array out_RemovedAttachments ) { local name NewAttachmentSocketName; local int i, CurrentAttachmentIdx; - + if ( CosmeticVariants.length > 0 && NewAttachmentMeshIndex < CosmeticVariants.length && NewAttachmentMeshIndex != INDEX_NONE) { @@ -902,6 +900,7 @@ function DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, op KFP.ThirdPersonAttachmentSocketNames[i] == NewAttachmentSocketName ) { RemoveAttachmentMeshAndSkin(i, KFP, KFPRI); + out_RemovedAttachments.AddItem(i); continue; } @@ -909,6 +908,7 @@ function DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, op if( GetOverrideCase(CurrentAttachmentIdx, NewAttachmentMeshIndex) ) { RemoveAttachmentMeshAndSkin(i, KFP, KFPRI); + out_RemovedAttachments.AddItem(i); continue; } @@ -916,6 +916,7 @@ function DetachConflictingAttachments(int NewAttachmentMeshIndex, KFPawn KFP, op if( GetOverrideCase(NewAttachmentMeshIndex, CurrentAttachmentIdx) ) { RemoveAttachmentMeshAndSkin(i, KFP, KFPRI); + out_RemovedAttachments.AddItem(i); continue; } } @@ -995,8 +996,7 @@ function int GetAttachmentSlotIndex( // Return the next available attachment index or the index that matches this mesh for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ ) { - if (KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx] == INDEX_NONE || - KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx] == CurrentAttachmentMeshIndex) + if (KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx] == CurrentAttachmentMeshIndex) { return AttachmentIdx; } diff --git a/KFGame/Classes/KFCheatManager.uc b/KFGame/Classes/KFCheatManager.uc index a8bf966..05f1a65 100644 --- a/KFGame/Classes/KFCheatManager.uc +++ b/KFGame/Classes/KFCheatManager.uc @@ -261,6 +261,44 @@ exec function TestNumbPrompts(int NumberOfPrompts) } } +exec function TestMapMessage(String S, float time) +{ + local Pawn P; + local KFPlayerController KFPC; + + P = GetMyPawn(); + KFPC = KFPlayerController(Outer); + + if(P == none || KFPC == None) + { + return; + } + + if(KFPC.MyGFxHUD != none ) + { + KFPC.MyGFxHUD.MapTextWidget.DisplayMapText(S, time, true); + } +} + +exec function TestMapCounterMessage(String S, float time) +{ + local Pawn P; + local KFPlayerController KFPC; + + P = GetMyPawn(); + KFPC = KFPlayerController(Outer); + + if(P == none || KFPC == None) + { + return; + } + + if(KFPC.MyGFxHUD != none ) + { + KFPC.MyGFxHUD.MapCounterTextWidget.DisplayMapText(S, time); + } +} + exec function MakeFakePopUp() { local Pawn P; @@ -883,6 +921,14 @@ simulated exec function Minigun() GiveWeapon( "KFGameContent.KFWeap_Minigun" ); } +/** + * Give the player the Vampire + */ +simulated exec function Vampire() +{ + GiveWeapon( "KFGameContent.KFWeap_HRG_Vampire" ); +} + /** * Give the player all pistol weapons */ @@ -995,6 +1041,11 @@ simulated exec function MineRec() GiveWeapon( "KFGameContent.KFWeap_Mine_Reconstructor" ); } +simulated exec function FrostSAxe() +{ + GiveWeapon( "KFGameContent.KFWeap_Rifle_FrostShotgunAxe" ); +} + /** * Give the player all Medic weapons */ @@ -1010,6 +1061,7 @@ simulated exec function Medic() GiveWeapon( "KFGameContent.KFWeap_Rifle_HRGIncision" ); GiveWeapon( "KFGameContent.KFWeap_AssaultRifle_MedicRifleGrenadeLauncher" ); GiveWeapon( "KFGameContent.KFWeap_Blunt_MedicBat" ); + GiveWeapon( "KFGameContent.KFWeap_HRG_Vampire" ); } /** @@ -2361,7 +2413,7 @@ exec function PathInfo() ClientMessage( "Paths last built: "$WorldInfo.LastSuccessfulPathBuildTime, CheatType ); } -/** Sends all active NPCs and not-yet-spawned NPCs into or out of debug mode */ +/** Sends all active NPCs and not-yet-spawned NPCs into or out of debug mode */ exec function AIDebugMode( optional bool bDebugMode=true ) { local KFGameInfo KFG; diff --git a/KFGame/Classes/KFEmit_DirectionalPath.uc b/KFGame/Classes/KFEmit_DirectionalPath.uc new file mode 100644 index 0000000..e63479c --- /dev/null +++ b/KFGame/Classes/KFEmit_DirectionalPath.uc @@ -0,0 +1,219 @@ +//============================================================================= +// KFEmit_DirectionalPath +//============================================================================= +// Directional emitter +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================ + +class KFEmit_DirectionalPath extends Emitter; + +/** The Template to use for this emitter */ +var() ParticleSystem EmitterTemplate; + +/** path points to travel to */ +var vector DestinationFinal; +var vector DestinationMidPoint; +var vector DestinationCurrent; + +/** limit to destroy the partcile */ +var float LimitDistanceCurrent; +var float LimitDistanceCurrentPowed; +var float LimitDistanceDestinationFinal; +var float LimitDistanceDestinationMidPoint; + +/** rate to changed dir on curves */ +var float CurveTurnRateCurrent; +var float CurveTurnRateUntilDestinationFinal; +var float CurveTurnRateUntilDestinationMidPoint; + +var float RateTickCheckHasReached; + +var vector LastDir; +var vector NewDir; +var bool IsEnabled; + +/********************************************************************************************* +* Acceleration physics + ********************************************************************************************* */ + +/** Acceleration magnitude */ +var() float ParticleSpeed; + +var float HalfAngleSpawnCone; + +var transient bool bInitialized; + +var transient bool bReachDestinationFinal; +var transient bool bReachDestinationMidPoint; +var transient float TickCheckHasReachedTime; + +simulated function PostBeginPlay() +{ + //LifeSpan = 3.0; + TickCheckHasReachedTime = RateTickCheckHasReached; + Super.PostBeginPlay(); +} + +/** Override the final waypoint (optional) */ +simulated function SetDestination( vector NewDestinationFinal, + vector NewDestinationMidPoint, + float NewLimitDistanceDestinationFinal, + float NewLimitDistanceDestinationMidPoint, + float NewCurveTurnRateUntilDestinationFinal, + float NewCurveTurnRateUntilDestinationMidPoint, + float NewHalfAngleSpawnCone) +{ + DestinationFinal = NewDestinationFinal; + DestinationMidPoint = NewDestinationMidPoint; + + LimitDistanceDestinationFinal = NewLimitDistanceDestinationFinal; + LimitDistanceDestinationMidPoint = NewLimitDistanceDestinationMidPoint; + + CurveTurnRateUntilDestinationFinal = NewCurveTurnRateUntilDestinationFinal; + CurveTurnRateUntilDestinationMidPoint = NewCurveTurnRateUntilDestinationMidPoint; + + bReachDestinationFinal = false; + bReachDestinationMidPoint = false; + HalfAngleSpawnCone = NewHalfAngleSpawnCone; + + DestinationCurrent = DestinationMidPoint; + LimitDistanceCurrent = LimitDistanceDestinationMidPoint; + LimitDistanceCurrentPowed = LimitDistanceCurrent * LimitDistanceCurrent; + CurveTurnRateCurrent = CurveTurnRateUntilDestinationMidPoint; + + Velocity = VRandCone(Normal(DestinationCurrent - Location), HalfAngleSpawnCone) * ParticleSpeed; + LastDir = Normal(Velocity); + SetRotation(rotator(Normal(Velocity))); + SetPhysics(PHYS_Projectile); + + //OriginalDistanceToDestination = VSize(Destination - Location); + + bInitialized = true; +} + +simulated function UpdateDestination( vector NewDestinationFinal, optional vector NewDestinationMidPoint ) +{ + DestinationFinal = NewDestinationFinal; + DestinationMidPoint = NewDestinationMidPoint; + + DestinationCurrent = DestinationFinal; + if (!bReachDestinationMidPoint) + { + DestinationCurrent = DestinationMidPoint; + } +} + +simulated event SetTemplate(ParticleSystem NewTemplate, optional bool bDestroyOnFinish) +{ + Super(Emitter).SetTemplate(NewTemplate, bDestroyOnFinish); +} + +simulated function bool HasReachedDestinationFinal() +{ + Local bool bCloseEnough; + bCloseEnough = VSizeSq(Location - DestinationFinal) <= LimitDistanceCurrentPowed ; + return bCloseEnough; +} + +simulated function bool HasReachedDestinationMidPoint() +{ + Local bool bCloseEnough; + bCloseEnough = VSizeSq(Location - DestinationMidPoint) <= LimitDistanceCurrentPowed ; + return bCloseEnough; +} + + +simulated function Tick(float DeltaTime) +{ + if ( !bInitialized || IsEnabled == false ) + { + return; + } + + TickCheckHasReachedTime -= DeltaTime; + if (TickCheckHasReachedTime <= 0) + { + TickCheckHasReachedTime = RateTickCheckHasReached; + + if (bReachDestinationMidPoint) + { + if (bReachDestinationFinal) + { + SetLocation(DestinationFinal); + return; + } + if( HasReachedDestinationFinal() ) + { + bReachDestinationFinal = true; + SetLocation(DestinationFinal); + return; + } + } + else + { + if( HasReachedDestinationMidPoint() ) + { + bReachDestinationMidPoint = true; + DestinationCurrent = DestinationFinal; + LimitDistanceCurrent = LimitDistanceDestinationFinal; + LimitDistanceCurrentPowed = LimitDistanceCurrent * LimitDistanceCurrent; + CurveTurnRateCurrent = CurveTurnRateUntilDestinationFinal; + } + } + } + + + + + + //Acceleration = CurveTurnRate * DeltaTime * ACCEL_RATE * Normal(Destination - Location); + //Velocity = Velocity + Acceleration; // force double acceleration + NewDir = Normal(DestinationCurrent - Location); + SetRotation(rotator(LastDir + CurveTurnRateCurrent * NewDir)); + Velocity = vector(Rotation) * ParticleSpeed; + //SetRotation(rotator(Normal(Velocity))); + LastDir = vector(Rotation); + //Velocity = vector(Rotation) * ParticleSpeed; + + //DrawDebugSphere(Location, 12, 12, 255, 0, 0, false); +} + +simulated function DeactivateEmitter() +{ + ParticleSystemComponent.DeactivateSystem(); + IsEnabled = false; + bReachDestinationFinal = false; + bReachDestinationMidPoint = false; + SetTickIsDisabled(true); + SetHidden(true); +} + +simulated function ActivateEmitter() +{ + ParticleSystemComponent.ActivateSystem(); + IsEnabled = true; + bInitialized = true; + SetTickIsDisabled(false); + SetHidden(false); +} + +simulated function OnParticleSystemFinished(ParticleSystemComponent FinishedComponent) +{ + return; +} + +defaultproperties +{ + ParticleSpeed=600 + bNoDelete=false + bStatic=false + HalfAngleSpawnCone=60 + + LimitDistanceDestinationFinal=5 + LimitDistanceDestinationMidPoint=16 + CurveTurnRateUntilDestinationFinal=0.4 + CurveTurnRateUntilDestinationMidPoint=4.0 + RateTickCheckHasReached=0.05 +} diff --git a/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2020.uc b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2020.uc new file mode 100644 index 0000000..488c698 --- /dev/null +++ b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2020.uc @@ -0,0 +1,27 @@ +class KFGFXSpecialEventObjectivesContainer_Xmas2020 extends KFGFxSpecialEventObjectivesContainer; + +function Initialize(KFGFxObject_Menu NewParentMenu) +{ + super.Initialize(NewParentMenu); +} + +DefaultProperties +{ + ObjectiveIconURLs[0] = "Xmas_UI.UI_Objectives_Christmas2020_FrozenRoses" // Collect 3 roses in Elysium + ObjectiveIconURLs[1] = "Xmas_UI.UI_Objectives_Christmas2020_FourDifferentTales" // Collect 4 tomes in Elysium + ObjectiveIconURLs[2] = "Xmas_UI.UI_Objectives_Christmas2020_UnderTheMistletoe" // Complete one wave in Elysium's Botanica arena + ObjectiveIconURLs[3] = "Xmas_UI.UI_Objectives_Christmas2020_AChristmasCarol" // Complete one wave in Elysium's Loremaster Sanctum arena + ObjectiveIconURLs[4] = "Xmas_UI.UI_Objectives_Christmas2020_EverlastingWinter" // Complete wave 15 on Endless Hard or higher difficulty on Elysium + + //defaults + AllCompleteRewardIconURL="CHR_CosmeticSet_XMAS_04_Item_TEX.tacticalelfpack.tacticalelfpack_precious_large" + ChanceDropIconURLs[0]="CHR_Cosmetic_XMAS_Item_TEX.Tickets.Krampus_Ticket" + ChanceDropIconURLs[1]="CHR_Cosmetic_XMAS_Item_TEX.Tickets.Krampus_Ticket_Golden" + IconURL="Xmas_UI.KF2_Christmas_ChristmasCrackdown_SmallLogo" + + UsesProgressList[0] = true + UsesProgressList[1] = true + UsesProgressList[2] = false + UsesProgressList[3] = false + UsesProgressList[4] = false +} \ No newline at end of file diff --git a/KFGame/Classes/KFGFxControlsContainer_Input.uc b/KFGame/Classes/KFGFxControlsContainer_Input.uc index f41e778..45275ee 100644 --- a/KFGame/Classes/KFGFxControlsContainer_Input.uc +++ b/KFGame/Classes/KFGFxControlsContainer_Input.uc @@ -21,6 +21,12 @@ var localized string MouseString; var localized string MouseSmoothingString; var localized string ZoomSensitivityString; var localized string ControllerZoomSensitivityString; +var localized string ControllerDeadzoneString; +var localized string ControllerDeadzoneDescriptionString; +var localized string ControllerDeadzoneDescriptionXboxString; +var localized string ControllerAccelerationJumpString; +var localized string ControllerAccelerationJumpDescriptionString; +var localized string ControllerAccelerationJumpDescriptionXboxString; var localized string AimAssistLockOnString; var localized string AimAssistRotationString; var localized string AimAssistSlowDownString; @@ -32,7 +38,6 @@ var KFGFxOptionsMenu_Controls ControlsMenu; function Initialize( KFGFxObject_Menu NewParentMenu ) { super.Initialize( NewParentMenu ); - ControlsMenu = KFGFxOptionsMenu_Controls(NewParentMenu); LocalizeText(); InitializeOptions(); @@ -43,20 +48,36 @@ function LocalizeText() local GFxObject LocalizedObject; LocalizedObject = CreateObject( "Object" ); - LocalizedObject.SetString("sensitivityLabel" , SensitivityString); - LocalizedObject.SetString("invertedLabel" , InvertedString); - LocalizedObject.SetString("Mouse" , MouseString); - LocalizedObject.SetString("controllerSensitivityLabel" , SensitivityString); - LocalizedObject.SetString("controllerInvertedLabel" , InvertedString); - LocalizedObject.SetString("controllerString" , ControllerString); + LocalizedObject.SetString("sensitivityLabel" , SensitivityString); + LocalizedObject.SetString("invertedLabel" , InvertedString); + LocalizedObject.SetString("Mouse" , MouseString); + LocalizedObject.SetString("controllerSensitivityLabel" , SensitivityString); + LocalizedObject.SetString("controllerInvertedLabel" , InvertedString); + LocalizedObject.SetString("controllerString" , ControllerString); + + LocalizedObject.SetString("mouseSmoothingLabel" , MouseSmoothingString); + LocalizedObject.SetString("zoomSensitivityLabel" , ZoomSensitivityString); + LocalizedObject.SetString("controllerZoomSensitivityLabel" , ControllerZoomSensitivityString); + LocalizedObject.SetString("controllerDeadzoneLabel" , ControllerDeadzoneString); + LocalizedObject.SetString("controllerAccelerationJumpLabel" , ControllerAccelerationJumpString); + + // Localization alternative for Xbox + if( class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Durango) ) + { + LocalizedObject.SetString("controllerDeadzoneDescriptionLabel" , ControllerDeadzoneDescriptionXboxString); + LocalizedObject.SetString("controllerAccelerationJumpDescriptionLabel" , ControllerAccelerationJumpDescriptionXboxString); + } + else + { + LocalizedObject.SetString("controllerDeadzoneDescriptionLabel" , ControllerDeadzoneDescriptionString); + LocalizedObject.SetString("controllerAccelerationJumpDescriptionLabel" , ControllerAccelerationJumpDescriptionString); + } + + LocalizedObject.SetString("aimAssistLockOnLabel" , aimAssistLockOnString); + LocalizedObject.SetString("aimAssistRotationLabel" , aimAssistRotationString); + LocalizedObject.SetString("aimAssistSlowDownLabel" , aimAssistSlowDownString); + LocalizedObject.SetString("forceFeedbackLabel" , forceFeedbackString); - LocalizedObject.SetString("mouseSmoothingLabel" , MouseSmoothingString); - LocalizedObject.SetString("zoomSensitivityLabel" , ZoomSensitivityString); - LocalizedObject.SetString("controllerZoomSensitivityLabel" , ControllerZoomSensitivityString); - LocalizedObject.SetString("aimAssistLockOnLabel" , aimAssistLockOnString); - LocalizedObject.SetString("aimAssistRotationLabel" , aimAssistRotationString); - LocalizedObject.SetString("aimAssistSlowDownLabel" , aimAssistSlowDownString); - LocalizedObject.SetString("forceFeedbackLabel" , forceFeedbackString); LocalizedObject.SetString("resetDefault", Localize("KFGFxOptionsMenu_Graphics","DefaultString","KFGame")); SetObject("localizedText", LocalizedObject); @@ -95,6 +116,14 @@ function InitializeOptions() ValuesObject.SetFloat("controllerZoomSensitivityValueMin" , 100 * ControlsMenu.MinControllerZoomLookSensitivity); ValuesObject.SetFloat("controllerZoomSensitivityValueMax" , 100 * ControlsMenu.MaxControllerZoomLookSensitivity); + ValuesObject.SetFloat("controllerDeadzoneValue" , 100 * KFPI.GamepadDeadzoneScale); + ValuesObject.SetFloat("controllerDeadzoneValueMin" , 100 * ControlsMenu.MinControllerDeadzone); + ValuesObject.SetFloat("controllerDeadzoneValueMax" , 100 * ControlsMenu.MaxControllerDeadzone); + + ValuesObject.SetFloat("controllerAccelerationJumpValue" , 100 * KFPI.GamepadAccelerationJumpScale); + ValuesObject.SetFloat("controllerAccelerationJumpValueMin" , 100 * ControlsMenu.MinControllerAccelerationJump); + ValuesObject.SetFloat("controllerAccelerationJumpValueMax" , 100 * ControlsMenu.MaxControllerAccelerationJump); + ValuesObject.SetBool("controllerInvertedValue" , KFPI.bInvertController); ValuesObject.SetBool("aimAssistLockOnValue" , KFPI.bAutoTargetEnabled); ValuesObject.SetBool("aimAssistRotationValue" , KFPI.bTargetAdhesionEnabled); @@ -137,6 +166,12 @@ function ResetInputOptions() KFPI.GamepadZoomedSensitivityScale = ControlsMenu.Manager.CachedProfile.GetDefaultFloat(KFID_GamepadZoomedSensitivityScale); ControlsMenu.Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadZoomedSensitivityScale, KFPI.GamepadZoomedSensitivityScale); + + KFPI.GamepadDeadzoneScale = ControlsMenu.Manager.CachedProfile.GetDefaultFloat(KFID_GamepadDeadzoneScale); + ControlsMenu.Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadDeadzoneScale, KFPI.GamepadDeadzoneScale); + + KFPI.GamepadAccelerationJumpScale = ControlsMenu.Manager.CachedProfile.GetDefaultFloat(KFID_GamepadAccelerationJumpScale); + ControlsMenu.Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadAccelerationJumpScale, KFPI.GamepadAccelerationJumpScale); KFPI.bInvertController = ControlsMenu.Manager.CachedProfile.GetDefaultBool(KFID_InvertController); ControlsMenu.Manager.CachedProfile.SetProfileSettingValueBool(KFID_InvertController, KFPI.bInvertController); diff --git a/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc b/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc index 69418ec..bc68211 100644 --- a/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc +++ b/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc @@ -32,12 +32,17 @@ var int LastWeight; var byte LastSecondaryAmmo; var bool bWasUsingAltFireMode; var bool bUsesSecondaryAmmo; +var bool bUsesGrenadesAsSecondaryAmmo; var class LastPerkClass; var KFWeapon LastWeapon; var KFInventoryManager MyKFInvManager; +var ASColorTransform DefaultColor; +var ASColorTransform RedColor; +var name OldState; + function InitializeHUD() { MyKFPC = KFPlayerController(GetPC()); @@ -46,6 +51,9 @@ function InitializeHUD() { MyKFInvManager = KFInventoryManager(MyKFPC.Pawn.InvManager); } + + DefaultColor = GetObject("secondaryAmmoContainer").GetColorTransform(); + RedColor = GetObject("FlashlightContainer").GetColorTransform(); } function TickHud(float DeltaTime) @@ -132,6 +140,9 @@ function UpdateWeapon() local byte CurrentSecondaryAmmo; local string CurrentSpecialAmmo; local KFWeapon CurrentWeapon; + local ASColorTransform ColorChange; + local name StateName; + local bool ForceSecondaryWeaponIconUpdate; if(MyKFPC != none && MyKFPC.Pawn != none && MyKFPC.Pawn.Weapon != none ) { @@ -143,6 +154,7 @@ function UpdateWeapon() { LastWeapon = CurrentWeapon; RefreshWeapon(CurrentWeapon); + ForceSecondaryWeaponIconUpdate = true; } else if( bWasUsingAltFireMode != CurrentWeapon.bUseAltFireMode ) { @@ -180,14 +192,40 @@ function UpdateWeapon() // always reset the last special ammo since setting a new string turns the default "---" off LastSpecialAmmo = CurrentSpecialAmmo; - + StateName = CurrentWeapon.GetStateName(); if (bUsesSecondaryAmmo) { CurrentSecondaryAmmo = CurrentWeapon.GetSecondaryAmmoForHUD(); - if (CurrentSecondaryAmmo != LastSecondaryAmmo) + + // Update the amount of ammo + if (CurrentSecondaryAmmo != LastSecondaryAmmo) { SetInt("secondaryAmmo" , CurrentSecondaryAmmo); LastSecondaryAmmo = CurrentSecondaryAmmo; + } + + // Force the color of the background if we detect a weapon change and the weapon doesn't use secondary ammo + if( !bUsesGrenadesAsSecondaryAmmo && ForceSecondaryWeaponIconUpdate ) + { + GetObject("secondaryAmmoContainer").SetColorTransform(DefaultColor); + } + + // Update the aspect of the icon + if ( bUsesGrenadesAsSecondaryAmmo && StateName != OldState) + { + OldState = StateName; + if(CurrentWeapon.HasToReloadSecondaryAmmoForHUD()) + { + ColorChange.Add = MakeLinearColor(0.65f,0.23f,0.00f,0.2f); + GetObject("secondaryAmmoContainer").SetColorTransform(ColorChange); + SetString("secondaryIcon", "img://"$CurrentWeapon.SecondaryAmmoTexture.GetPackageName()$".UI_FireModeSelect_BulletSingleProhibited"); + + } + else + { + SetString("secondaryIcon", "img://"$CurrentWeapon.SecondaryAmmoTexture.GetPackageName()$"."$CurrentWeapon.SecondaryAmmoTexture); + GetObject("secondaryAmmoContainer").SetColorTransform(DefaultColor); + } } } } @@ -213,6 +251,7 @@ function RefreshWeapon(KFWeapon CurrentWeapon) SetBool("bUsesAmmo", bUsesAmmo); bUsesSecondaryAmmo = CurrentWeapon.UsesSecondaryAmmo(); + bUsesGrenadesAsSecondaryAmmo = CurrentWeapon.UsesGrenadesAsSecondaryAmmo(); SetBool("bUsesSecondaryAmmo", bUsesSecondaryAmmo); if( bUsesSecondaryAmmo ) { diff --git a/KFGame/Classes/KFGFxMenu_Gear.uc b/KFGame/Classes/KFGFxMenu_Gear.uc index 8515234..9117d7d 100644 --- a/KFGame/Classes/KFGFxMenu_Gear.uc +++ b/KFGame/Classes/KFGFxMenu_Gear.uc @@ -45,6 +45,9 @@ var localized string BioString; var localized string HeadString; var localized string BodyString; var localized string AttachmentsString; +var localized string Attachment0String; +var localized string Attachment1String; +var localized string Attachment2String; var localized string SkinsString; var localized string BackString; var localized string NoneString; @@ -149,6 +152,9 @@ function LocalizeText() LocalizedObject.SetString("bodiesString", BodyString); LocalizedObject.SetString("skinsString", SkinsString); LocalizedObject.SetString("attachmentsString", AttachmentsString); + LocalizedObject.SetString("attachment0String", Attachment0String); + LocalizedObject.SetString("attachment1String", Attachment1String); + LocalizedObject.SetString("attachment2String", Attachment2String); SetObject("localizeText", LocalizedObject); } @@ -498,7 +504,7 @@ function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionNa for(i = 0; i < `MAX_COSMETIC_ATTACHMENTS; i++) { - AttachmentIndex = MyKFPRI.RepCustomizationInfo.AttachmentMeshIndices[i]; + AttachmentIndex = MyKFPRI.RepCustomizationInfo.AttachmentMeshIndices[i]; if( AttachmentIndex == `CLEARED_ATTACHMENT_INDEX ) { DataObject.SetString("selectedAttachment_"$i, "----"); @@ -674,12 +680,25 @@ private function Callback_Body( int MeshIndex, int SkinIndex ) SetGearButtons(MeshIndex, SkinIndex, BodyMeshKey, BodySkinKey, BodyFunctionKey); } -private function Callback_Attachment( int MeshIndex, int SkinIndex ) +private function Callback_Attachment1( int MeshIndex, int SkinIndex ) +{ + Callback_AttachmentNumbered(MeshIndex, SkinIndex, 0); +} +private function Callback_Attachment2( int MeshIndex, int SkinIndex ) +{ + Callback_AttachmentNumbered(MeshIndex, SkinIndex, 1); +} +private function Callback_Attachment3( int MeshIndex, int SkinIndex ) +{ + Callback_AttachmentNumbered(MeshIndex, SkinIndex, 2); +} + +private function Callback_AttachmentNumbered(int MeshIndex, int SkinIndex, int SlotIndex) { local Pawn P; local KFPawn KFP; - local int SlotIndex; - + local int i; + local array RemovedAttachments; P = GetPC().Pawn; if( P != none ) { @@ -687,6 +706,29 @@ private function Callback_Attachment( int MeshIndex, int SkinIndex ) if ( KFP != none && MyKFPRI != None ) { + //CurrentCharInfo.RemoveAttachmentMeshAndSkin(SlotIndex, KFP, MyKFPRI); + CurrentCharInfo.DetachConflictingAttachments(MeshIndex, KFP, MyKFPRI, RemovedAttachments); + + SelectCustomizationOption(KFP, CO_Attachment, MeshIndex, SkinIndex, SlotIndex); + + } + } + SetAttachmentButtons(AttachmentKey, AttachmentFunctionKey); +} + +private function Callback_Attachment( int MeshIndex, int SkinIndex ) +{ + local Pawn P; + local KFPawn KFP; + local int SlotIndex; + P = GetPC().Pawn; + if( P != none ) + { + KFP = KFPawn( P ); + + if ( KFP != none && MyKFPRI != None ) + { + CurrentCharInfo.DetachConflictingAttachments(MeshIndex, KFP, MyKFPRI); SlotIndex = CurrentCharInfo.GetAttachmentSlotIndex(MeshIndex, KFP, MyKFPRI); SelectCustomizationOption(KFP, CO_Attachment, MeshIndex, SkinIndex, SlotIndex); diff --git a/KFGame/Classes/KFGFxMenu_Store.uc b/KFGame/Classes/KFGFxMenu_Store.uc index 3adada7..78780ea 100644 --- a/KFGame/Classes/KFGFxMenu_Store.uc +++ b/KFGame/Classes/KFGFxMenu_Store.uc @@ -11,6 +11,8 @@ class KFGFxMenu_Store extends KFGFxObject_Menu native(UI); +`include(KFProfileSettings.uci) + var localized string ExitKF2; /** Caches a local reference to the online subsystem */ @@ -22,8 +24,6 @@ var KFGFxStoreContainer_Cart CartContainer; var GFxObject AddCartButton; - - struct StoreItem { var int SKU; @@ -65,6 +65,9 @@ function InitializeMenu( KFGFxMoviePlayer_Manager InManager ) function OnOpen() { + local KFProfileSettings ProfileSettings; + local bool bHasTabbedToStore; + if( class'WorldInfo'.static.IsConsoleBuild( CONSOLE_Orbis ) ) { CheckForEmptyStore(); @@ -78,6 +81,17 @@ function OnOpen() { OnlineSub.AddOnInventoryReadCompleteDelegate(OnInventoryReadComplete); } + + ProfileSettings = Manager.CachedProfile; + bHasTabbedToStore = ProfileSettings != none ? ProfileSettings.GetProfileInt(KFID_HasTabbedToStore) != 0 : false; + if( Class'KFGameEngine'.static.IsSalesEventActive() && ProfileSettings != none && !bHasTabbedToStore ) + { + ProfileSettings.SetProfileSettingValueInt(KFID_HasTabbedToStore, 1); + } + else if( !Class'KFGameEngine'.static.IsSalesEventActive() && Class'KFGameEngine'.static.IsSalesEventChecked() && ProfileSettings != none ) + { + ProfileSettings.SetProfileSettingValueInt(KFID_HasTabbedToStore, 0); + } RefreshItemList(); diff --git a/KFGame/Classes/KFGFxMoviePlayer_HUD.uc b/KFGame/Classes/KFGFxMoviePlayer_HUD.uc index 0f6124f..014588f 100644 --- a/KFGame/Classes/KFGFxMoviePlayer_HUD.uc +++ b/KFGame/Classes/KFGFxMoviePlayer_HUD.uc @@ -64,6 +64,10 @@ var KFGFxWidget_NonCriticalGameMessage InviteGameMessageWidget; var KFGFxWidget_RhythmCounter RhythmCounterWidget; // Widget that displays health bar var KFGFxWidget_BossHealthBar bossHealthBar; +// Widget that displays map texts +var KFGFxWidget_MapText MapTextWidget; +// Widget that displays map texts +var KFGFxWidget_MapCounterText MapCounterTextWidget; var KFPlayerController KFPC; @@ -172,6 +176,22 @@ event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget) BossHealthBar.InitializeHUD(); } break; + case 'mapTextWidget': + if( MapTextWidget == none ) + { + MapTextWidget=KFGFxWidget_MapText(Widget); + SetWidgetPathBinding( Widget, WidgetPath ); + MapTextWidget.InitializeHUD(); + } + break; + case 'counterMapTextWidget': + if( MapCounterTextWidget == none ) + { + MapCounterTextWidget=KFGFxWidget_MapCounterText(Widget); + SetWidgetPathBinding( Widget, WidgetPath ); + MapCounterTextWidget.InitializeHUD(); + } + break; case 'KickVoteWidget': if( KickVoteWidget == none ) { @@ -351,7 +371,7 @@ function TickHud(float DeltaTime) { return; } - + if (WaveInfoWidget != none) { WaveInfoWidget.TickHUD(DeltaTime); @@ -377,6 +397,16 @@ function TickHud(float DeltaTime) BossHealthBar.TickHud( DeltaTime ); } + if(MapTextWidget != none) + { + MapTextWidget.TickHud( UpdateInterval ); + } + + if(MapCounterTextWidget != none) + { + MapCounterTextWidget.TickHud( UpdateInterval ); + } + if( SpectatorInfoWidget != none ) { SpectatorInfoWidget.TickHud( DeltaTime ); @@ -678,6 +708,22 @@ function HideBossNamePlate() } } +function DisplayMapText(string MessageText, float DisplayTime, bool bWaitForTheNextMessageToFinish) +{ + if(MapTextWidget != none) + { + MapTextWidget.DisplayMapText(MessageText, DisplayTime, bWaitForTheNextMessageToFinish); + } +} + +function DisplayMapCounterText(string MessageText, float DisplayTime) +{ + if(MapCounterTextWidget != none) + { + MapCounterTextWidget.DisplayMapText(MessageText, DisplayTime); + } +} + function DisplayPriorityMessage(string InPrimaryMessageString, string InSecondaryMessageString, int LifeTime, optional EGameMessageType MessageType) { local GFxObject PriorityMessageObject; @@ -1348,6 +1394,8 @@ DefaultProperties WidgetBindings.Add((WidgetName="InviteMessageWidget", WidgetClass=class'KFGFxWidget_NonCriticalGameMessage')) WidgetBindings.Add((WidgetName="RhythmCounter", WidgetClass=class'KFGFxWidget_RhythmCounter')) WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar')) + WidgetBindings.Add((WidgetName="mapTextWidget", WidgetClass=class'KFGFxWidget_MapText')) + WidgetBindings.Add((WidgetName="counterMapTextWidget", WidgetClass=class'KFGFxWidget_MapCounterText')) SpecialWaveIconPath(AT_Clot)="UI_Endless_TEX.ZEDs.UI_ZED_Endless_Cyst" diff --git a/KFGame/Classes/KFGFxOptionsMenu_Controls.uc b/KFGame/Classes/KFGFxOptionsMenu_Controls.uc index d1416f3..dbafca6 100644 --- a/KFGame/Classes/KFGFxOptionsMenu_Controls.uc +++ b/KFGame/Classes/KFGFxOptionsMenu_Controls.uc @@ -20,6 +20,10 @@ var const float MinControllerLookSensitivity; var const float MaxControllerLookSensitivity; var const float MinControllerZoomLookSensitivity; var const float MaxControllerZoomLookSensitivity; +var const float MinControllerDeadzone; +var const float MaxControllerDeadzone; +var const float MinControllerAccelerationJump; +var const float MaxControllerAccelerationJump; var const float MinMouseLookSensitivity; var const float MaxMouseLookSensitivity; var const float MinMouseLookZoomSensitivity; @@ -98,6 +102,7 @@ event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget) case ('inputContainer'): if ( InputContainer == none ) { + //`log(`location@" case ('inputContainer') "); InputContainer = KFGFxControlsContainer_Input( Widget ); InputContainer.Initialize( self ); } @@ -164,6 +169,26 @@ function Callback_ControllerZoomSensitivity( float NewSensitivity ) Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadZoomedSensitivityScale, KFPI.GamepadZoomedSensitivityScale); } +function Callback_ControllerDeadzone( float NewDeadzone ) +{ + local KFPlayerInput KFPI; + + KFPI = KFPlayerInput(GetPC().PlayerInput); + + KFPI.GamepadDeadzoneScale = NewDeadzone / 100; + Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadDeadzoneScale, KFPI.GamepadDeadzoneScale); +} + +function Callback_ControllerAccelerationJump( float NewAccelerationJump ) +{ + local KFPlayerInput KFPI; + + KFPI = KFPlayerInput(GetPC().PlayerInput); + + KFPI.GamepadAccelerationJumpScale = NewAccelerationJump / 100; + Manager.CachedProfile.SetProfileSettingValueFloat(KFID_GamepadAccelerationJumpScale, KFPI.GamepadAccelerationJumpScale); +} + function Callback_ControllerInvertChanged( bool bInvertController ) { local KFPlayerInput KFPI; @@ -311,6 +336,10 @@ defaultproperties MaxControllerLookSensitivity=3.5 MinControllerZoomLookSensitivity=.1 MaxControllerZoomLookSensitivity=1 + MinControllerDeadzone=.0 + MaxControllerDeadzone=.3 + MinControllerAccelerationJump=.0 + MaxControllerAccelerationJump=1 MinMouseLookSensitivity=.01 MaxMouseLookSensitivity=.7 MinMouseLookZoomSensitivity=.2 diff --git a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc index d9ce28a..781b69f 100644 --- a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc +++ b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc @@ -41,9 +41,9 @@ function Initialize( KFGFxObject_Menu NewParentMenu ) super.Initialize( NewParentMenu ); StartMenu = KFGFxMenu_StartGame( NewParentMenu ); OnlineSub = class'GameEngine'.static.GetOnlineSubsystem(); + FillWhatsNew(); LocalizeMenu(); SetWhatsNewItems(); - if( class'KFGameEngine'.static.IsSoloPlayDisabled()) { DisableSoloButton(); @@ -142,8 +142,11 @@ function SetWhatsNewItems() if (!class'WorldInfo'.static.isEosBuild() && WhatsNewItems[i].TextField == "PS4Key") continue; DataObject = CreateObject("Object"); DataObject.SetString("label", Localize("WhatsNewMessages",WhatsNewItems[i].TextField,"KFGame")); + `log("label"@WhatsNewItems[i].TextField); DataObject.SetString("imageURL",WhatsNewItems[i].ImageURL); + `log("imageURL"@WhatsNewItems[i].ImageURL); DataObject.SetString("redirectURL",WhatsNewItems[i].RedirectURL); + `log("redirectURL"@WhatsNewItems[i].RedirectURL); DataArray.SetElementObject(index++, DataObject); } } @@ -167,36 +170,54 @@ function LocalizeMenu() SetObject("localizedText", TextObject); } +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/"); + WhatsNewItems.AddItem(item); +// Featured Time Limited Item + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/5588"); + 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"); + WhatsNewItems.AddItem(item); +// Featured Cosmetic Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Winter","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/8617"); + WhatsNewItems.AddItem(item); +// Featured Weapon Bundle + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_FrostGun", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/8619"); + WhatsNewItems.AddItem(item); +// Misc Community Links + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityHub", "Jaegorhorn", "https://steamcommunity.com/app/232090"); + WhatsNewItems.AddItem(item); + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityForums", "Forums", "http://forums.tripwireinteractive.com/"); + 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"); + WhatsNewItems.AddItem(item); + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Merch", "Merch", "http://www.tripwireinteractive.com/redirect/shop/"); + WhatsNewItems.AddItem(item); + item=SetWhatsNewItem("img://UI_WhatsNew_PS4.UI_WhatsNew_KFUncovered", "Uncovered", "https://www.youtube.com/watch?v=fTdfedt9B48/"); + WhatsNewItems.AddItem(item); + +} + +function SWhatsNew SetWhatsNewItem(string image, string TextField, string URL) +{ + local SWhatsNew item; + item.ImageURL = image; + item.Textfield = TextField; + item.RedirectURL = URL; + + return item; +} + DefaultProperties { -// Latest Update - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Halloween_InfernalInsurrection_Event", Textfield="LatestUpdate", RedirectURL="http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/")) -// Featured Time Limited Item - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Halloween_PremiumTicket", Textfield="FeaturedEventItem", RedirectURL="https://store.steampowered.com/buyitem/232090/4928")) -// Featured Weapon Skin Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Fall_JaegerMKIII", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8464")) -// Featured Cosmetic Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Apocalypse", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8465")) -// Featured Cosmetic Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_WW1", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8466")) -// Featured Weapon Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Fall_Minigun", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8467")) -// Featured Weapon Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Fall_MineReconstructor", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8468")) -// Featured Weapon Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Fall_InfernalInsurrection_Bundle", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8469")) -// Featured Cosmetic Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Halloween_FullGearInfernalInsurrection", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8463")) -// Featured Outfit Bundle - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Fall_ReaperOutfit", Textfield="FeaturedItemBundle", RedirectURL="https://store.steampowered.com/buyitem/232090/8462")) -// Epic Horzine key - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew_PS4.UI_WhatsNew_PS4Key", Textfield="PS4Key", RedirectURL="https://store.steampowered.com/buyitem/232090/4303")) - -// Misc Community Links - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_CommunityHub", Textfield="Jaegorhorn", RedirectURL="https://steamcommunity.com/app/232090")) - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_CommunityForums", Textfield="Forums", RedirectURL="http://forums.tripwireinteractive.com/")) - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Survey", Textfield="Survey", RedirectURL="http://www.tripwireinteractive.com/redirect/KF2Survey/")) - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_CommunityIssue", Textfield="CommunityTracker", RedirectURL="https://trello.com/b/ZOwMRlcW/killing-floor-2-community-issue-roadmap")) - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew.UI_WhatsNew_Merch", Textfield="Merch", RedirectURL="http://www.tripwireinteractive.com/redirect/shop/")) - WhatsNewItems.Add((ImageURL="img://UI_WhatsNew_PS4.UI_WhatsNew_KFUncovered", Textfield="Uncovered", RedirectURL="https://www.youtube.com/watch?v=fTdfedt9B48/")) } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxStoreContainer_Main.uc b/KFGame/Classes/KFGFxStoreContainer_Main.uc index efb030c..bb6cc77 100644 --- a/KFGame/Classes/KFGFxStoreContainer_Main.uc +++ b/KFGame/Classes/KFGFxStoreContainer_Main.uc @@ -339,6 +339,18 @@ function GFxObject CreateStoreItem(ItemProperties StoreItem) DataObject.SetString("label", StoreItem.Name); DataObject.SetString("description", StoreItem.Description); + //`log("Price"@StoreItem.Price@"- BasePrice"@StoreItem.BasePrice@"- DiscountRate"@StoreItem.DiscountRate@"- ItemOnSale"@StoreItem.ItemOnSale); + + if( StoreItem.ItemOnSale ) + { + DataObject.SetString("itemOnSale", StoreItem.ItemOnSale ? "1" : "0"); + DataObject.SetString("itemPriceBase", StoreItem.BasePrice); + if(StoreItem.DiscountRate != "") + { + DataObject.SetString("discountRate", StoreItem.DiscountRate); + } + } + DataObject.SetString("price", class'WorldInfo'.static.IsConsoleBuild() ? "" : StoreItem.Price); DataObject.SetString("imageURL", "img://"$StoreItem.IconURL); DataObject.SetString("imageURLLarge", "img://"$StoreItem.IconURLLarge); @@ -434,25 +446,19 @@ DefaultProperties XboxFilterExceptions[0]="Wasteland Bundle" // Wasteland Outfit Bundle - FeaturedItemIDs[0]=8462 - FeaturedItemIDs[1]=8463 - FeaturedItemIDs[2]=8464 - FeaturedItemIDs[3]=8465 - FeaturedItemIDs[4]=8466 - FeaturedItemIDs[5]=8468 - FeaturedItemIDs[6]=8467 - FeaturedItemIDs[7]=8469 - FeaturedItemIDs[8]=7619 + FeaturedItemIDs[0]=7944 + FeaturedItemIDs[1]=8615 + FeaturedItemIDs[2]=8616 + FeaturedItemIDs[3]=8617 + FeaturedItemIDs[4]=8618 + FeaturedItemIDs[5]=8619 - ConsoleFeaturedItemIDs[0]=8462 - ConsoleFeaturedItemIDs[1]=8463 - ConsoleFeaturedItemIDs[2]=8464 - ConsoleFeaturedItemIDs[3]=8465 - ConsoleFeaturedItemIDs[4]=8466 - ConsoleFeaturedItemIDs[5]=8468 - ConsoleFeaturedItemIDs[6]=8467 - ConsoleFeaturedItemIDs[7]=8469 - ConsoleFeaturedItemIDs[8]=7783 + ConsoleFeaturedItemIDs[0]=7947 + ConsoleFeaturedItemIDs[1]=8615 + ConsoleFeaturedItemIDs[2]=8616 + ConsoleFeaturedItemIDs[3]=8617 + ConsoleFeaturedItemIDs[4]=8618 + ConsoleFeaturedItemIDs[5]=8619 MaxFeaturedItems=5 } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxWidget_BaseParty.uc b/KFGame/Classes/KFGFxWidget_BaseParty.uc index aa1154f..5defaaa 100644 --- a/KFGame/Classes/KFGFxWidget_BaseParty.uc +++ b/KFGame/Classes/KFGFxWidget_BaseParty.uc @@ -216,11 +216,10 @@ function CreatePlayerOptions(UniqueNetId PlayerID, int SlotIndex) if( ProfileString != "" ) { //View profile option Added at the end if we are on PC but first on console. - if (isPlayerFromSteam(PlayerID)) + if (isPlayerFromSteam(PlayerID) || class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Orbis) || class'WorldInfo'.static.IsConsoleBuild(CONSOLE_Durango)) { AddStringOptionToList(ViewProfileKey, OptionIndex, ProfileString, DataProvider); } - } OptionIndex++; diff --git a/KFGame/Classes/KFGFxWidget_MapCounterText.uc b/KFGame/Classes/KFGFxWidget_MapCounterText.uc new file mode 100644 index 0000000..3efe837 --- /dev/null +++ b/KFGame/Classes/KFGFxWidget_MapCounterText.uc @@ -0,0 +1,56 @@ +//============================================================================= +// KFGFxWidget_MapCounterText +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= + +class KFGFxWidget_MapCounterText extends GFxObject; + +var GFxObject counterMapTextField; + +var KFPlayerController KFPC; + +var transient float CurrentDisplayTime; +var transient float ControlTime; + +function InitializeHUD() +{ + KFPC = KFPlayerController(GetPC()); + counterMapTextField = GetObject("counterMapText"); + SetVisible(false); +} + +function DisplayMapText(string CountText, float DisplayTime) +{ + if(counterMapTextField != none) + { + ControlTime = DisplayTime; + CurrentDisplayTime = DisplayTime; + counterMapTextField.SetText(CountText); + SetVisible(true); + } +} + +function TickHud(float DeltaTime) +{ + if(ControlTime > 0) + { + ControlTime -= DeltaTime; + if(ControlTime <= 0) + { + HideMessage(); + } + } +} + +function HideMessage() +{ + counterMapTextField.SetText(""); + SetVisible(false); +} + +DefaultProperties +{ } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxWidget_MapText.uc b/KFGame/Classes/KFGFxWidget_MapText.uc new file mode 100644 index 0000000..0fa8646 --- /dev/null +++ b/KFGame/Classes/KFGFxWidget_MapText.uc @@ -0,0 +1,81 @@ +//============================================================================= +// KFGFxWidget_MapText +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= + +class KFGFxWidget_MapText extends GFxObject; + +var GFxObject mapTextField; + +var KFPlayerController KFPC; + +var transient float CurrentDisplayTime; +var transient float ControlTime; + +struct MapStoredMessage +{ + var string Text; + var float DisplayTime; +}; +var array StoredMessageList; + +function InitializeHUD() +{ + KFPC = KFPlayerController(GetPC()); + mapTextField = GetObject("mapText"); + SetVisible(false); +} + +function DisplayMapText(string MapText, float DisplayTime, bool bWaitForTheNextMessageToFinish) +{ + Local MapStoredMessage StoredMessage; + + if(mapTextField != none) + { + if(ControlTime > 0 && bWaitForTheNextMessageToFinish) + { + StoredMessage.Text = MapText; + StoredMessage.DisplayTime = DisplayTime; + StoredMessageList.AddItem(StoredMessage); + return; + } + ControlTime = DisplayTime; + CurrentDisplayTime = DisplayTime; + mapTextField.SetText(MapText); + SetVisible(true); + } +} + +function TickHud(float DeltaTime) +{ + if(ControlTime > 0) + { + ControlTime -= DeltaTime; + if(ControlTime <= 0) + { + HideMessage(); + } + } +} + +function HideMessage() +{ + if(StoredMessageList.Length > 0) + { + ControlTime += StoredMessageList[0].DisplayTime; + CurrentDisplayTime = StoredMessageList[0].DisplayTime; + mapTextField.SetText(StoredMessageList[0].Text); + SetVisible(true); + StoredMessageList.Remove(0, 1); + return; + } + mapTextField.SetText(""); + SetVisible(false); +} + +DefaultProperties +{ } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxWidget_MenuBar.uc b/KFGame/Classes/KFGFxWidget_MenuBar.uc index 5a67f25..52dd831 100644 --- a/KFGame/Classes/KFGFxWidget_MenuBar.uc +++ b/KFGame/Classes/KFGFxWidget_MenuBar.uc @@ -10,6 +10,8 @@ class KFGFxWidget_MenuBar extends KFGFxObject_Menu; +`include(KFProfileSettings.uci) + var localized array MenuStrings; var localized string ExitString; var localized string CancelString; @@ -93,6 +95,9 @@ function UpdateMenu(byte CurrentMenuIndex) function HandleButtonSpecialCase(byte ButtonIndex, out GFxObject GfxButton) { + local KFProfileSettings ProfileSettings; + local bool bHasTabbedToStore; + GfxButton.SetInt( "index", ButtonIndex ); // For XB1, we change the EXIT button to logout while in the menus @@ -133,6 +138,13 @@ function HandleButtonSpecialCase(byte ButtonIndex, out GFxObject GfxButton) GfxButton.SetString( "label", ConsoleLocalize("StoreStringXB1", "KFGFxMenu_Store") ); } GfxButton.SetBool("enabled", CanUseStore() ); // Disabled for E3 build + + ProfileSettings = Manager.CachedProfile; + bHasTabbedToStore = ProfileSettings != none ? ProfileSettings.GetProfileInt(KFID_HasTabbedToStore) != 0 : false; + if( CanUseStore() && Class'KFGameEngine'.static.IsSalesEventActive() && Class'KFGameEngine'.static.IsSalesEventChecked() && ProfileSettings != none && !bHasTabbedToStore) + { + GfxButton.SetBool( "bPulsing", true ); + } StoreButton = GfxButton; return; //@HSL_END diff --git a/KFGame/Classes/KFGameEngine.uc b/KFGame/Classes/KFGameEngine.uc index e3d06f7..c4af57b 100644 --- a/KFGame/Classes/KFGameEngine.uc +++ b/KFGame/Classes/KFGameEngine.uc @@ -47,6 +47,7 @@ var private const int LoadedSeasonalEventId; /** Week index of the year - Used as index into weekly event */ var private int WeeklyEventIndex; + /************************************************************************************ * @name Content ***********************************************************************************/ @@ -469,7 +470,8 @@ function ClearOnlineDelegates() /** Static because these are both called on default object */ native static function int GetSeasonalEventID(); native static function int GetWeeklyEventIndex(); - +native static function bool IsSalesEventActive(); +native static function bool IsSalesEventChecked(); /*********************************************************************************** * @name Game Options ***********************************************************************************/ diff --git a/KFGame/Classes/KFGfxMenu_StartGame.uc b/KFGame/Classes/KFGfxMenu_StartGame.uc index 1726c8a..59b563b 100644 --- a/KFGame/Classes/KFGfxMenu_StartGame.uc +++ b/KFGame/Classes/KFGfxMenu_StartGame.uc @@ -208,7 +208,7 @@ static function class GetSpecialEventClass case SEI_Fall: return class'KFGFxSpecialEventObjectivesContainer_Fall2020'; case SEI_Winter: - return class'KFGFxSpecialEventObjectivesContainer_Xmas2019'; + return class'KFGFXSpecialEventObjectivesContainer_Xmas2020'; } return class'KFGFxSpecialEventObjectivesContainer'; diff --git a/KFGame/Classes/KFGfxMoviePlayer_Manager.uc b/KFGame/Classes/KFGfxMoviePlayer_Manager.uc index 7e59d22..9530b53 100644 --- a/KFGame/Classes/KFGfxMoviePlayer_Manager.uc +++ b/KFGame/Classes/KFGfxMoviePlayer_Manager.uc @@ -245,6 +245,7 @@ var bool bMenusOpen; // true if we're using menus, otherwise we're using the HUD var bool bMenusActive; //@HSL - JRO - 6/21/2016 - Same as bMenusOpen but doesn't include the closing animation var bool bSearchingForGame; // true if we are in the process of finding a game var bool bCanCloseMenu; // Set to true after a menu has been completely opened and allows a player to close the menu +var bool bForceCloseMenuNextTime; // Allows the system to close the menu var bool bPlayerInLobby; //@HSL_MOD_BEGIN - amiller 5/11/2016 - Adding support to save extra data into profile settings - removing config var bool bSetGamma; // Set to true if we've already set the gamma on the first launch @@ -1278,6 +1279,7 @@ function CloseMenus(optional bool bForceClose=false) if ( (bMenusOpen && bCanCloseMenu) || bForceClose) { + bForceCloseMenuNextTime = false; UnloadCurrentPopup(); if ( !bAfterLobby && PartyWidget != none || GetPC() == none || GetPC().WorldInfo.GRI == none || GetPC().WorldInfo.GRI.bMatchIsOver ) @@ -1304,6 +1306,10 @@ function CloseMenus(optional bool bForceClose=false) SetMenuVisibility( false ); SetHUDVisiblity( true) ; } + else if(bForceCloseMenuNextTime) + { + `TimerHelper.SetTimer( 0.1, false, nameof(CloseMenus), self ); + } } /** Called when the movie player is closed */ @@ -1851,6 +1857,7 @@ event bool FilterButtonInput(int ControllerId, name ButtonName, EInputEvent Inpu } else if(KFPRI.bHasSpawnedIn && !KFGRI.bMatchIsOver && KFGRI.bMatchHasBegun && KFGRI.bTraderIsOpen && CurrentMenu != TraderMenu && bMenusOpen) { + bForceCloseMenuNextTime = true; CurrentMenu.Callback_ReadyClicked(true); } } diff --git a/KFGame/Classes/KFHUDBase.uc b/KFGame/Classes/KFHUDBase.uc index f87fdd2..6daa52e 100644 --- a/KFGame/Classes/KFHUDBase.uc +++ b/KFGame/Classes/KFHUDBase.uc @@ -800,11 +800,11 @@ simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH ) // drop shadow for player name text Canvas.SetDrawColorStruct(PlayerBarShadowColor); - Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + 8); + Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y - 2.5f * BarHeight + (36 * FontScale * ResModifier) + 1); //KFII-52291: -2.5 is a bit of a magic number, but it works (intuition says it should be 0 if we look at where armor bar is being drawn). Canvas.DrawText(KFPRI.PlayerName, , FontScale, FontScale, MyFontRenderInfo); Canvas.SetDrawColorStruct(PlayerBarTextColor); - Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + 7); + Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y - 2.5f * BarHeight + (36 * FontScale * ResModifier)); //KFII-52291: -2.5 is a bit of a magic number, but it works (intuition says it should be 0 if we look at where armor bar is being drawn). Canvas.DrawText(KFPRI.PlayerName, , FontScale, FontScale, MyFontRenderInfo); //Draw armor bar diff --git a/KFGame/Classes/KFKismetMapLocalization.uc b/KFGame/Classes/KFKismetMapLocalization.uc new file mode 100644 index 0000000..8685d14 --- /dev/null +++ b/KFGame/Classes/KFKismetMapLocalization.uc @@ -0,0 +1,19 @@ +//============================================================================= +// KFKismetMapLocalization +//============================================================================= +// Base class for Kismet localization +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2017 Tripwire Interactive LLC +//============================================================================= +class KFKismetMapLocalization extends Object within KFSeqAct_DrawLocalizedText + hidedropdown; + +var Font TextFont; + +static simulated function string GetLocalization(int Id); + +static simulated function Font GetFont() +{ + return default.TextFont; +} \ No newline at end of file diff --git a/KFGame/Classes/KFKismetMapLocalization_Elysium.uc b/KFGame/Classes/KFKismetMapLocalization_Elysium.uc new file mode 100644 index 0000000..38c6c0b --- /dev/null +++ b/KFGame/Classes/KFKismetMapLocalization_Elysium.uc @@ -0,0 +1,72 @@ +//============================================================================= +// KFKismetMapLocalization_Elysium +//============================================================================= +// Class for Elysium Kismet localization +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2017 Tripwire Interactive LLC +//============================================================================= + +class KFKismetMapLocalization_Elysium extends KFKismetMapLocalization; + +var localized string FuneralPyreIgnitionText; +var localized string TomeMissingText; +var localized string LeverWarningText; +var localized string LoreMastersKnowsText; +var localized string SandTomeCollectedText; +var localized string SteelTomeCollectedText; +var localized string SludgeTomeCollectedText; +var localized string WoodTomeCollectedText; +var localized string RedRoseCollectedText; +var localized string MagentaRoseollectedText; +var localized string YellowRoseCollectedText; +var localized string FlowerActivationText; +var localized string BotanicaOpenText; +var localized string OneOfThreeCollectedText; +var localized string TwoOfThreeCollectedText; +var localized string ThreeOfThreeCollectedText; +var localized string OneOfFourCollectedText; +var localized string TwoOfFourCollectedText; +var localized string ThreeOfFourCollectedText; +var localized string FourOfFourCollectedText; + +static simulated function string GetLocalization(int MessageId) +{ + switch(MessageId) + { + case 0: return default.FuneralPyreIgnitionText; + + case 1: return default.TomeMissingText; + + case 2: return default.LeverWarningText; + case 3: return default.LoreMastersKnowsText; + + case 4: return default.SandTomeCollectedText; + case 5: return default.SteelTomeCollectedText; + case 6: return default.SludgeTomeCollectedText; + case 7: return default.WoodTomeCollectedText; + + case 8: return default.RedRoseCollectedText; + case 9: return default.MagentaRoseollectedText; + case 10: return default.YellowRoseCollectedText; + + case 11: return default.FlowerActivationText; + + case 12: return default.BotanicaOpenText; + + case 13: return default.OneOfThreeCollectedText; + case 14: return default.TwoOfThreeCollectedText; + case 15: return default.ThreeOfThreeCollectedText; + + case 16: return default.OneOfFourCollectedText; + case 17: return default.TwoOfFourCollectedText; + case 18: return default.ThreeOfFourCollectedText; + case 19: return default.FourOfFourCollectedText; + } + return ""; +} + +defaultproperties +{ + TextFont=Font'UI_Canvas_Fonts.Font_General' +} \ No newline at end of file diff --git a/KFGame/Classes/KFMeleeHelperWeapon.uc b/KFGame/Classes/KFMeleeHelperWeapon.uc index d042559..7b68d30 100644 --- a/KFGame/Classes/KFMeleeHelperWeapon.uc +++ b/KFGame/Classes/KFMeleeHelperWeapon.uc @@ -88,6 +88,16 @@ var float MeleeImpactCamShakeScale; * Anim Notify / Impact Timing *********************************************************************************************/ +simulated function EPawnOctant GetNextAttackDir() +{ + return NextAttackDir; +} + +simulated function SetNextAttackDir(EPawnOctant _nextAttackDir) +{ + NextAttackDir = _nextAttackDir; +} + /** Notification called from KFAnimNotify_MeleeImpact. */ simulated function MeleeImpactNotify(KFAnimNotify_MeleeImpact_1P Notify) { @@ -727,16 +737,21 @@ simulated function ProcessMeleeHit(byte FiringMode, ImpactInfo Impact) // play effects before doing damage, because doing damage can change the actor (e.g. destructibles) and result in incorrect sounds PlayMeleeHitEffects(Impact.HitActor, Impact.HitLocation, Impact.RayDir); - - Impact.HitActor.TakeDamage( GetMeleeDamage(FiringMode, Impact.RayDir), Instigator.Controller, - Impact.HitLocation, Momentum, - GetDamageType(FiringMode), Impact.HitInfo, Outer ); + + PawnTakeDamage(Impact, FiringMode, Momentum); // notify weapon for custom code NotifyMeleeCollision(Impact.HitActor, Impact.HitLocation); } } +simulated function PawnTakeDamage(ImpactInfo Impact,byte FiringMode, vector Momentum) +{ + Impact.HitActor.TakeDamage( GetMeleeDamage(FiringMode, Impact.RayDir), Instigator.Controller, + Impact.HitLocation, Momentum, + GetDamageType(FiringMode), Impact.HitInfo, Outer ); +} + /** returns the damage type to use for this attack */ simulated function class GetDamageType(byte FiringMode) { diff --git a/KFGame/Classes/KFMeleeHelperWeaponFrostShotgunAxe.uc b/KFGame/Classes/KFMeleeHelperWeaponFrostShotgunAxe.uc new file mode 100644 index 0000000..e16ff6e --- /dev/null +++ b/KFGame/Classes/KFMeleeHelperWeaponFrostShotgunAxe.uc @@ -0,0 +1,165 @@ +//============================================================================= +// KFMeleeHelperWeapon +//============================================================================= +// Manages melee attack related functionality for 1st person weapons +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= +class KFMeleeHelperWeaponFrostShotgunAxe extends KFMeleeHelperWeapon + config(Game); + +var bool bIcedEnemy; +var ParticleSystem ChargedEffect; +var ParticleSystemComponent FullyChargedPSC; +var AkEvent oFrozenSound; +var AkEvent oHitSoundAkEvent; + +simulated function PawnTakeDamage(ImpactInfo Impact,byte FiringMode, vector Momentum) +{ + local int InstantDamage; + + bIcedEnemy = false; + if(Impact.HitActor.IsA('KFPawn_Monster')) + { + if(KFPawn_Monster(Impact.HitActor).IsDoingSpecialMove(SM_Frozen)) + { + bIcedEnemy = true; + } + } + InstantDamage = GetMeleeDamage(FiringMode, Impact.RayDir); + Impact.HitActor.TakeDamage(InstantDamage, Instigator.Controller, + Impact.HitLocation, Momentum, + GetDamageType(FiringMode), Impact.HitInfo, Outer ); + +} + +simulated function bool IsEnemyIced(){ + return bIcedEnemy; +} + + +/** Called from state MeleeAtacking */ +simulated function BeginMeleeAttack(optional bool bIsChainAttack) +{ + local Pawn P; + local KFPawn_Monster KFPM; + local vector Projection; + local float MeleeDuration; + + // Don't let a weak zed grab us when we just melee attacked + // Ramm - commented out, too exploitable + // SetWeakZedGrabCooldownOnPawn(0.5); + + // initialize attack settings + bHasAlreadyHit = false; + bHitEnemyThisAttack = false; + + // Let the playercontroller know we did an attack + if ( Instigator != None && Instigator.Controller != none && + KFPlayerController(Instigator.Controller) != none ) + { + KFPlayerController(Instigator.Controller).AddShotsFired(1); + } + + // Clear reset flag (see InitAttackSequence, ContinueMeleeAttack) + bResetChainSequence = false; + + // save the direction of this attack + CurrentAttackDir = ( CurrentFireMode == CUSTOM_FIREMODE ) ? DIR_None : GetNextAttackDir(); + + // Notify enemy pawns of melee strike + if( WorldInfo.NetMode != NM_Client ) + { + foreach WorldInfo.AllPawns( class'Pawn', P ) + { + if( P.GetTeamNum() != Instigator.GetTeamNum() && P.IsAliveAndWell() && !P.IsHumanControlled() ) + { + Projection = Instigator.Location - P.Location; + if( VSizeSQ(Projection) <= Square(MaxHitRange + P.CylinderComponent.CollisionRadius) ) + { + KFPM = KFPawn_Monster( P ); + if( KFPM != none && KFPM.MyKFAIC != none ) + { + KFPM.MyKFAIC.ReceiveMeleeWarning( CurrentAttackDir, Projection, Instigator ); + } + } + } + } + } + + // Select and play attack animation + MeleeDuration = PlayMeleeAttackAnimation(); + + if ( MeleeDuration > 0.f ) + { + // @hack: Add current DeltaSeconds to timer. This fixes an off-by-one frame issue that can + // that can cause the timer to interrupt animation at low framerate. This is particularly + // bad for melee when using impact anim notifies. + SetTimer(MeleeDuration + WorldInfo.DeltaSeconds, FALSE, nameof(MeleeCheckTimer), self); + + // set the timer to check for hits + if( bUseMeleeHitTimer && InitialImpactDelay > 0.f ) + { + // Clear complete time so it is intialized properly + ImpactComplete_ActorTime = -1.f; + SetTimer(InitialImpactDelay, FALSE, nameof(MeleeImpactTimer), self); + } + } + else + { + `warn("MeleeDuration is zero!!!"); + SetTimer(0.001, false, nameof(HandleFinishedFiring)); + } +} + +/** + * Called by ProcessMeleeHit to spawn effects + * Network: Local Player and Server + */ +simulated function PlayMeleeHitEffects(Actor Target, vector HitLocation, vector HitDirection, optional bool bShakeInstigatorCamera=true) +{ + // @note: Skipping super(). No victim camera shake is intentional + if( WorldInfo.NetMode != NM_DedicatedServer ) + { + // first person (local) fire effects + if ( Instigator.IsFirstPerson() ) + { + PlayerController(Instigator.Controller).ClientPlayCameraShake(MeleeImpactCamShake, MeleeImpactCamShakeScale, true, CAPS_UserDefined, rotator(-HitDirection)); + + if ( Target.IsA('Pawn') ) + { + AddBlood(0.01f, 0.1f); + if(KFPawn_Monster(Target).IsDoingSpecialMove(SM_Frozen)) + { + + if( IsZero(HitDirection) && Instigator != none ) + { + HitDirection = Normal(Instigator.Location - HitLocation); + } + + WorldInfo.MyEmitterPool.SpawnEmitter(ChargedEffect, HitLocation, rotator(HitDirection), Target); + Instigator.PlayAkEvent(oFrozenSound); + Instigator.PlayAkEvent(oHitSoundAkEvent); + } + } + } + + // If we hit a pawn we can skip the Tracing code in PlayImpactEffects. Pawn FX are handled in + // PlayHit and this prevents incorrect (world) FX from playing if the trace is bad. + if ( !(Target.bCanBeDamaged && Target.IsA('Pawn')) ) + { + // Use ImpactEffectManager to material based world impacts + `ImpactEffectManager.PlayImpactEffects(HitLocation, Instigator, HitDirection, WorldImpactEffects); + } + } +} + + +defaultproperties +{ + oFrozenSound=AkEvent'WW_WEP_SA_CompoundBow.Play_Arrow_Impact_Cryo' + oHitSoundAkEvent=AkEvent'WW_WEP_FrostFang.Play_FrostFang_Base_Impact' + ChargedEffect=ParticleSystem'WEP_Frost_Shotgun_Axe_EMIT.FX_FrostFang_Melee_ImpactFrozen_01'; + HitboxBoneName=RW_Weapon +} diff --git a/KFGame/Classes/KFOnlineStatsReadDingo.uc b/KFGame/Classes/KFOnlineStatsReadDingo.uc index ff75cf4..247a992 100644 --- a/KFGame/Classes/KFOnlineStatsReadDingo.uc +++ b/KFGame/Classes/KFOnlineStatsReadDingo.uc @@ -65,6 +65,7 @@ defaultproperties ColumnIds.Add(STATID_ACHIEVE_BiolapseCollectibles) ColumnIds.Add(STATID_ACHIEVE_DesolationCollectibles) ColumnIds.Add(STATID_ACHIEVE_HellmarkStationCollectibles) + ColumnIds.Add(STATID_ACHIEVE_ElysiumEndlessWaveFifteen) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky5, Name="AchievementMrPerky5")) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky10, Name = "AchievementMrPerky10")) @@ -118,4 +119,5 @@ defaultproperties ColumnMappings.Add((Id=STATID_ACHIEVE_BiolapseCollectibles,Name="AchievementCollectBiolapse")) ColumnMappings.Add((Id=STATID_ACHIEVE_DesolationCollectibles,Name="AchievementCollectDesolation")) ColumnMappings.Add((Id=STATID_ACHIEVE_HellmarkStationCollectibles,Name="AchievementCollectHellmarkStation")) + ColumnMappings.Add((Id=STATID_ACHIEVE_ElysiumEndlessWaveFifteen,Name="AchievementEndlessElysium")) } diff --git a/KFGame/Classes/KFOnlineStatsWrite.uc b/KFGame/Classes/KFOnlineStatsWrite.uc index aec276d..1e43191 100644 --- a/KFGame/Classes/KFOnlineStatsWrite.uc +++ b/KFGame/Classes/KFOnlineStatsWrite.uc @@ -421,6 +421,10 @@ const KFACHID_HellmarkStationHard = 274; const KFACHID_HellmarkStationHellOnEarth = 275; const KFACHID_HellmarkStationCollectibles = 276; +const KFACHID_ElysiumHard = 277; +const KFACHID_ElysiumHellOnEarth = 278; +const KFACHID_ElysiumEndlessWaveFifteen = 279; + /* __TW_ANALYTICS_ */ var int PerRoundWeldXP; var int PerRoundHealXP; @@ -1698,14 +1702,17 @@ final function bool CanCacheSpecialEvent() /** Verify what event we're in and cache local event state. If we've changed to a new event, * clear out the status flags before caching new date value. */ -native final private function CacheSpecialEventState(int Value); +native final private function CacheSpecialEventState(int Value, int Year, int Month); native final function int GetSpecialEventRewardValue(); /** Triggered by KF PC when the special event ID is passed through as a valid value */ final function UpdateSpecialEventState() { - CacheSpecialEventState(InitialSpecialEventInfo); + local int year, month, dayofweek, day, hour, minute, second, msec; + GetSystemTime(year, month, dayofweek, day, hour, minute, second, msec); + + CacheSpecialEventState(InitialSpecialEventInfo, year, month); if( InitialSpecialEventInfo != SpecialEventInfo ) { // Flush stats write if we did a reset @@ -1717,7 +1724,7 @@ final function UpdateSpecialEventState() * special event index, do not update the stat. Also, if the map name passed doesn't match * the list of allowed maps in native, don't record. */ -native final function UpdateSpecialEvent(int EventIndex, int ObjectiveIndex); +native final function UpdateSpecialEvent(int EventIndex, int ObjectiveIndex, int Year, int Month); /** Grab the state of a special event objective at a specific index. */ native final function bool IsEventObjectiveComplete(int ObjectiveIndex); @@ -1993,7 +2000,7 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Revolver_Buckshot, KFDT_Ballistic_HRGBuckshot, KFDT_Bludgeon_HRGBuckshot),CompletionAmount=10000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_HZ12, KFDT_Ballistic_HZ12,KFDT_Bludgeon_HZ12),CompletionAmount=10000)) //7000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_M4, KFDT_Ballistic_M4Shotgun,KFDT_Bludgeon_M4Shotgun),CompletionAmount=10000)) //7000 - DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_AA12, KFDT_Ballistic_AA12Shotgun,KFDT_Bludgeon_AA12Shotgun),CompletionAmount=10000)) + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_AA12, KFDT_Ballistic_AA12Shotgun,KFDT_Bludgeon_AA12Shotgun),CompletionAmount=10000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Shotgun_ElephantGun, KFDT_Ballistic_ElephantGun,KFDT_Bludgeon_ElephantGun),CompletionAmount=10000)) //Medic Weapons @@ -2004,7 +2011,8 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_Hemogoblin, KFDT_Ballistic_Hemogoblin, KFDT_Bludgeon_Hemogoblin),CompletionAmount=9000)) //7000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_Medic, KFDT_Ballistic_Assault_Medic,KFDT_Bludgeon_Assault_Medic),CompletionAmount=9000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_Rifle_HRGIncision, KFDT_Ballistic_HRGIncisionHurt, KFDT_Ballistic_HRGIncisionHeal,KFDT_Bludgeon_HRGIncision),CompletionAmount=5000)) - DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_MedicRifleGrenadeLauncher, KFDT_Ballistic_MedicRifleGrenadeLauncher, KFDT_Bludgeon_MedicRifleGrenadeLauncher, KFDT_Toxic_MedicGrenadeLauncher, KFDT_Ballistic_MedicRifleGrenadeLauncherImpact),CompletionAmount=10000)) + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Vampire, KFDT_Bleeding_HRG_Vampire_BloodSuck, KFDT_Ballistic_HRG_Vampire_BloodBallImpact, KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact, KFDT_Toxic_HRG_Vampire_BloodBall, KFDT_Piercing_HRG_Vampire_CrystalSpike, KFDT_Bludgeon_HRG_Vampire),CompletionAmount=9000)) + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_MedicRifleGrenadeLauncher, KFDT_Ballistic_MedicRifleGrenadeLauncher, KFDT_Bludgeon_MedicRifleGrenadeLauncher, KFDT_Toxic_MedicGrenadeLauncher, KFDT_Ballistic_MedicRifleGrenadeLauncherImpact),CompletionAmount=10000)) //Demo Weapons DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_GrenadeLauncher_HX25, KFDT_ExplosiveSubmunition_HX25,KFDT_Ballistic_HX25Impact,KFDT_Ballistic_HX25SubmunitionImpact,KFDT_Bludgeon_HX25),CompletionAmount=5000)) //3000 @@ -2192,6 +2200,9 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-HELLMARKSTATION),CompletionAmount=1)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-HELLMARKSTATION),CompletionAmount=2)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-HELLMARKSTATION),CompletionAmount=3)) + 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)) //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 0ee5056..da2854a 100644 --- a/KFGame/Classes/KFOnlineStatsWriteDingo.uc +++ b/KFGame/Classes/KFOnlineStatsWriteDingo.uc @@ -67,4 +67,5 @@ defaultproperties Properties.Add((PropertyId = STATID_ACHIEVE_BiolapseCollectibles,Data = (Type = SDT_Int32,Value1 = 0))) 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))) } diff --git a/KFGame/Classes/KFPawn.uc b/KFGame/Classes/KFPawn.uc index 69ebbd1..36c6feb 100644 --- a/KFGame/Classes/KFPawn.uc +++ b/KFGame/Classes/KFPawn.uc @@ -4401,9 +4401,9 @@ simulated function SetPawnAmbientSound(AkEvent NewAmbientSound) } } -simulated function bool IsWeaponAmbientSoundPlaying(AkEvent AmbientSound) +simulated function bool IsWeaponAmbientSoundPlaying(AkEvent AmbientSoundToCheck) { - return WeaponAkComponent.IsPlaying(AmbientSound); + return WeaponAkComponent.IsPlaying(AmbientSoundToCheck); } /** starts playing the given sound via the WeaponAmbientSound AudioComponent and sets WeaponAmbientSoundCue for replicating to clients diff --git a/KFGame/Classes/KFPerk_Berserker.uc b/KFGame/Classes/KFPerk_Berserker.uc index 91a1bb4..618dcc5 100644 --- a/KFGame/Classes/KFPerk_Berserker.uc +++ b/KFGame/Classes/KFPerk_Berserker.uc @@ -255,7 +255,8 @@ simulated function ModifySpeed( out float Speed ) } } - if( MyKFWeapon != none && MyKFWeapon.IsMeleeWeapon() ) + if (MyKFWeapon != none && + (MyKFWeapon.IsMeleeWeapon() || IsWeaponOnPerk(MyKFWeapon,, self.class))) { Speed += Speed * GetSkillValue( PerkSkills[EBerserkerNinja] ); } diff --git a/KFGame/Classes/KFPerk_Gunslinger.uc b/KFGame/Classes/KFPerk_Gunslinger.uc index 2460c4e..672d239 100644 --- a/KFGame/Classes/KFPerk_Gunslinger.uc +++ b/KFGame/Classes/KFPerk_Gunslinger.uc @@ -58,6 +58,7 @@ var private int HeadShotComboCountDisplay; /** The maximum number of headshots that count toward the Rhythm Method perk skill damage multiplier */ var private const int MaxHeadShotComboCount; var private const float HeadShotCountdownIntervall; +var private const float SteadySkillDamageModifier; /********************************************************************************************* * @name Perk init and spawning @@ -133,10 +134,13 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau local float TempDamage; TempDamage = InDamage; - if( DamageCauser != none ) { KFW = GetWeaponFromDamageCauser( DamageCauser ); + if(KFW == none && DamageCauser.IsA('KFPawn_Human')) + { + KFW = KFWeapon(KFPawn_Human(DamageCauser).Weapon); + } } if( (KFW != none && IsWeaponOnPerk( KFW,, self.class )) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) ) @@ -160,6 +164,11 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau `QALog( "Bone Breaker arms and leg damage =" @ Indamage * static.GetBoneBreakerDamage(), bLogPerk ); TempDamage += Indamage * static.GetBoneBreakerDamage(); } + + if( IsShootnMoveActive() && KFW.bUsingSights ) + { + TempDamage += Indamage * SteadySkillDamageModifier; + } } `QALog( "Total Damage Given" @ DamageType @ KFW @ GetPercentage( InDamage, Round( TempDamage ) ), bLogPerk ); @@ -801,6 +810,7 @@ DefaultProperties PerkBuildStatID=STATID_Guns_Build ShootnMooveBobDamp=1.11f + SteadySkillDamageModifier=0.075f MaxHeadShotComboCount=5 RhytmMethodRTPCName="R_Method" diff --git a/KFGame/Classes/KFPerk_Support.uc b/KFGame/Classes/KFPerk_Support.uc index af9e6ac..6c2da9d 100644 --- a/KFGame/Classes/KFPerk_Support.uc +++ b/KFGame/Classes/KFPerk_Support.uc @@ -359,7 +359,10 @@ function ModifyHealth( out int InHealth ) simulated function float GetTightChokeModifier() { - if( IsTightChokeActive() ) + local KFWeapon MyKFWeapon; + + MyKFWeapon = GetOwnerWeapon(); + if( IsTightChokeActive() && IsWeaponOnPerk(MyKFWeapon,, self.class) ) { return GetSkillValue( PerkSkills[ESupportTightChoke] ); } diff --git a/KFGame/Classes/KFPerk_Survivalist.uc b/KFGame/Classes/KFPerk_Survivalist.uc index 49d89eb..b3efbd6 100644 --- a/KFGame/Classes/KFPerk_Survivalist.uc +++ b/KFGame/Classes/KFPerk_Survivalist.uc @@ -41,6 +41,7 @@ var private const GameExplosion ShrapnelExplosionTemplate; var private const float ShrapnelChance; var private const float SnarePower; var private const float MeleeExpertMovementSpeedModifier; +var private const float PassiveWeaponSwitchModifier; var class HealingGrenadeWeaponDef; var class MolotovGrenadeWeaponDef; @@ -301,6 +302,22 @@ function ModifyArmor( out byte MaxArmor ) } } +/** + * @brief The passive skill of the survivalist modifies the weapon switch speed + * + * @param ModifiedSwitchTime Duration of putting down or equipping the weapon + */ +simulated function ModifyWeaponSwitchTime( out float ModifiedSwitchTime ) +{ + `QALog( "(Passive Weapon Switch) Increase:" @ GetPercentage( ModifiedSwitchTime, ModifiedSwitchTime * (1.f - static.GetPassiveWeaponSwitchModifier()) ), bLogPerk ); + ModifiedSwitchTime *= 1.f - static.GetPassiveWeaponSwitchModifier(); +} + +simulated final static function float GetPassiveWeaponSwitchModifier() +{ + return default.PassiveWeaponSwitchModifier; +} + /********************************************************************************************* * @name Selectable skills functions ********************************************************************************************* */ @@ -445,7 +462,7 @@ simulated function float GetAoERadiusModifier() simulated function float GetZedTimeModifier( KFWeapon W ) { local name StateName; - if( GetMadManActive() && !W.IsMeleeWeapon() ) + if( GetMadManActive() && !W.IsMeleeWeapon() || KFWeap_MeleeBase(W).default.bHasToBeConsideredAsRangedWeaponForPerks ) { StateName = W.GetStateName(); `Warn(StateName); @@ -712,11 +729,13 @@ simulated static function GetPassiveStrings( out array PassiveValues, ou PassiveValues[1] = Round( GetPassiveValue( default.DamageResistance, Level ) * 100 ) $ "%"; PassiveValues[2] = Round( GetPassiveValue( default.HeavyBodyArmor, Level ) * 100 ) $ "%"; PassiveValues[3] = Round( GetPassiveValue( default.ZedTimeReload, Level ) * 100 ) $ "%"; + PassiveValues[4] = ""; Increments[0] = "[" @ Left( string( default.WeaponDamage.Increment * 100 ), InStr(string(default.WeaponDamage.Increment * 100), ".") + 2 ) $ "% /" @ default.LevelString @ "]"; Increments[1] = "[" @ Left( string( default.DamageResistance.Increment * 100 ), InStr(string(default.DamageResistance.Increment * 100), ".") + 2 ) $ "% /" @ default.LevelString @ "]"; Increments[2] = "[" @ Left( string( default.HeavyBodyArmor.Increment * 100 ), InStr(string(default.HeavyBodyArmor.Increment * 100), ".") + 2 ) $ "% /" @ default.LevelString @ "]"; Increments[3] = "[" @ Left( string( default.ZedTimeReload.Increment * 100 ), InStr(string(default.ZedTimeReload.Increment * 100), ".") + 2 ) $ "% /" @ default.LevelString @ "]"; + Increments[4] = ""; } simulated function string GetGrenadeImagePath() @@ -767,6 +786,8 @@ DefaultProperties HeavyBodyArmor=(Name="Heavy Body Armor",Increment=0.01,Rank=0,StartingValue=0.f,MaxValue=0.25) ZedTimeReload=(Name="Zed Time Reload",Increment=0.03f,Rank=0,StartingValue=0.f,MaxValue=0.75f) + PassiveWeaponSwitchModifier=0.35f + PerkSkills(ESurvivalist_TacticalReload)=(Name="TacticalReload",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_TacticalReload", Increment=0.f,Rank=0,StartingValue=0.25,MaxValue=0.25) PerkSkills(ESurvivalist_HeavyWeaponsReload)=(Name="HeavyWeaponsReload",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_HeavyWeapons", Increment=0.f,Rank=0,StartingValue=2.5f,MaxValue=2.5f) PerkSkills(ESurvivalist_FieldMedic)=(Name="FieldMedic",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_FieldMedic", Increment=0.f,Rank=0,StartingValue=0.5f,MaxValue=0.5f) diff --git a/KFGame/Classes/KFPerk_Swat.uc b/KFGame/Classes/KFPerk_Swat.uc index 1a71977..658efde 100644 --- a/KFGame/Classes/KFPerk_Swat.uc +++ b/KFGame/Classes/KFPerk_Swat.uc @@ -356,7 +356,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) local name StateName; StateName = W.GetStateName(); - if( IsRapidAssaultActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class )) ) + if( IsRapidAssaultActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class ) || W.IsA('KFWeap_Pistol_Dual9mm') ) ) { if( ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE ) { @@ -404,7 +404,7 @@ function float GetStumblePowerModifier( optional KFPawn KFP, optional class 0 ) { - CurrTurn = Lerp( CurrTurn, ViewAccel_MaxTurnSpeed, ViewAccel_BlendTimer / ViewAccel_BlendTime ); + CurrTurn = Lerp( CurrTurn, ViewAccel_TurnSpeed, ViewAccel_BlendTimer / ViewAccel_BlendTime ); } else { - CurrTurn = Lerp( CurrTurn, -ViewAccel_MaxTurnSpeed, ViewAccel_BlendTimer / ViewAccel_BlendTime ); + CurrTurn = Lerp( CurrTurn, -ViewAccel_TurnSpeed, ViewAccel_BlendTimer / ViewAccel_BlendTime ); } } @@ -2952,8 +2971,9 @@ defaultproperties ViewAccel_JoyMagThreshold=0.97 ViewAccel_JoyPitchThreshold=0.4 ViewAccel_BlendTime=0.25 - ViewAccel_MaxTurnSpeed=2.4 - + ViewAccel_MaxTurnSpeed=4.5 + ViewAccel_MinTurnSpeed=1.0 + ForceLookAtPawnMinAngle=0.9f ForceLookAtPawnRotationRate=22 ForceLookAtPawnDampenedRotationRate=8 diff --git a/KFGame/Classes/KFProfileSettings.uc b/KFGame/Classes/KFProfileSettings.uc index 1413ed9..8750056 100644 --- a/KFGame/Classes/KFProfileSettings.uc +++ b/KFGame/Classes/KFProfileSettings.uc @@ -251,6 +251,9 @@ defaultproperties ProfileMappings.Add((Id=KFID_SavedInProgressIndex, Name="SavedInProgressIndex", MappingType=PVMT_RawValue)) ProfileMappings.Add((Id=KFID_ControllerSoundEnabled, Name="Controller Sound Enabled", MappingType=PVMT_RawValue)) ProfileMappings.Add((Id=KFID_MatchmakingRegion, Name="Matchmaking Region", MappingType=PVMT_RawValue)) + ProfileMappings.Add((Id=KFID_GamepadDeadzoneScale, Name="Gamepad Deadzone", MappingType=PVMT_RawValue)) + ProfileMappings.Add((Id=KFID_GamepadAccelerationJumpScale, Name="Gamepad Acceleration Jump", MappingType=PVMT_RawValue)) + //Added 7/11/2016 ProfileMappings.Add((Id=KFID_UseAltAimOnDuals, Name="Use alt Dual Aim", MappingType=PVMT_RawValue)) @@ -282,6 +285,8 @@ defaultproperties //Added 3/6/2019 - Classic Player Info ProfileMappings.Add((Id = KFID_ClassicPlayerInfo, Name = "Legacy Health Bars", MappingType = PVMT_RawValue)) + //Added 10/15/2020 - Has Enter to Store Tab during sales + ProfileMappings.Add((Id = KFID_HasTabbedToStore, Name = "Has Tabbed To Store", MappingType = PVMT_RawValue)) // Hex values for SDT_Float values, I use http://www.h-schmidt.net/FloatConverter/IEEE754.html for conversion @@ -364,4 +369,12 @@ defaultproperties //Added 3/6/2019 - Classic Player Info DefaultSettings.Add((Owner=OPPO_Game, ProfileSetting=(PropertyId=KFID_ClassicPlayerInfo, Data=(Type=SDT_INT32, Value1=0)))) + + //Added 10/1/2020 - Support for deadzone and acceleration jump gamepad settings + DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_GamepadDeadzoneScale,Data=(Type=SDT_Float,Value1=0x3e4ccccd)))) // 0.20f + DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_GamepadAccelerationJumpScale,Data=(Type=SDT_Float,Value1=0x3ecccccd)))) // 0.4f + + //Saber Added 10/15/2020 - Has Enter to Store Tab during sales + ProfileMappings.Add((Id = KFID_HasTabbedToStore, Name = "Has Tabbed To Store", MappingType = PVMT_RawValue)) + DefaultSettings.Add((Owner=OPPO_Game,ProfileSetting=(PropertyId=KFID_HasTabbedToStore,Data=(Type=SDT_Int32,Value1=0)))) } diff --git a/KFGame/Classes/KFSeasonalEventStats.uc b/KFGame/Classes/KFSeasonalEventStats.uc index e2393a1..27016e6 100644 --- a/KFGame/Classes/KFSeasonalEventStats.uc +++ b/KFGame/Classes/KFSeasonalEventStats.uc @@ -34,6 +34,7 @@ private event GrantEventItems(); final protected simulated function FinishedObjective(int EventIndex, int ObjectiveIndex) { local KFPlayerController KFPC; + local int year, month, dayofweek, day, hour, minute, second, msec; if (!IsValid()) { @@ -45,7 +46,8 @@ final protected simulated function FinishedObjective(int EventIndex, int Objecti !KFPC.PlayerReplicationInfo.bOnlySpectator && !Outer.HasCheated() && !Outer.IsEventObjectiveComplete(ObjectiveIndex)) { - Outer.UpdateSpecialEvent(EventIndex, ObjectiveIndex); + GetSystemTime(year, month, dayofweek, day, hour, minute, second, msec); + Outer.UpdateSpecialEvent(EventIndex, ObjectiveIndex, year, month); if (KFPC.MyGFxHUD != none && KFPC.MyGFxHUD.LevelUpNotificationWidget != none && ((class'KFGameEngine'.static.GetSeasonalEventID() % 10) == EventIndex)) diff --git a/KFGame/Classes/KFSeqAct_DrawCountText.uc b/KFGame/Classes/KFSeqAct_DrawCountText.uc new file mode 100644 index 0000000..7d2d8e2 --- /dev/null +++ b/KFGame/Classes/KFSeqAct_DrawCountText.uc @@ -0,0 +1,78 @@ +//============================================================================= +// KFSeqAct_DrawCountText +//============================================================================= +// Kismet node to draw texts in the counter container of the HUD +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= +class KFSeqAct_DrawCountText extends SequenceAction + dependson(HUD) + native; + +var(Message) string Message; + +var() class MapLocalizationClass; + +var() float DisplayTimeSeconds; + +var() vector2d MessageFontScale; +var() vector2d MessageOffset; +var() Color MessageColor; + +var bool bDisplayOnObject; + +cpptext +{ + UBOOL UpdateOp(FLOAT deltaTime); + virtual void Activated(); +}; + +var HUD.KismetDrawTextInfo DrawTextInfo; + +/** +* Return the version number for this class. Child classes should increment this method by calling Super then adding +* a individual class version to the result. When a class is first created, the number should be 0; each time one of the +* link arrays is modified (VariableLinks, OutputLinks, InputLinks, etc.), the number that is added to the result of +* Super.GetObjClassVersion() should be incremented by 1. +* +* @return the version number for this specific class. +*/ +static event int GetObjClassVersion() +{ + return Super.GetObjClassVersion() + 2; +} + +event Initialize() +{ + DrawTextInfo.MessageText = Message; + DrawTextInfo.MessageFont = GetFontText(); + DrawTextInfo.MessageFontScale = MessageFontScale; + DrawTextInfo.MessageOffset = MessageOffset; + DrawTextInfo.MessageColor = MessageColor; +} + +simulated function Font GetFontText() +{ + return MapLocalizationClass.static.GetFont(); +} + +defaultproperties +{ + ObjName="Draw Count Text" + ObjCategory="Killing Floor" + + DisplayTimeSeconds=-1 + + MessageFontScale=(X=1,Y=1) + MessageOffset=(X=0,Y=0) + MessageColor=(R=255,G=255,B=255,A=255) + + InputLinks(0)=(LinkDesc="Show") + InputLinks(1)=(LinkDesc="Hide") + + VariableLinks(1)=(ExpectedType=class'SeqVar_String',LinkDesc="String",MinVars=0,bHidden=TRUE) + + bLatentExecution=TRUE + bAutoActivateOutputLinks=FALSE +} diff --git a/KFGame/Classes/KFSeqAct_DrawLocalizedText.uc b/KFGame/Classes/KFSeqAct_DrawLocalizedText.uc new file mode 100644 index 0000000..93f3f43 --- /dev/null +++ b/KFGame/Classes/KFSeqAct_DrawLocalizedText.uc @@ -0,0 +1,111 @@ +//============================================================================= +// KFSeqAct_DrawLocalizedText +//============================================================================= +// Kismet node to draw localized texts in the HUD +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= +class KFSeqAct_DrawLocalizedText extends SequenceAction + dependson(HUD) + native; + +var int SecondaryIDValue; + +enum ELocalizedID +{ + LID_0, + LID_1, LID_2, LID_3, LID_4, LID_5, LID_6, LID_7, LID_8, LID_9, LID_10, + LID_11, LID_12, LID_13, LID_14, LID_15, LID_16, LID_17, LID_18, LID_19, LID_20, + LID_21, LID_22, LID_23, LID_24, LID_25, LID_26, LID_27, LID_28, LID_29, LID_30, + LID_31, LID_32, LID_33, LID_34, LID_35, LID_36, LID_37, LID_38, LID_39, LID_40, + LID_41, LID_42, LID_43, LID_44, LID_45, LID_46, LID_47, LID_48, LID_49, LID_MAX, +}; + +var(Message) ELocalizedID MessageLocalizedID; +var(Message) array SecondaryMessageLocalizedIDList; + +var(Message) bool bUseSecondaryMessage; +var(Message) string TextForReplace; + +var() class MapLocalizationClass; + +var() float DisplayTimeSeconds; + +var() vector2d MessageFontScale; +var() vector2d MessageOffset; +var() Color MessageColor; + +var bool bDisplayOnObject; + +cpptext +{ + UBOOL UpdateOp(FLOAT deltaTime); + virtual void Activated(); +}; + +var HUD.KismetDrawTextInfo DrawTextInfo; + +/** +* Return the version number for this class. Child classes should increment this method by calling Super then adding +* a individual class version to the result. When a class is first created, the number should be 0; each time one of the +* link arrays is modified (VariableLinks, OutputLinks, InputLinks, etc.), the number that is added to the result of +* Super.GetObjClassVersion() should be incremented by 1. +* +* @return the version number for this specific class. +*/ +static event int GetObjClassVersion() +{ + return Super.GetObjClassVersion() + 2; +} + +event Initialize() +{ + DrawTextInfo.MessageText = GetLocalizationText(); + DrawTextInfo.MessageFont = GetFontText(); + DrawTextInfo.MessageFontScale = MessageFontScale; + DrawTextInfo.MessageOffset = MessageOffset; + DrawTextInfo.MessageColor = MessageColor; +} + +simulated function string GetLocalizationText() +{ + Local string finalText; + Local string secondaryText; + + finalText = MapLocalizationClass.static.GetLocalization(MessageLocalizedID); + `log("bUseSecondaryMessage"@bUseSecondaryMessage); + if(bUseSecondaryMessage) + { + `log("SecondaryIDValue"@SecondaryIDValue); + secondaryText = MapLocalizationClass.static.GetLocalization(SecondaryMessageLocalizedIDList[SecondaryIDValue]); + class'Actor'.static.ReplaceText(finalText, TextForReplace, secondaryText); + } + return finalText; +} + +simulated function Font GetFontText() +{ + return MapLocalizationClass.static.GetFont(); +} + +defaultproperties +{ + ObjName="Draw Localized Text" + ObjCategory="Killing Floor" + + DisplayTimeSeconds=-1 + + MessageFontScale=(X=1,Y=1) + MessageOffset=(X=0,Y=0) + MessageColor=(R=255,G=255,B=255,A=255) + + InputLinks(0)=(LinkDesc="Show") + InputLinks(1)=(LinkDesc="Hide") + + VariableLinks(1)=(ExpectedType=class'SeqVar_String',LinkDesc="String",MinVars=0,bHidden=TRUE) + VariableLinks(2)=(ExpectedType=class'SeqVar_Int',LinkDesc="SecondaryIDValue",MinVars=0,bHidden=TRUE,bWriteable=true,PropertyName=SecondaryIDValue) + + bLatentExecution=TRUE + bAutoActivateOutputLinks=FALSE +} diff --git a/KFGame/Classes/KFSeqAct_DrawRandomLocalizedText.uc b/KFGame/Classes/KFSeqAct_DrawRandomLocalizedText.uc new file mode 100644 index 0000000..b2f46d6 --- /dev/null +++ b/KFGame/Classes/KFSeqAct_DrawRandomLocalizedText.uc @@ -0,0 +1,60 @@ +//============================================================================= +// KFSeqAct_DrawRandomLocalizedText +//============================================================================= +// Kismet node to draw random localized texts in the HUD +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= +class KFSeqAct_DrawRandomLocalizedText extends KFSeqAct_DrawLocalizedText + dependson(HUD) + HideCategories(Message) + native; + +var(RandomMessage) array MessageLocalizedIDList; + +cpptext +{ + UBOOL UpdateOp(FLOAT deltaTime); + virtual void Activated(); +}; + +/** +* Return the version number for this class. Child classes should increment this method by calling Super then adding +* a individual class version to the result. When a class is first created, the number should be 0; each time one of the +* link arrays is modified (VariableLinks, OutputLinks, InputLinks, etc.), the number that is added to the result of +* Super.GetObjClassVersion() should be incremented by 1. +* +* @return the version number for this specific class. +*/ +static event int GetObjClassVersion() +{ + return Super.GetObjClassVersion() + 3; +} + +simulated function string GetLocalizationText() +{ + Local int RandomValue; + RandomValue = Rand(MessageLocalizedIDList.length); + return MapLocalizationClass.static.GetLocalization(MessageLocalizedIDList[RandomValue]); +} + +defaultproperties +{ + ObjName="Draw Random Localized Text" + ObjCategory="Killing Floor" + + DisplayTimeSeconds=-1 + + MessageFontScale=(X=1,Y=1) + MessageOffset=(X=0,Y=0) + MessageColor=(R=255,G=255,B=255,A=255) + + InputLinks(0)=(LinkDesc="Show") + InputLinks(1)=(LinkDesc="Hide") + + VariableLinks(1)=(ExpectedType=class'SeqVar_String',LinkDesc="String",MinVars=0,bHidden=TRUE) + + bLatentExecution=TRUE + bAutoActivateOutputLinks=FALSE +} diff --git a/KFGame/Classes/KFSprayActor.uc b/KFGame/Classes/KFSprayActor.uc index a97f5c9..3b2e282 100644 --- a/KFGame/Classes/KFSprayActor.uc +++ b/KFGame/Classes/KFSprayActor.uc @@ -480,6 +480,27 @@ simulated function SetFOV( float NewFOV ) SkeletalSprayMesh.SetFOV(NewFOV); } +simulated function vector GetLastContactPositionMeshHit() +{ + local KFPawn_Monster KFPM; + local vector ClosestBonePosition; + + KFPM = KFPawn_Monster(HighestSprayMeshContactThisTick.Actor); + + if (KFPM != none && KFPM.Mesh != none && HighestSprayMeshContactThisTick.BoneName != '') + { + return KFPM.Mesh.GetBoneLocation(HighestSprayMeshContactThisTick.BoneName); + } + + if (KFPM != none && KFPM.Mesh != none) + { + KFPM.Mesh.FindClosestBone(HighestSprayMeshContactThisTick.ContactPosition, ClosestBonePosition); + return ClosestBonePosition; + } + //Based on KFSprayActor.cpp and value assigned to DesiredSplashLoc (however there it is adding instead of subtracting, worth taking a look) + return HighestSprayMeshContactThisTick.ContactPosition - HighestSprayMeshContactThisTick.ContactNormal * 32; +} + simulated function SetupFX() { local int ChainIdx, Idx; @@ -698,7 +719,6 @@ simulated function DetachAndFinish() simulated function CleanupEndFire() { local int Idx; - // turn off fire particles for (Idx=0; Idx 0; } + /** + * Returns true if this weapon uses greandes as secondary ammo + */ +static simulated event bool UsesGrenadesAsSecondaryAmmo() +{ + return default.bUseGrenadeAsSecondaryAmmo; +} + /** * Returns true if this weapon uses a secondary ammo pool */ @@ -4744,6 +4754,12 @@ simulated function int GetSecondaryAmmoForHUD() return AmmoCount[1] + SpareAmmoCount[1]; } +/** Determines if we have to reload the secondary ammo of the weapon (EX: m16 grenades) */ +simulated function bool HasToReloadSecondaryAmmoForHUD() +{ + return AmmoCount[1] == 0; +} + /** * Called by Player to force current weapon to be reloaded * NOTE: A reload will only begin once the weapons FireInterval has completed @@ -7907,6 +7923,7 @@ defaultproperties WeaponSelectTexture=Texture2D'ui_weaponselect_tex.UI_WeaponSelect_AR15' SecondaryAmmoTexture=Texture2D'UI_SecondaryAmmo_TEX.GasTank' bCanRefillSecondaryAmmo=true + bUseGrenadeAsSecondaryAmmo=false bNoMagazine=false bAllowClientAmmoTracking=true diff --git a/KFGame/Classes/KFWeaponSkinList.uc b/KFGame/Classes/KFWeaponSkinList.uc index 9756aac..7583293 100644 --- a/KFGame/Classes/KFWeaponSkinList.uc +++ b/KFGame/Classes/KFWeaponSkinList.uc @@ -3297,4 +3297,113 @@ defaultproperties //Mine Reconstructor Wastelander Skins.Add((Id=8477, Weapondef=class'KFWeapDef_Mine_Reconstructor', MIC_1P=("wep_skinset36_mat.Wep_1stP_MineReconstructor_Wastelander_MIC"), MIC_3P="wep_skinset36_mat.Wep_3rdP_MineReconstructor_Wastelander_MIC", MIC_Pickup="wep_skinset36_mat.Wep_3rdP_MineReconstructor_Wastelander_Pickup_MIC")) +//IceBreaker Sub Zero AK12 + Skins.Add((Id=8510, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Ak12', MIC_1P=("WEP_SkinSet38_MAT.winter_ak12.Winter_AK12_1P_Mint_MIC", "WEP_SkinSet38_MAT.winter_ak12.Winter_AK12_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_ak12.Winter_AK12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_ak12.Winter_AK12_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Boomstick + Skins.Add((Id=8511, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet38_MAT.winter_doublebarrel.Winter_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_doublebarrel.Winter_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_doublebarrel.Winter_DoubleBarrel_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Desert Eagle + Skins.Add((Id=8512, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet38_MAT.winter_deagle.Winter_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_deagle.Winter_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_deagle.Winter_Deagle_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Dragonsbreath + Skins.Add((Id=8513, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet38_MAT.winter_dragonsbreath.Winter_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_dragonsbreath.Winter_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_dragonsbreath.Winter_Dragonsbreath_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Hemoclobber + Skins.Add((Id=8514, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicBat', MIC_1P=("WEP_SkinSet38_MAT.winter_medicbat.Winter_MedicBat_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_medicbat.Winter_MedicBat_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_medicbat.Winter_MedicBat_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Kriss + Skins.Add((Id=8515, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Kriss', MIC_1P=("WEP_SkinSet38_MAT.winter_kriss.Winter_Kriss_1P_Mint_MIC", "WEP_SkinSet38_MAT.winter_kriss.Winter_Kriss_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_kriss.Winter_Kriss_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_kriss.Winter_Kriss_3P_Pickup_MIC")) + +//IceBreaker Sub Zero M79 + Skins.Add((Id=8516, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("wep_skinset38_mat.winter_m79.Winter_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_m79.Winter_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_m79.Winter_M79_3P_Pickup_MIC")) + +//IceBreaker Sub Zero M99 + Skins.Add((Id=8517, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M99', MIC_1P=("WEP_SkinSet38_MAT.winter_m99.Winter_M99_1P_Mint_MIC", "WEP_SkinSet38_MAT.winter_m99.Winter_M99_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_m99.Winter_m99_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_m99.Winter_M99_3P_Pickup_MIC")) + +//IceBreaker Sub Zero Pulverizer + Skins.Add((Id=8518, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Pulverizer', MIC_1P=("WEP_SkinSet38_MAT.winter_pulverizer.Winter_Pulverizer_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_pulverizer.Winter_Pulverizer_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_pulverizer.Winter_Pulverizer_3P_Pickup_MIC")) + +//IceBreaker Sub Zero RPG-7 + Skins.Add((Id=8519, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet38_MAT.winter_rpg7.Winter_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.winter_rpg7.Winter_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.winter_rpg7.Winter_RPG7_3P_Pickup_MIC")) + +//IceBreaker Precious AK12 + Skins.Add((Id=8520, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Ak12', MIC_1P=("WEP_SkinSet38_MAT.wintergold_ak12.WinterGold_AK12_1P_Mint_MIC", "WEP_SkinSet38_MAT.wintergold_ak12.WinterGold_AK12_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_ak12.WinterGold_AK12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_ak12.WinterGold_AK12_3P_Pickup_MIC")) + +//IceBreaker Precious Boomstick + Skins.Add((Id=8521, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet38_MAT.wintergold_doublebarrel.WinterGold_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_doublebarrel.WinterGold_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_doublebarrel.WinterGold_DoubleBarrel_3P_Pickup_MIC")) + +//IceBreaker Precious Desert Eagle + Skins.Add((Id=8522, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet38_MAT.wintergold_deagle.WinterGold_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_deagle.WinterGold_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_deagle.WinterGold_Deagle_3P_Pickup_MIC")) + +//IceBreaker Precious Dragonsbreath + Skins.Add((Id=8523, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Dragonsbreath', MIC_1P=("WEP_SkinSet38_MAT.wintergold_dragonsbreath.WinterGold_Dragonsbreath_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_dragonsbreath.WinterGold_Dragonsbreath_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_dragonsbreath.WinterGold_Dragonsbreath_3P_Pickup_MIC")) + +//IceBreaker Precious Hemoclobber + Skins.Add((Id=8524, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicBat', MIC_1P=("WEP_SkinSet38_MAT.wintergold_medicbat.WinterGold_MedicBat_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_medicbat.WinterGold_MedicBat_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_medicbat.WinterGold_MedicBat_3P_Pickup_MIC")) + +//IceBreaker Precious Kriss + Skins.Add((Id=8525, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Kriss', MIC_1P=("WEP_SkinSet38_MAT.wintergold_kriss.WinterGold_Kriss_1P_Mint_MIC", "WEP_SkinSet38_MAT.wintergold_kriss.WinterGold_Kriss_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_kriss.WinterGold_Kriss_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_kriss.WinterGold_Kriss_3P_Pickup_MIC")) + +//IceBreaker Precious M79 + Skins.Add((Id=8526, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M79', MIC_1P=("wep_skinset38_mat.wintergold_m79.WinterGold_M79_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_m79.WinterGold_M79_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_m79.WinterGold_M79_3P_Pickup_MIC")) + +//IceBreaker Precious M99 + Skins.Add((Id=8527, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M99', MIC_1P=("WEP_SkinSet38_MAT.wintergold_m99.WinterGold_M99_1P_Mint_MIC", "WEP_SkinSet38_MAT.wintergold_m99.WinterGold_M99_Scope_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_m99.WinterGold_m99_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_m99.WinterGold_M99_3P_Pickup_MIC")) + +//IceBreaker Precious Pulverizer + Skins.Add((Id=8528, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Pulverizer', MIC_1P=("WEP_SkinSet38_MAT.wintergold_pulverizer.WinterGold_Pulverizer_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_pulverizer.WinterGold_Pulverizer_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_pulverizer.WinterGold_Pulverizer_3P_Pickup_MIC")) + +//IceBreaker Precious RPG-7 + Skins.Add((Id=8529, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet38_MAT.wintergold_rpg7.WinterGold_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet38_MAT.wintergold_rpg7.WinterGold_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet38_MAT.wintergold_rpg7.WinterGold_RPG7_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Arc Generator + Skins.Add((Id=8530, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_EMP_ArcGenerator', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgarcgenerator.Spectre_HRGArcGenerator_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgarcgenerator.Spectre_HRGArcGenerator_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgarcgenerator.Spectre_HRGArcGenerator_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Scorcher + Skins.Add((Id=8531, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGScorcher', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgscorcher.Spectre_HRGScorcher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgscorcher.Spectre_HRGScorcher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgscorcher.Spectre_HRGScorcher_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Kaboomstick + Skins.Add((Id=8532, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_Kaboomstick', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgkaboomstick.Spectre_HRGKaboomstick_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgkaboomstick.Spectre_HRGKaboomstick_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgkaboomstick.Spectre_HRGKaboomstick_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Teslauncher + Skins.Add((Id=8533, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGTeslauncher', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgteslauncher.Spectre_HRGTesLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgteslauncher.Spectre_HRGTesLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgteslauncher.Spectre_HRGTesLauncher_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Incendiary Rifle + Skins.Add((Id=8534, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGIncendiaryRifle', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgincendiaryrifle.Spectre_HRGIncendiaryRifle_1P_Mint_MIC", "WEP_SkinSet37_MAT.spectre_hrgincendiaryrifle.Spectre_HRGIncendiaryRifleM203_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgincendiaryrifle.Spectre_HRGIncendiaryRifle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgincendiaryrifle.Spectre_HRGIncendiaryRifle_3P_Pickup_MIC")) + +//Spectre Dynamic HRG Vampire + Skins.Add((Id=8535, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_Vampire', MIC_1P=("WEP_SkinSet37_MAT.spectre_hrgvampire.Spectre_HRGVampire_1P_Mint_MIC", "WEP_SkinSet37_MAT.spectre_hrgvampire.Spectre_HRGVampire_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectre_hrgvampire.Spectre_HRGVampire_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectre_hrgvampire.Spectre_HRGVampire_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Arc Generator + Skins.Add((Id=8536, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_EMP_ArcGenerator', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgarcgenerator.SpectreChroma_HRGArcGenerator_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgarcgenerator.SpectreChroma_HRGArcGenerator_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgarcgenerator.SpectreChroma_HRGArcGenerator_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Scorcher + Skins.Add((Id=8537, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGScorcher', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgscorcher.SpectreChroma_HRGScorcher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgscorcher.SpectreChroma_HRGScorcher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgscorcher.SpectreChroma_HRGScorcher_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Kaboomstick + Skins.Add((Id=8538, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_Kaboomstick', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgkaboomstick.SpectreChroma_HRGKaboomstick_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgkaboomstick.SpectreChroma_HRGKaboomstick_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgkaboomstick.SpectreChroma_HRGKaboomstick_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Teslauncher + Skins.Add((Id=8539, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGTeslauncher', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgteslauncher.SpectreChroma_HRGTesLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgteslauncher.SpectreChroma_HRGTesLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgteslauncher.SpectreChroma_HRGTesLauncher_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Incendiary Rifle + Skins.Add((Id=8540, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRGIncendiaryRifle', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgincendiaryrifle.SpectreChroma_HRGIncendiaryRifle_1P_Mint_MIC", "WEP_SkinSet37_MAT.spectrechroma_hrgincendiaryrifle.SpectreChroma_HRGIncendiaryRifleM203_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgincendiaryrifle.SpectreChroma_HRGIncendiaryRifle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgincendiaryrifle.SpectreChroma_HRGIncendiaryRifle_3P_Pickup_MIC")) + +//Spectre Dynamic Chroma HRG Vampire + Skins.Add((Id=8541, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_HRG_Vampire', MIC_1P=("WEP_SkinSet37_MAT.spectrechroma_hrgvampire.SpectreChroma_HRGVampire_1P_Mint_MIC", "WEP_SkinSet37_MAT.spectrechroma_hrgvampire.SpectreChroma_HRGVampire_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet37_MAT.spectrechroma_hrgvampire.SpectreChroma_HRGVampire_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet37_MAT.spectrechroma_hrgvampire.SpectreChroma_HRGVampire_3P_Pickup_MIC")) + +//8609 Frost Fang | Standard + Skins.Add((Id=8609, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_1P_Frost_Shotgun_Axe_MAT.WEP_1stP_Frost_Shotgun_MIC"), MIC_3P="WEP_3P_Frost_Shotgun_Axe_MAT.Wep_3rdP_Frost_Shotgun_MIC", MIC_Pickup="WEP_3P_Frost_Shotgun_Axe_MAT.Wep_3rdP_Frost_Shotgun_Pickup_MIC")) +//8610 Frost Fang | Wood + Skins.Add((Id=8610, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_SkinSet39_MAT.Wep_1stP_Frost_Shotgun_Wood_MIC"), MIC_3P="WEP_SkinSet39_MAT.Wep_3rdP_Frost_Shotgun_Wood_MIC", MIC_Pickup="WEP_SkinSet39_MAT.Wep_3rdP_Frost_Shotgun_Wood_Pickup_MIC")) +//8611 Frost Fang | Cabala + Skins.Add((Id=8611, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_SkinSet39_MAT.Wep_1stP_Frost_Shotgun_Cabala_MIC"), MIC_3P="WEP_SkinSet39_MAT.Wep_3stP_Frost_Shotgun_Cabala_MIC", MIC_Pickup="WEP_SkinSet39_MAT.Wep_3stP_Frost_Shotgun_Cabala_Pickup_MIC")) +//8612 Frost Fang | Runic + Skins.Add((Id=8612, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_SkinSet39_MAT.Wep_1stP_Frost_Shotgun_Runic_MIC"), MIC_3P="WEP_SkinSet39_MAT.Wep_3stP_Frost_Shotgun_Runic_MIC", MIC_Pickup="WEP_SkinSet39_MAT.Wep_3rdP_Frost_Shotgun_Runic_Pickup_MIC")) +//8613 Frost Fang | Deco Ice + Skins.Add((Id=8613, Weapondef=class'KFWeapDef_Rifle_FrostShotgunAxe', MIC_1P=("WEP_SkinSet39_MAT.Wep_1stP_Frost_Shotgun_DecoIce_MIC"), MIC_3P="WEP_SkinSet39_MAT.Wep_3stP_Frost_Shotgun_DecoIce_MIC", MIC_Pickup="WEP_SkinSet39_MAT.Wep_3rdP_Frost_Shotgun_DecoIce_Pickup_MIC")) +//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")) + } \ No newline at end of file diff --git a/KFGame/KFOnlineStats.uci b/KFGame/KFOnlineStats.uci index 262619d..17c2dd2 100644 --- a/KFGame/KFOnlineStats.uci +++ b/KFGame/KFOnlineStats.uci @@ -151,4 +151,5 @@ const STATID_ACHIEVE_DefeatMatriarch = 4053; const STATID_ACHIEVE_BiolapseCollectibles = 4054; const STATID_ACHIEVE_DesolationCollectibles = 4055; const STATID_ACHIEVE_HellmarkStationCollectibles = 4056; +const STATID_ACHIEVE_ElysiumEndlessWaveFifteen = 4057; /** `endif */ diff --git a/KFGame/KFProfileSettings.uci b/KFGame/KFProfileSettings.uci index c4d56b7..437b516 100644 --- a/KFGame/KFProfileSettings.uci +++ b/KFGame/KFProfileSettings.uci @@ -70,4 +70,6 @@ const KFID_SavedHeadshotID= 171; const KFID_ToggleToRun=172; const KFID_ClassicPlayerInfo=173; const KFID_VOIPMicVolumeMultiplier = 174; - +const KFID_GamepadDeadzoneScale = 175; +const KFID_GamepadAccelerationJumpScale = 176; +const KFID_HasTabbedToStore = 177; diff --git a/KFGameContent/Classes/KFDT_Ballistic_DragonsBreath.uc b/KFGameContent/Classes/KFDT_Ballistic_DragonsBreath.uc index 345f4e4..d57351f 100644 --- a/KFGameContent/Classes/KFDT_Ballistic_DragonsBreath.uc +++ b/KFGameContent/Classes/KFDT_Ballistic_DragonsBreath.uc @@ -9,8 +9,7 @@ //============================================================================= class KFDT_Ballistic_DragonsBreath extends KFDT_Ballistic_Shotgun - abstract - hidedropdown; + abstract; // Damage type to use for the burning damage over time var class BurnDamageType; diff --git a/KFGameContent/Classes/KFDT_Ballistic_Frost_Shotgun_Axe.uc b/KFGameContent/Classes/KFDT_Ballistic_Frost_Shotgun_Axe.uc new file mode 100644 index 0000000..106d6c7 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_Frost_Shotgun_Axe.uc @@ -0,0 +1,50 @@ +//============================================================================= +// KFDT_Ballistic_Frost_Shotgun_Axe +//============================================================================= +// Ballistic damage with light impact energy, but stronger hit reactions +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_Frost_Shotgun_Axe extends KFDT_Ballistic_Shotgun + abstract + hidedropdown; + +/** Allows the damage type to customize exactly which hit zones it can dismember */ +static simulated function bool CanDismemberHitZone( name InHitZoneName ) +{ + if( super.CanDismemberHitZone( InHitZoneName ) ) + { + return true; + } + + switch ( InHitZoneName ) + { + case 'lupperarm': + case 'rupperarm': + return true; + } + + return false; +} + +defaultproperties +{ + // Physics + KDamageImpulse=2500 //2750 + KDeathUpKick=800 + KDeathVel=650 + + // Afflictions + StumblePower =20 //40 + GunHitPower =20 + FreezePower =11 //17 + + WeaponDef=class'KFWeapDef_Rifle_FrostShotgunAxe' + + ModifierPerkList(0)=class'KFPerk_Support' + ModifierPerkList(1)=class'KFPerk_Berserker' + + EffectGroup=FXG_Freeze +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact.uc new file mode 100644 index 0000000..1e72293 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact.uc @@ -0,0 +1,23 @@ +//============================================================================= +// KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact extends KFDT_Ballistic_HRG_Vampire_BloodBallImpact + abstract + hidedropdown; + +defaultproperties +{ + PoisonPower=30 //80 + StumblePower=350 + KnockdownPower=140 + GunHitPower=350 + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallImpact.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallImpact.uc new file mode 100644 index 0000000..d8de0e3 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_Vampire_BloodBallImpact.uc @@ -0,0 +1,32 @@ +//============================================================================= +// KFDT_Ballistic_HRG_Vampire_BloodBallImpact +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_HRG_Vampire_BloodBallImpact extends KFDT_Ballistic_Shell + abstract + hidedropdown; + +static simulated function bool CanDismemberHitZone( name InHitZoneName ) +{ + return false; +} + +defaultproperties +{ + DoT_Type=DOT_NONE + + EffectGroup=FXG_Toxic + + PoisonPower=10 //20 + StumblePower=40 //100 + KnockdownPower=0 //25 + GunHitPower=40 //100 + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} diff --git a/KFGameContent/Classes/KFDT_Bleeding_HRG_Vampire_BloodSuck.uc b/KFGameContent/Classes/KFDT_Bleeding_HRG_Vampire_BloodSuck.uc new file mode 100644 index 0000000..0169e86 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bleeding_HRG_Vampire_BloodSuck.uc @@ -0,0 +1,46 @@ +//============================================================================= +// KFDT_Bleeding_HRG_Vampire_BloodSuck +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Bleeding_HRG_Vampire_BloodSuck extends KFDT_Bleeding + abstract; + +/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */ +static function ApplySecondaryDamage( KFPawn Victim, int DamageTaken, optional Controller InstigatedBy ) +{ + local class ToxicDT; + + ToxicDT = class'KFDT_Ballistic_Assault_Medic'.static.GetMedicToxicDmgType( DamageTaken, InstigatedBy ); + if ( ToxicDT != None ) + { + Victim.ApplyDamageOverTime(DamageTaken, InstigatedBy, ToxicDT); + } +} + +defaultproperties +{ + //physics + KDamageImpulse=0 + KDeathUpKick=350 + KDeathVel=350 + + //Afflictions + BleedPower=50 //50 + StumblePower=0 //20 + GunHitPower=5 + + //Damage Over Time Components + DoT_Type=DOT_Bleeding + DoT_Duration=0.5 //5.0 + DoT_Interval=0.5 //1.0 + DoT_DamageScale=0.1 + bStackDoT=true + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Bludgeon_FireAxeBash.uc b/KFGameContent/Classes/KFDT_Bludgeon_FireAxeBash.uc index 4a97173..c2a6895 100644 --- a/KFGameContent/Classes/KFDT_Bludgeon_FireAxeBash.uc +++ b/KFGameContent/Classes/KFDT_Bludgeon_FireAxeBash.uc @@ -15,7 +15,7 @@ defaultproperties KDeathUpKick=0 KDeathVel=500 - StumblePower=150 + StumblePower=200 //150 MeleeHitPower=100 WeaponDef=class'KFWeapDef_FireAxe' diff --git a/KFGameContent/Classes/KFDT_Bludgeon_HRG_Vampire.uc b/KFGameContent/Classes/KFDT_Bludgeon_HRG_Vampire.uc new file mode 100644 index 0000000..b595026 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_HRG_Vampire.uc @@ -0,0 +1,19 @@ +//============================================================================= +// KFDT_Bludgeon_HRG_Vampire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Bludgeon_HRG_Vampire extends KFDT_Bludgeon_RifleButt + abstract + hidedropdown; + +DefaultProperties +{ + StumblePower=200 + MeleeHitPower=100 + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Explosive_HRGIncendiaryRifle.uc b/KFGameContent/Classes/KFDT_Explosive_HRGIncendiaryRifle.uc index 9dea35e..314a819 100644 --- a/KFGameContent/Classes/KFDT_Explosive_HRGIncendiaryRifle.uc +++ b/KFGameContent/Classes/KFDT_Explosive_HRGIncendiaryRifle.uc @@ -7,8 +7,7 @@ //============================================================================= class KFDT_Explosive_HRGIncendiaryRifle extends KFDT_Fire - abstract - hidedropdown; + abstract; // Damage type to use for the burning damage over time var class BurnDamageType; diff --git a/KFGameContent/Classes/KFDT_Explosive_HuskCannon.uc b/KFGameContent/Classes/KFDT_Explosive_HuskCannon.uc index 7532499..d2afd6c 100644 --- a/KFGameContent/Classes/KFDT_Explosive_HuskCannon.uc +++ b/KFGameContent/Classes/KFDT_Explosive_HuskCannon.uc @@ -8,8 +8,7 @@ //============================================================================= class KFDT_Explosive_HuskCannon extends KFDT_Explosive - abstract - hidedropdown; + abstract; // Damage type to use for the burning damage over time var class BurnDamageType; diff --git a/KFGameContent/Classes/KFDT_Fire_FlareGun_Dual.uc b/KFGameContent/Classes/KFDT_Fire_FlareGun_Dual.uc index 02e2d4a..e66b3b0 100644 --- a/KFGameContent/Classes/KFDT_Fire_FlareGun_Dual.uc +++ b/KFGameContent/Classes/KFDT_Fire_FlareGun_Dual.uc @@ -7,8 +7,7 @@ // Copyright (C) 2017 Tripwire Interactive LLC //============================================================================= class KFDT_Fire_FlareGun_Dual extends KFDT_Fire_FlareGun - abstract - hidedropdown; + abstract; defaultproperties { diff --git a/KFGameContent/Classes/KFDT_Fire_Ground_DragonsBreath.uc b/KFGameContent/Classes/KFDT_Fire_Ground_DragonsBreath.uc index ac8a80a..b52bfe5 100644 --- a/KFGameContent/Classes/KFDT_Fire_Ground_DragonsBreath.uc +++ b/KFGameContent/Classes/KFDT_Fire_Ground_DragonsBreath.uc @@ -9,8 +9,7 @@ //============================================================================= class KFDT_Fire_Ground_DragonsBreath extends KFDT_Fire_Ground - abstract - hidedropdown; + abstract; static function int GetKillerDialogID() { diff --git a/KFGameContent/Classes/KFDT_Fire_Ground_FlareGun.uc b/KFGameContent/Classes/KFDT_Fire_Ground_FlareGun.uc index de39b73..3cdb029 100644 --- a/KFGameContent/Classes/KFDT_Fire_Ground_FlareGun.uc +++ b/KFGameContent/Classes/KFDT_Fire_Ground_FlareGun.uc @@ -8,8 +8,7 @@ // Tulio Beloqui (Saber Interactive) //============================================================================= class KFDT_Fire_Ground_FlareGun extends KFDT_Fire_Ground - abstract - hidedropdown; + abstract; static function int GetKillerDialogID() { diff --git a/KFGameContent/Classes/KFDT_Fire_Ground_HRGScorcher.uc b/KFGameContent/Classes/KFDT_Fire_Ground_HRGScorcher.uc index c99032b..e18f66e 100644 --- a/KFGameContent/Classes/KFDT_Fire_Ground_HRGScorcher.uc +++ b/KFGameContent/Classes/KFDT_Fire_Ground_HRGScorcher.uc @@ -9,8 +9,7 @@ //============================================================================= class KFDT_Fire_Ground_HRGScorcher extends KFDT_Fire_Ground - abstract - hidedropdown; + abstract; static function int GetKillerDialogID() { diff --git a/KFGameContent/Classes/KFDT_Fire_Ground_MolotovGrenade.uc b/KFGameContent/Classes/KFDT_Fire_Ground_MolotovGrenade.uc index 7fa46c9..39f53e3 100644 --- a/KFGameContent/Classes/KFDT_Fire_Ground_MolotovGrenade.uc +++ b/KFGameContent/Classes/KFDT_Fire_Ground_MolotovGrenade.uc @@ -9,8 +9,7 @@ //============================================================================= class KFDT_Fire_Ground_MolotovGrenade extends KFDT_Fire_Ground - abstract - hidedropdown; + abstract; defaultproperties { diff --git a/KFGameContent/Classes/KFDT_Fire_MolotovGrenade.uc b/KFGameContent/Classes/KFDT_Fire_MolotovGrenade.uc index 5d75d93..1b6ba49 100644 --- a/KFGameContent/Classes/KFDT_Fire_MolotovGrenade.uc +++ b/KFGameContent/Classes/KFDT_Fire_MolotovGrenade.uc @@ -9,8 +9,7 @@ //============================================================================= class KFDT_Fire_MolotovGrenade extends KFDT_Fire - abstract - hidedropdown; + abstract; defaultproperties { diff --git a/KFGameContent/Classes/KFDT_Piercing_HRG_Vampire_CrystalSpike.uc b/KFGameContent/Classes/KFDT_Piercing_HRG_Vampire_CrystalSpike.uc new file mode 100644 index 0000000..202b271 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Piercing_HRG_Vampire_CrystalSpike.uc @@ -0,0 +1,37 @@ +//============================================================================= +// KFDT_Piercing_HRG_Vampire_CrystalSpike +//============================================================================= +// Damage type for crystal spike (alternate fire) of HRG Vampire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Piercing_HRG_Vampire_CrystalSpike extends KFDT_Piercing + abstract + hidedropdown; + +/** Called when damage is dealt to apply additional damage type (e.g. Damage Over Time) */ +static function ApplySecondaryDamage( KFPawn Victim, int DamageTaken, optional Controller InstigatedBy ) +{ + local class ToxicDT; + + ToxicDT = class'KFDT_Ballistic_Assault_Medic'.static.GetMedicToxicDmgType( DamageTaken, InstigatedBy ); + if ( ToxicDT != None ) + { + Victim.ApplyDamageOverTime(DamageTaken, InstigatedBy, ToxicDT); + } +} + +defaultproperties +{ + KDamageImpulse=1500 + KDeathUpKick=250 + KDeathVel=150 + + StumblePower=250 + GunHitPower=100 + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} diff --git a/KFGameContent/Classes/KFDT_Piercing_IonThrusterStab.uc b/KFGameContent/Classes/KFDT_Piercing_IonThrusterStab.uc index 8bf5e3e..8968ab4 100644 --- a/KFGameContent/Classes/KFDT_Piercing_IonThrusterStab.uc +++ b/KFGameContent/Classes/KFDT_Piercing_IonThrusterStab.uc @@ -6,8 +6,7 @@ //============================================================================= class KFDT_Piercing_IonThrusterStab extends KFDT_Piercing - abstract - hidedropdown; + abstract; // Damage type to use for the burning damage over time var class BurnDamageType; diff --git a/KFGameContent/Classes/KFDT_Slashing_FireAxe.uc b/KFGameContent/Classes/KFDT_Slashing_FireAxe.uc index ab4aad2..9f31b38 100644 --- a/KFGameContent/Classes/KFDT_Slashing_FireAxe.uc +++ b/KFGameContent/Classes/KFDT_Slashing_FireAxe.uc @@ -126,8 +126,9 @@ static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, n defaultproperties { - KDamageImpulse=200 - KDeathUpKick=250 + KDamageImpulse=2000 + KDeathUpKick=500 + KDeathVel=500 StumblePower=50 MeleeHitPower=150 diff --git a/KFGameContent/Classes/KFDT_Slashing_FireAxeHeavy.uc b/KFGameContent/Classes/KFDT_Slashing_FireAxeHeavy.uc index 4681562..5b4c828 100644 --- a/KFGameContent/Classes/KFDT_Slashing_FireAxeHeavy.uc +++ b/KFGameContent/Classes/KFDT_Slashing_FireAxeHeavy.uc @@ -29,11 +29,12 @@ static simulated function bool CanDismemberHitZone(name InHitZoneName) defaultproperties { - KDamageImpulse=300 - KDeathUpKick=400 + KDamageImpulse=2500 + KDeathUpKick=700 + KDeathVel=700 StumblePower=75 - StunPower=75 + StunPower=100 //75 MeleeHitPower=100 WeaponDef=class'KFWeapDef_FireAxe' diff --git a/KFGameContent/Classes/KFDT_Slashing_Frost_Shotgun_Axe.uc b/KFGameContent/Classes/KFDT_Slashing_Frost_Shotgun_Axe.uc new file mode 100644 index 0000000..972bd99 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Slashing_Frost_Shotgun_Axe.uc @@ -0,0 +1,142 @@ +//============================================================================= +// KFDT_Slashing_Frost_Shotgun_Axe +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2017 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Slashing_Frost_Shotgun_Axe extends KFDT_Slashing + abstract + hidedropdown; + +/** Allows the damage type to customize exactly which hit zones it can dismember */ +static simulated function bool CanDismemberHitZone( name InHitZoneName ) +{ + return true; +} + +/** Allows the damage type to map a hit zone to a different bone for dismemberment purposes */ +static simulated function GetBoneToDismember(KFPawn_Monster InPawn, vector HitDirection, name InHitZoneName, out name OutBoneName) +{ + local EPawnOctant SlashDir; + local KFCharacterInfo_Monster MonsterInfo; + + MonsterInfo = InPawn.GetCharacterMonsterInfo(); + if ( MonsterInfo == none ) + { + return; + } + + SlashDir = GetLastSlashDirection(InPawn, HitDirection); + + if( SlashDir == DIR_Forward || SlashDir == DIR_Backward ) + { + if( InHitZoneName == 'chest' || InHitZoneName == 'head' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit ) + { + // Randomly pick the left or right shoulder bone and split the guy in half vertically + OutBoneName = Rand(2) == 0 + ? MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName + : MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName; + } + } + } + else if( SlashDir == DIR_Left || SlashDir == DIR_Right ) + { + if( InHitZoneName == 'chest' || InHitZoneName == 'abdomen' || InHitZoneName == 'stomach' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowHorizontalSplit ) + { + // Split the guy in half horizontally + OutBoneName = MonsterInfo.SpecialMeleeDismemberment.SpineBoneName; + } + } + } + else if( SlashDir == DIR_ForwardLeft || SlashDir == DIR_BackwardRight ) + { + if( InHitZoneName == 'chest' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit ) + { + OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName; + } + } + else if( InHitZoneName == 'head' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit ) + { + // Use a random chance to decide whether to dismember the head or the shoulder constraints + if( Rand(2) == 0 ) + { + // ... and choose one of the shoulder constraints at random + OutBoneName = MonsterInfo.SpecialMeleeDismemberment.RightShoulderBoneName; + } + } + } + } + else if( SlashDir == DIR_ForwardRight || SlashDir == DIR_BackwardLeft ) + { + if( InHitZoneName == 'chest' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit ) + { + OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName; + } + } + else if( InHitZoneName == 'head' ) + { + if( MonsterInfo.SpecialMeleeDismemberment.bAllowVerticalSplit ) + { + // Use a random chance to decide whether to dismember the head or the shoulder constraints + if( Rand(2) == 0 ) + { + OutBoneName = MonsterInfo.SpecialMeleeDismemberment.LeftShoulderBoneName; + } + } + } + } +} + +/** Allows the damage type to modify the impulse when a specified hit zone is dismembered */ +static simulated function ModifyDismembermentHitImpulse(KFPawn_Monster InPawn, name InHitZoneName, vector HitDirection, + out vector OutImpulseDir, out vector OutParentImpulseDir, + out float OutImpulseScale, out float OutParentImpulseScale) +{ + local EPawnOctant SlashDir; + + SlashDir = GetLastSlashDirection(InPawn, HitDirection); + + // Apply upward impulse on decapitation from a clean horizontal slash + if( InHitZoneName == 'head' && + ( SlashDir == DIR_Left || SlashDir == DIR_Right ) ) + { + OutImpulseDir += 10*vect(0,0,1); + OutImpulseDir = Normal(OutImpulseDir); + OutParentImpulseScale = 0.f; + } + // Do not apply any impulse on split in half from a vertical slash + else if( (InHitZoneName == 'head' || InHitZoneName == 'chest' ) && + ( SlashDir == DIR_Forward || SlashDir == DIR_Backward) ) + { + OutImpulseScale = 0.f; + OutParentImpulseScale = 0.f; + } +} + +//IsDoingSpecialMove(SM_Frozen) +defaultproperties +{ + //KDamageImpulse=200 + //KDeathUpKick=250 + KDamageImpulse=2500 + KDeathUpKick=700 + KDeathVel=700 + + StumblePower=250 + MeleeHitPower=200 + + WeaponDef=class'KFWeapDef_Rifle_FrostShotgunAxe' + + ModifierPerkList(0)=class'KFPerk_Berserker' +} diff --git a/KFGameContent/Classes/KFDT_Slashing_IonThruster.uc b/KFGameContent/Classes/KFDT_Slashing_IonThruster.uc index 2d9333f..b766be5 100644 --- a/KFGameContent/Classes/KFDT_Slashing_IonThruster.uc +++ b/KFGameContent/Classes/KFDT_Slashing_IonThruster.uc @@ -6,8 +6,7 @@ //============================================================================= class KFDT_Slashing_IonThruster extends KFDT_Slashing - abstract - hidedropdown; + abstract; // Damage type to use for the burning damage over time var class BurnDamageType; diff --git a/KFGameContent/Classes/KFDT_Slashing_IonThrusterHeavy.uc b/KFGameContent/Classes/KFDT_Slashing_IonThrusterHeavy.uc index ed1644a..df89249 100644 --- a/KFGameContent/Classes/KFDT_Slashing_IonThrusterHeavy.uc +++ b/KFGameContent/Classes/KFDT_Slashing_IonThrusterHeavy.uc @@ -6,8 +6,7 @@ //============================================================================= class KFDT_Slashing_IonThrusterHeavy extends KFDT_Slashing_IonThruster - abstract - hidedropdown; + abstract; /** Allows the damage type to customize exactly which hit zones it can dismember */ static simulated function bool CanDismemberHitZone( name InHitZoneName ) diff --git a/KFGameContent/Classes/KFDT_Slashing_IonThrusterSpecial.uc b/KFGameContent/Classes/KFDT_Slashing_IonThrusterSpecial.uc index ce6a094..1cbcea1 100644 --- a/KFGameContent/Classes/KFDT_Slashing_IonThrusterSpecial.uc +++ b/KFGameContent/Classes/KFDT_Slashing_IonThrusterSpecial.uc @@ -6,8 +6,7 @@ //============================================================================= class KFDT_Slashing_IonThrusterSpecial extends KFDT_Slashing_IonThruster - abstract - hidedropdown; + abstract; /** Allows the damage type to customize exactly which hit zones it can dismember */ static simulated function bool CanDismemberHitZone( name InHitZoneName ) diff --git a/KFGameContent/Classes/KFDT_Toxic_HRG_Vampire_BloodBall.uc b/KFGameContent/Classes/KFDT_Toxic_HRG_Vampire_BloodBall.uc new file mode 100644 index 0000000..b7b095b --- /dev/null +++ b/KFGameContent/Classes/KFDT_Toxic_HRG_Vampire_BloodBall.uc @@ -0,0 +1,27 @@ +//============================================================================= +// KFDT_Toxic_HRG_Vampire_BloodBall +//============================================================================= +// Toxic Cloud DamageType +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Toxic_HRG_Vampire_BloodBall extends KFDT_Toxic + abstract + hidedropdown; + +defaultproperties +{ + PoisonPower=16 + StumblePower=40 //200 + KnockdownPower=0 //40 + + DoT_Type=DOT_Toxic + DoT_Duration=2.0 //1.0 + DoT_Interval=0.5 //1.0 + DoT_DamageScale=0.1 + + ModifierPerkList(0)=class'KFPerk_FieldMedic' + WeaponDef=class'KFWeapDef_HRG_Vampire' +} diff --git a/KFGameContent/Classes/KFExplosion_HRG_Vampire_BloodBall.uc b/KFGameContent/Classes/KFExplosion_HRG_Vampire_BloodBall.uc new file mode 100644 index 0000000..e381ae1 --- /dev/null +++ b/KFGameContent/Classes/KFExplosion_HRG_Vampire_BloodBall.uc @@ -0,0 +1,282 @@ +//============================================================================= +// KFExplosion_HRG_Vampire_BloodBall +//============================================================================= +// Used by projectiles and kismet to spawn an explosion +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFExplosion_HRG_Vampire_BloodBall extends KFExplosionActorLingering; + +var() class HealingDamageType; +var() float HealingAmount; + +var AkEvent SmokeLoopStartEvent; +var AkEvent SmokeLoopStopEvent; + +var KFPerk CachedInstigatorPerk; + +var float ChargePercentage; + +var float DamageByChargePercentage; + +var float fMinAmmoutHealing; +var float fMaxAmmoutHealing; + +var float fAltMinAmmoutHealing; +var float fAltMaxAmmoutHealing; + +var bool bHealsInstigator; +var bool bHealsDifferentAmmoutToInstigator; + +var float ImpactDecalSizeMax; +var float ImpactDecalSizeMin; + +simulated function SpawnExplosionParticleSystem(ParticleSystem Template) +{ + local ParticleSystemComponent PSC; + local vector vec; + + // If the template is none, grab the default + if( !ExplosionTemplate.bAllowPerMaterialFX && Template == none ) + { + Template = KFGameExplosion(ExplosionTemplate).ExplosionEffects.DefaultImpactEffect.ParticleTemplate; + } + + // Use custom pool + PSC = WorldInfo.MyEmitterPool.SpawnEmitter(Template, Location, rotator(ExplosionTemplate.HitNormal), None); + //ChargePercentage + vec.X = ChargePercentage; + vec.Y = ChargePercentage; + vec.Z = ChargePercentage; + PSC.SetVectorParameter( name("BlobCharge"), vec); + PSC.SetFloatParameter( name("MineFxControlParam"), ChargePercentage); + + +} + +/* + * @param Direction For bDirectionalExplosion=true explosions, this is the forward direction of the blast. + * Overridden to add the ability to spawn fragments from the explosion + **/ +simulated function Explode(GameExplosion NewExplosionTemplate, optional vector Direction) +{ + local KFPawn KFP; + super.Explode(NewExplosionTemplate, Direction); + + if( Instigator != none ) + { + + KFP = KFPawn(Instigator); + if( KFP != none ) + { + CachedInstigatorPerk = KFP.GetPerk(); + } + } + + if (Role == Role_Authority) + { + //DelayedExplosionDamage(); + SetTimer(Interval, false, nameof(DelayedExplosionDamage), self); + } +} + +/** + * Deal damage or heal players + */ +protected simulated function AffectsPawn(Pawn Victim, float DamageScale) +{ + local KFPawn_Human HumanVictim; + local KFPawn_Monster MonsterVictim; + local KFProj_MedicGrenade OwnerProjectile; + local bool bCanRepairArmor; + local Box BBox; + local vector BBoxCenter; + local Actor HitActor; + local bool bDamageBlocked; + local float AmountToHeal; + + + if( Victim != none && Victim.IsAliveAndWell() ) + { + MonsterVictim = KFPawn_Monster(Victim); + if( MonsterVictim != none ) + { + if( bWasFadedOut|| bDeleteMe || bPendingDelete ) + { + return; + } + + Victim.GetComponentsBoundingBox(BBox); + BBoxCenter = (BBox.Min + BBox.Max) * 0.5f; + HitActor = TraceExplosive(BBoxCenter, Location + vect(0, 0, 20)); + bDamageBlocked = (HitActor != None && HitActor != Victim); + if(bDamageBlocked && HitActor.IsA('KFDoorActor')) + { + bDamageBlocked = false; + } + if( !bDamageBlocked ) + { + Victim.TakeRadiusDamage(InstigatorController, ExplosionTemplate.Damage * DamageScale, ExplosionTemplate.DamageRadius, + ExplosionTemplate.MyDamageType, ExplosionTemplate.MomentumTransferScale, Location, bDoFullDamage, + (Owner != None) ? Owner : self, ExplosionTemplate.DamageFalloffExponent); + } + + } + else + { + + Victim.GetComponentsBoundingBox(BBox); + BBoxCenter = (BBox.Min + BBox.Max) * 0.5f; + HitActor = TraceExplosive(BBoxCenter, Location + vect(0, 0, 20)); + bDamageBlocked = (HitActor != None && HitActor != Victim); + if(bDamageBlocked && HitActor.IsA('KFDoorActor')) + { + bDamageBlocked = false; + } + if(!bDamageBlocked) + { + if(!bHealsInstigator && Victim == Instigator) + { + return; + } + HumanVictim = KFPawn_Human(Victim); + if( HumanVictim != none && HumanVictim.GetExposureTo(Location) > 0 ) + { + OwnerProjectile = KFProj_MedicGrenade(Owner); + if( OwnerProjectile != none ) + { + bCanRepairArmor = OwnerProjectile.HealedPawns.Find( HumanVictim ) == INDEX_NONE; + } + + if(bHealsDifferentAmmoutToInstigator && bHealsInstigator && Victim == Instigator) + { + AmountToHeal = FMax(fAltMinAmmoutHealing, Lerp(fAltMinAmmoutHealing, fAltMaxAmmoutHealing, DamageByChargePercentage)); + HumanVictim.HealDamage( AmountToHeal, InstigatorController, HealingDamageType, bCanRepairArmor); + } + else + { + AmountToHeal = FMax(fMinAmmoutHealing, Lerp(fMinAmmoutHealing, fMaxAmmoutHealing, DamageByChargePercentage)); + HumanVictim.HealDamage( AmountToHeal, InstigatorController, HealingDamageType, bCanRepairArmor); + } + + if( bCanRepairArmor ) + { + OwnerProjectile.HealedPawns.AddItem( HumanVictim ); + } + } + } + } + } +} + +simulated protected function UpdateExplosionTemplateWithPerMaterialFX(PhysicalMaterial PhysMaterial) +{ + super.UpdateExplosionTemplateWithPerMaterialFX(PhysMaterial); + + // Set a default impact effect if there isn't a physical material + if( PhysMaterial == none ) + { + MyImpactEffect = KFGameExplosion(ExplosionTemplate).ExplosionEffects.DefaultImpactEffect; + } + else if( WorldInfo.MyImpactEffectManager != none ) // none on dedicated server + { + `ImpactEffectManager.GetImpactEffect(PhysMaterial, MyImpactEffect,KFGameExplosion(ExplosionTemplate).ExplosionEffects); + } + + if( MyImpactEffect.ParticleTemplate != none ) + { + ExplosionTemplate.ExplosionSound = MyImpactEffect.Sound; + + } +} + +//Copied from KFExplosionActor -> SpawnExplosionDecal +//Added support to variable DecalSize depending on blood ball charge. +simulated function SpawnExplosionDecal() +{ + local MaterialInterface MI; + local MaterialInstanceTimeVarying MITV_Decal; + local int DecalMaterialsLength; + local float DecalSize, DecalThickness; + local KFGameExplosion KFExplosionTemplate; + + if( WorldInfo.bDropDetail ) + { + return; + } + + // If the template is none, grab the default + if( !ExplosionTemplate.bAllowPerMaterialFX ) + { + KFExplosionTemplate = KFGameExplosion(ExplosionTemplate); + if( KFExplosionTemplate == none || KFExplosionTemplate.ExplosionEffects == none ) + { + return; + } + + MyImpactEffect = KFExplosionTemplate.ExplosionEffects.DefaultImpactEffect; + } + + // if we have a decal to spawn on impact + DecalMaterialsLength = MyImpactEffect.DecalMaterials.length; + if( DecalMaterialsLength > 0 ) + { + MI = MyImpactEffect.DecalMaterials[Rand(DecalMaterialsLength)]; + if( MI != None ) + { + DecalSize = Lerp(ImpactDecalSizeMin, ImpactDecalSizeMax, ChargePercentage); + + //Always extend decal thickness for explosions + DecalThickness = DecalSize * 2.f; + + if( MaterialInstanceTimeVarying(MI) != none ) + { + MITV_Decal = new(self) class'MaterialInstanceTimeVarying'; + MITV_Decal.SetParent( MI ); + + WorldInfo.ExplosionDecalManager.SpawnDecal(MITV_Decal, ExplosionTemplate.HitLocation, rotator(-ExplosionTemplate.HitNormal), DecalSize, DecalSize, DecalThickness, FALSE,(MyImpactEffect.bNoDecalRotation) ? 0.f : (FRand() * 360.0) ); + //here we need to see if we are an MITV and then set the burn out times to occur + MITV_Decal.SetScalarStartTime( MyImpactEffect.DecalDissolveParamName, MyImpactEffect.DecalDuration ); + } + else + { + WorldInfo.ExplosionDecalManager.SpawnDecal( MI, ExplosionTemplate.HitLocation, rotator(-ExplosionTemplate.HitNormal), DecalSize, DecalSize, DecalThickness, true, + (MyImpactEffect.bNoDecalRotation) ? 0.f : (FRand() * 360.0),,,,,,, MyImpactEffect.DecalDuration ); + } + } + } +} + +DefaultProperties +{ + HealingDamageType=class'KFDT_Healing' + HealingAmount=0; + + fMinAmmoutHealing=12; //10; + fMaxAmmoutHealing=60; //50; + + ImpactDecalSizeMax=425.f + ImpactDecalSizeMin=178.f + + Interval=0 + MaxTime=0.0 + FadeOutTime=0.0 + + bExplodeMoreThanOnce=false + bDoFullDamage=false + + bOnlyDamagePawns=true + + bSkipLineCheckForPawns=true + + LoopStartEvent=none + LoopStopEvent=none + +//EXPERIMENTAL FEATURES FOR DESIGN + bHealsInstigator = false; + bHealsDifferentAmmoutToInstigator = false; + fAltMinAmmoutHealing=1; + fAltMaxAmmoutHealing=5; +} diff --git a/KFGameContent/Classes/KFPawn_ZedBloatKing.uc b/KFGameContent/Classes/KFPawn_ZedBloatKing.uc index c2fef0e..9733201 100644 --- a/KFGameContent/Classes/KFPawn_ZedBloatKing.uc +++ b/KFGameContent/Classes/KFPawn_ZedBloatKing.uc @@ -767,6 +767,16 @@ defaultproperties DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_AltFiremodeZapDamage', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.4))) + + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.25))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.5))) + + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.3))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) ParryResistance=4 diff --git a/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc b/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc index 761bf80..9466764 100644 --- a/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc +++ b/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc @@ -203,6 +203,9 @@ defaultproperties DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_BloatPukeMine', DamageScale=(0.00))) DamageTypeModifiers.Add((DamageType=class'KFDT_Toxic_BloatKingPukeMine', DamageScale=(0.00))) + //Special cases + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(2.0))) + diff --git a/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc b/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc index b879326..50bb9f4 100644 --- a/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc +++ b/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc @@ -675,6 +675,15 @@ DefaultProperties DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_AltFiremodeZapDamage', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.6))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.4))) + + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.5))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) Begin Object Class=KFGameExplosion Name=ExploTemplate0 Damage=40 //20 diff --git a/KFGameContent/Classes/KFPawn_ZedHans.uc b/KFGameContent/Classes/KFPawn_ZedHans.uc index 63ad944..50d1d76 100644 --- a/KFGameContent/Classes/KFPawn_ZedHans.uc +++ b/KFGameContent/Classes/KFPawn_ZedHans.uc @@ -1231,6 +1231,13 @@ DefaultProperties DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.6))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.9))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.5))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) + // --------------------------------------------- // Block Settings diff --git a/KFGameContent/Classes/KFPawn_ZedMatriarch.uc b/KFGameContent/Classes/KFPawn_ZedMatriarch.uc index 1266df0..d143a0a 100644 --- a/KFGameContent/Classes/KFPawn_ZedMatriarch.uc +++ b/KFGameContent/Classes/KFPawn_ZedMatriarch.uc @@ -1953,6 +1953,16 @@ defaultproperties DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.4))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.25))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.5))) + + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.3))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) + // --------------------------------------------- // Armor diff --git a/KFGameContent/Classes/KFPawn_ZedPatriarch.uc b/KFGameContent/Classes/KFPawn_ZedPatriarch.uc index b307b00..d7713ca 100644 --- a/KFGameContent/Classes/KFPawn_ZedPatriarch.uc +++ b/KFGameContent/Classes/KFPawn_ZedPatriarch.uc @@ -2188,6 +2188,15 @@ defaultproperties DamageTypeModifiers.Add((DamageType=class'KFDT_EMP_ArcGenerator_AltFiremodeZapDamage', DamageScale=(1.5))) DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRGScorcherLightingImpact', DamageScale=(0.4))) DamageTypeModifiers.Add((DamageType=class'KFDT_Fire_HRGScorcherDoT', DamageScale=(0.4))) + + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.3))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.25))) + //DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.5))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact', DamageScale=(0.4))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Piercing_HRG_Vampire_CrystalSpike', DamageScale=(0.3))) + DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) // --------------------------------------------- // Block Settings diff --git a/KFGameContent/Classes/KFProj_BloodBall_HRG_Vampire.uc b/KFGameContent/Classes/KFProj_BloodBall_HRG_Vampire.uc new file mode 100644 index 0000000..03b8eb7 --- /dev/null +++ b/KFGameContent/Classes/KFProj_BloodBall_HRG_Vampire.uc @@ -0,0 +1,297 @@ +//============================================================================= +// KFProj_BloodBall_HRG_Vampire +//============================================================================= +// Projectile class for Vampire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFProj_BloodBall_HRG_Vampire extends KFProjectile; + + +/** Storing all relative info about Blood Ball charged (in order to help in replication) */ +struct BloodBallChargeInfo +{ + var float ChargePercentage; + var float DamageByChargePercentage; +}; + +/** Dampen amount for every bounce */ +var float DampenFactor; + +/** Dampen amount for parallel angle to velocity */ +var float DampenFactorParallel; + +/** Vector to offset the ground FX particle system by when landing */ +var vector LandedFXOffset; + +/** Armed mine collision settings */ + +/** Decal settings */ +var MaterialInterface ImpactDecalMaterial; +var float ImpactDecalWidth; +var float ImpactDecalHeight; +var float ImpactDecalThickness; + +var float MaxExplodeTriggerHeightPerPercentage; +var float MinExplodeTriggerHeightPerPercentage; + +var float MaxDamageRadiusPerPercentage; +var float MinDamageRadiusPerPercentage; + +var float MaxCollisionRadius; +var float MinCollisionRadius; +var float MaxCollisionHeight; +var float MinCollisionHeight; + +var float MaxDamagePerPercentage; +var float MinDamagePerPercentage; + +var repnotify BloodBallChargeInfo BloodBallCharge; + +var float fCachedCylinderWidth, fCachedCylinderHeight; + +//EXPERIMENTAL FEATURES +var bool bCantBeTouchedByInstigator; +var bool bManuallyDetonated; +var bool bCantDetonateOnFullHP; + +replication +{ + if( bNetDirty && Role == Role_Authority) + BloodBallCharge; +} + +simulated event ReplicatedEvent( name VarName ) +{ + super.ReplicatedEvent( VarName ); + + if( VarName == nameOf(BloodBallCharge)) + { + ScalingExplosionTemplateByBloodBallCharge(); + ScalingProjEffectsByBloodBallCharge(); + } +} + +simulated function SetInheritedScale(float NewChargePercentage, float NewDamageByChargePercentage) +{ + BloodBallCharge.DamageByChargePercentage=NewDamageByChargePercentage; + BloodBallCharge.ChargePercentage = FMax(0.1, NewChargePercentage);//We want to see at least a bit of the projectile. + + ScalingExplosionTemplateByBloodBallCharge(); + ScalingProjEffectsByBloodBallCharge(); + + bNetDirty=true; +} + +simulated function ScalingExplosionTemplateByBloodBallCharge() +{ + fCachedCylinderWidth = Lerp(MinCollisionRadius, MaxCollisionRadius, BloodBallCharge.ChargePercentage); + fCachedCylinderHeight = Lerp(MinCollisionHeight, MaxCollisionHeight, BloodBallCharge.ChargePercentage); + CylinderComponent(CollisionComponent).SetCylinderSize(fCachedCylinderWidth, fCachedCylinderHeight); + + ExplosionTemplate.DamageRadius = FMax(MinDamageRadiusPerPercentage, Lerp(MinDamageRadiusPerPercentage, MaxDamageRadiusPerPercentage, BloodBallCharge.DamageByChargePercentage)); + ExplosionTemplate.Damage = FMax(MinDamagePerPercentage, Lerp(MinDamagePerPercentage, MaxDamagePerPercentage, BloodBallCharge.DamageByChargePercentage)); +} + +simulated function ScalingProjEffectsByBloodBallCharge() +{ + local vector ChargePercentageVector; + ChargePercentageVector.X = BloodBallCharge.ChargePercentage; + ChargePercentageVector.Y = BloodBallCharge.ChargePercentage; + ChargePercentageVector.Z = BloodBallCharge.ChargePercentage; + + if(ProjEffects != None) + { + ProjEffects.SetVectorParameter( name("BlobCharge"), ChargePercentageVector); + ProjEffects.SetFloatParameter( name("MineFxControlParam"), BloodBallCharge.ChargePercentage); + } +} + + + + +simulated event PostBeginPlay() +{ + super.PostBeginPlay(); + + BloodBallCharge.ChargePercentage=0; + BloodBallCharge.DamageByChargePercentage=0; +} + +simulated function SpawnFlightEffects() +{ + super.SpawnFlightEffects(); +} + +/** Validates a touch */ + + +simulated protected function PrepareExplosionTemplate() +{ + + local Weapon OwnerWeapon; + local Pawn OwnerPawn; + + super(KFProjectile).PrepareExplosionTemplate(); + OwnerWeapon = Weapon(Owner); + if (OwnerWeapon != none) + { + OwnerPawn = Pawn(OwnerWeapon.Owner); + if (OwnerPawn != none) + { + ExplosionTemplate.DamageRadius *= KFPawn(OwnerPawn).GetPerk().GetAoERadiusModifier(); + } + } +} + +simulated protected function PrepareExplosionActor(GameExplosionActor GEA) +{ + KFExplosion_HRG_Vampire_BloodBall(GEA).ChargePercentage = BloodBallCharge.ChargePercentage; + KFExplosion_HRG_Vampire_BloodBall(GEA).DamageByChargePercentage = BloodBallCharge.DamageByChargePercentage; + super.PrepareExplosionActor(GEA); +} + +/** Call ProcessBulletTouch */ +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + if (Other == Instigator || CheckRepeatingTouch(Other)) + { + return; + } + + if (IgnoreTouchActor != Other) + { + ProcessBulletTouch(Other, HitLocation, HitNormal); + } + super.ProcessTouch(Other, HitLocation, HitNormal); +} + +defaultproperties +{ + Speed=2000 + MaxSpeed=2000 + TerminalVelocity=2000 + TossZ=150 + GravityScale=0.5 + MomentumTransfer=50000.0 + + LifeSpan=300 + PostExplosionLifetime=1 + Physics=PHYS_Falling + bBounce=true + + ProjFlightTemplate= ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_BlobProjectile_01' + ExplosionActorClass=class'KFExplosion_HRG_Vampire_BloodBall' + + bSuppressSounds=false + bAmbientSoundZedTimeOnly=false + bAutoStartAmbientSound=false + bStopAmbientSoundOnExplode=true + + AmbientSoundPlayEvent=None + AmbientSoundStopEvent=None + + Begin Object Class=AkComponent name=AmbientAkSoundComponent + bStopWhenOwnerDestroyed=true + bForceOcclusionUpdateInterval=true + OcclusionUpdateInterval=0.25f + End Object + AmbientComponent=AmbientAkSoundComponent + Components.Add(AmbientAkSoundComponent) + + //ImpactDecalMaterial=DecalMaterial'FX_Mat_Lib.FX_Puke_Mine_Splatter_DM' + ImpactDecalWidth=178.f + ImpactDecalHeight=178.f + ImpactDecalThickness=28.f + + Begin Object Name=CollisionCylinder + CollisionRadius=10.f + CollisionHeight=10.f + CollideActors=true + //PhysMaterialOverride=PhysicalMaterial'WEP_Mine_Reconstructor_EMIT.BloatPukeMine_PM' + End Object + + bCollideActors=true + bProjTarget=true + bCanBeDamaged=false + bCollideComplex=true + bNoEncroachCheck=true + bPushedByEncroachers=false + DampenFactor=0.125f + DampenFactorParallel=0.175f + + LandedFXOffset=(X=0,Y=0,Z=2) + + // Since we're still using an extent cylinder, we need a line at 0 + ExtraLineCollisionOffsets.Add(()) + + // Explosion + Begin Object Class=KFGameExplosion Name=ExploTemplate0 + Damage=200 + DamageRadius=200 + DamageFalloffExponent=0.5f + DamageDelay=0.f + MyDamageType=class'KFDT_Toxic_HRG_Vampire_BloodBall' + //bIgnoreInstigator is set to true in PrepareExplosionTemplate + + //Impulse applied to Zeds + MomentumTransferScale=45000 + + // Damage Effects + KnockDownStrength=0 + KnockDownRadius=0 + FractureMeshRadius=0 + FracturePartVel=0 + ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Vampire_Arch.HRG_Vampire_BlobFireImpacts' + ExplosionSound=None + bAllowPerMaterialFX=true + //MomentumTransferScale=0 + + // Dynamic Light + ExploLight=none + + // Camera Shake + CamShake=CameraShake'WEP_Mine_Reconstructor_Arch.Camera_Shake' + CamShakeInnerRadius=200 + CamShakeOuterRadius=400 + CamShakeFalloff=1.f + bOrientCameraShakeTowardsEpicenter=true + + End Object + ExplosionTemplate=ExploTemplate0 + + GlassShatterType=FMGS_ShatterAll + + + MaxExplodeTriggerHeightPerPercentage=22 + MinExplodeTriggerHeightPerPercentage=11 + + MaxDamageRadiusPerPercentage=280 //340 + MinDamageRadiusPerPercentage=130 //160 + + MaxDamagePerPercentage=200 //150 + MinDamagePerPercentage=20 //15 + + MaxCollisionRadius=20 + MinCollisionRadius=10 + MaxCollisionHeight=20 + MinCollisionHeight=10 + + bBlockedByInstigator=true + bNetTemporary=false + + bSyncToOriginalLocation=true + bSyncToThirdPersonMuzzleLocation=true + bUseClientSideHitDetection=true + bUpdateSimulatedPosition=false + + TouchTimeThreshhold=0.05 + + //EXPERIMENTAL FEATURES FOR DESING + bManuallyDetonated=false + bCantBeTouchedByInstigator=true + bCantDetonateOnFullHP=true + + AssociatedPerkClass=class'KFPerk_FieldMedic' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFProj_BloodSplash.uc b/KFGameContent/Classes/KFProj_BloodSplash.uc new file mode 100644 index 0000000..b8f06db --- /dev/null +++ b/KFGameContent/Classes/KFProj_BloodSplash.uc @@ -0,0 +1,247 @@ +//============================================================================= +// KFProj_Blood Splash +//============================================================================= +// Projectile class for blood splashes that can leave decals. +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFProj_BloodSplash extends KFProjectile; + + +var DecalMaterial ImpactDecalMaterial; +var float ImpactDecalMaxSize; +var float ImpactDecalMinSize; +var float ImpactDecalThickness; + +var KFPawn BloodOriginPawn; + +/** Blow up on impact */ +simulated event HitWall(vector HitNormal, Actor Wall, PrimitiveComponent WallComp) +{ + if( StaticMeshComponent(WallComp) != none && StaticMeshComponent(WallComp).CanBecomeDynamic() ) + { + // pass through meshes that can move + return; + } + + SpawnBloodDecal(Location, HitNormal); + + //Explode( Location, HitNormal ); +} + +/** Blow up on impact */ +simulated function ProcessTouch( Actor Other, Vector HitLocation, Vector HitNormal ) +{ + if( Other.bBlockActors ) + { + // don't hit pawns because we don't want to see floating flames when the victim pawn dies + if ( Pawn(Other) != None ) + { + return; + } + + // don't hit client-side destructible actors + // @todo: maybe don't hit any destructibles for the same reason we don't hit pawns (floating flames when destroyed)? + if( KFDestructibleActor(Other) != none && KFDestructibleActor(Other).ReplicationMode == RT_ClientSide ) + { + return; + } + + //Explode( Location, HitNormal ); + SpawnBloodDecal(Location, HitNormal); + + } +} + +/** Overridden to adjust particle system for different surface orientations (wall, ceiling) + * and nudge location + */ +simulated protected function PrepareExplosionActor(GameExplosionActor GEA) +{ + /* + local KFExplosion_Molotov KFEM; + local vector ExplosionDir; + + super.PrepareExplosionActor( GEA ); + + // KFProjectile::Explode gives GEA a "nudged" location of 32 units, but it's too much, so use a smaller nudge + GEA.SetLocation( Location + vector(GEA.Rotation) * 10 ); + + KFEM = KFExplosion_Molotov( GEA ); + if( KFEM != none ) + { + ExplosionDir = vector( KFEM.Rotation ); + + if( ExplosionDir.Z < -0.95 ) + { + // ceiling + KFEM.LoopingParticleEffect = KFEM.default.LoopingParticleEffectCeiling; + } + else if( ExplosionDir.Z < 0.05 ) + { + // wall + KFEM.LoopingParticleEffect = KFEM.default.LoopingParticleEffectWall; + } + // else floor + } + */ +} + +simulated function SpawnBloodDecal(vector HitLocation, vector HitNormal ) +{ + local KFGoreManager GoreManager; + + // Grab the gore manager + GoreManager = KFGoreManager(WorldInfo.MyGoreEffectManager); + + if (GoreManager == none || BloodOriginPawn == none) + { + return; + } + + GoreManager.LeaveABloodSplatterDecal(BloodOriginPawn, HitLocation, Normal(Velocity)); + + //GoreManager. LeaveAPersistentBloodSplat(HitLocation, HitNormal, 1.0); + + if (KFPawn_Monster(BloodOriginPawn) != none) + { + GoreManager.CausePersistentBlood(KFPawn_Monster(BloodOriginPawn), class'KFDamageType', HitLocation, Normal(Velocity), 0, false, false); + } +} +/** +* Use alternative explosion effects when Ground Fire Perk is active +*/ +simulated function PostBeginPlay() +{ + /* + local KFPlayerReplicationInfo InstigatorPRI; + + if( AltExploEffects != none && Instigator != none ) + { + InstigatorPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + if( InstigatorPRI != none ) + { + bAltExploEffects = InstigatorPRI.bSplashActive; + } + } + else + { + bAltExploEffects = false; + } + + super.PostBeginPlay(); + */ +} + +/** + * Force the fire not to burn the instigator, since setting it in the default props is not working for some reason - Ramm + * Use the alternative FX for the Ground Fire Perk Skill - Tulio + */ +simulated protected function PrepareExplosionTemplate() +{ + /* + ExplosionTemplate.bIgnoreInstigator=true; + super.PrepareExplosionTemplate(); + + if( bAltExploEffects ) + { + ExplosionTemplate.ExplosionEffects = AltExploEffects; + } + */ +} + +defaultproperties +{ + Physics=PHYS_Falling + + bCollideComplex=TRUE // Ignore simple collision on StaticMeshes, and collide per poly + + // network + bNetTemporary=False + bAlwaysReplicateExplosion=true + AlwaysRelevantDistanceSquared=6250000 // 25m + + // gameplay + bBlockedByInstigator=false + GlassShatterType=FMGS_ShatterNone + + // audio + bStopAmbientSoundOnExplode=false + bAutoStartAmbientSound=false + bAmbientSoundZedTimeOnly=false + + AmbientSoundPlayEvent=None + AmbientSoundStopEvent=None + + /* + Begin Object Class=AkComponent name=AmbientAkSoundComponent + bStopWhenOwnerDestroyed=true + bForceOcclusionUpdateInterval=true + OcclusionUpdateInterval=0.25; + End Object + AmbientComponent=AmbientAkSoundComponent + Components.Add(AmbientAkSoundComponent) + */ + + // light + /* + Begin Object Class=PointLightComponent Name=FlamePointLight + LightColor=(R=245,G=190,B=140,A=255) + Brightness=2.f + Radius=300.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=10 + DamageRadius=150 + DamageFalloffExponent=1.f + DamageDelay=0.f + // Don't burn the guy that tossed it, it's just too much damage with multiple fires, its almost guaranteed to kill the guy that tossed it + bIgnoreInstigator=true + + MomentumTransferScale=1 + + // Damage Effects + MyDamageType=class'KFDT_Fire_Ground_MolotovGrenade' + KnockDownStrength=0 + FractureMeshRadius=0 + ExplosionEffects=KFImpactEffectInfo'wep_molotov_arch.Molotov_GroundFire' + + bDirectionalExplosion=true + + // Camera Shake + CamShake=none + + // Dynamic Light + ExploLight=FlamePointLight + ExploLightStartFadeOutTime=4.2 + ExploLightFadeOutTime=0.3 + End Object + ExplosionTemplate=ExploTemplate0 + */ + + ProjFlightTemplate=None + //ExplosionActorClass=class'KFExplosion_Molotov' + + AssociatedPerkClass=None + + ImpactDecalMaterial=DecalMaterial'FX_Mat_Lib.FX_CH_BloodSplatter_DM' + ImpactDecalMaxSize=125.f + ImpactDecalMinSize=75.f + ImpactDecalThickness=12.f + + // Ground Fire Perk Skill Alternative FX + //AltExploEffects=KFImpactEffectInfo'WEP_Flamethrower_ARCH.GroundFire_Splash_Impacts' +} diff --git a/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc b/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc index 78fc430..84e7637 100644 --- a/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc +++ b/KFGameContent/Classes/KFProj_BrokenFlare_HRGScorcher.uc @@ -259,5 +259,7 @@ defaultproperties End Object ExplosionTemplate=ExploTemplate0 ExplosionActorClass=class'KFExplosionActor' + + bDamageDestructiblesOnTouch=true } diff --git a/KFGameContent/Classes/KFProj_Bullet_Frost_Shotgun_Axe.uc b/KFGameContent/Classes/KFProj_Bullet_Frost_Shotgun_Axe.uc new file mode 100644 index 0000000..9a50987 --- /dev/null +++ b/KFGameContent/Classes/KFProj_Bullet_Frost_Shotgun_Axe.uc @@ -0,0 +1,42 @@ +//============================================================================= +// KFProj_Bullet_Frost_Shotgun_Axe +//============================================================================= +// Bullet class for the Frost_Shotgun_Axe +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFProj_Bullet_Frost_Shotgun_Axe extends KFProj_Bullet_Pellet + hidedropdown; + +var AkEvent oFrozenSound; + +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + local KFPawn p; + p = KFPawn(Other); + super.ProcessTouch(Other, HitLocation, HitNormal); + if(p != none) + { + if(KFPawn_Monster(p).IsDoingSpecialMove(SM_Frozen)) + { + p.PlayAkEvent(oFrozenSound); + } + } +} + +defaultproperties +{ + MaxSpeed=7000 //24000.0 + Speed=7000 //24000.0 + + DamageRadius=0 + + ProjFlightTemplate=ParticleSystem'WEP_Frost_Shotgun_Axe_EMIT.FX_FrostFang_Tracer_01' + ProjFlightTemplateZedTime=ParticleSystem'WEP_Frost_Shotgun_Axe_EMIT.FX_FrostFang_Tracer_Zedtime_01' + ImpactEffects=KFImpactEffectInfo'WEP_Frost_Shotgun_Axe_ARCH.WEP_FrostFang_Projectile_Impact' + oFrozenSound=AkEvent'WW_WEP_SA_CompoundBow.Play_Arrow_Impact_Cryo' + AssociatedPerkClass=class'KFPerk_Support' +} + diff --git a/KFGameContent/Classes/KFProj_Bullet_Pistol_ChiappaRhino.uc b/KFGameContent/Classes/KFProj_Bullet_Pistol_ChiappaRhino.uc index 3070080..b65f6ad 100644 --- a/KFGameContent/Classes/KFProj_Bullet_Pistol_ChiappaRhino.uc +++ b/KFGameContent/Classes/KFProj_Bullet_Pistol_ChiappaRhino.uc @@ -19,12 +19,13 @@ defaultproperties ProjFlightTemplate=ParticleSystem'FX_Projectile_EMIT.FX_Tracer_9MM_ZEDTime' bSpawnShrapnel=true - //bDebugShrapnel=true + bDebugShrapnel=false + NumSpawnedShrapnel=3 - ShrapnelSpreadWidthEnvironment=0.5 - ShrapnelSpreadHeightEnvironment=0.5 - ShrapnelSpreadWidthZed=0.5 - ShrapnelSpreadHeightZed=0.5 + ShrapnelSpreadWidthEnvironment=0.25 //0.5 + ShrapnelSpreadHeightEnvironment=0.25 //0.5 + ShrapnelSpreadWidthZed=0.75 //0.5 + ShrapnelSpreadHeightZed=0.75 //0.5 ShrapnelClass = class'KFProj_Bullet_Pistol_ChiappaRhinoShrapnel' ShrapnelSpawnSoundEvent = AkEvent'WW_WEP_ChiappaRhinos.Play_WEP_ChiappaRhinos_Bullet_Fragmentation' ShrapnelSpawnVFX=ParticleSystem'WEP_ChiappaRhino_EMIT.FX_ChiappaRhino_Shrapnel_Hit' diff --git a/KFGameContent/Classes/KFProj_CrystalSpike_HRG_Vampire.uc b/KFGameContent/Classes/KFProj_CrystalSpike_HRG_Vampire.uc new file mode 100644 index 0000000..9765047 --- /dev/null +++ b/KFGameContent/Classes/KFProj_CrystalSpike_HRG_Vampire.uc @@ -0,0 +1,63 @@ +//============================================================================= +// KFProj_CrystalSpike_HRG_Vampire +//============================================================================= +// Bullet class for the HRG Vampire crystal spikes. +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +// +//============================================================================= + +class KFProj_CrystalSpike_HRG_Vampire extends KFProj_Bullet + hidedropdown; + + +simulated function ProcessBulletTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + super.ProcessBulletTouch(Other, HitLocation, HitNormal); + + if( WorldInfo.NetMode != NM_DedicatedServer ) + { + if ( Other.IsA('Pawn') && Other.bCanBeDamaged) + { + WorldInfo.MyEmitterPool.SpawnEmitter(ImpactEffects.DefaultImpactEffect.ParticleTemplate, HitLocation, rotator(HitNormal), Other); + PlaySoundBase(ImpactEffects.DefaultImpactEffect.Sound, true,,, HitLocation); + } + } +} + +defaultproperties +{ + bWarnAIWhenFired=true + + MaxSpeed=12000.0 //15000.0 + Speed=12000.0 ///15000.0 + TerminalVelocity=12000.0 //15000.0 + + DamageRadius=0 + + ProjFlightTemplate=ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_Projectile_ALT' + + LifeSpan=10 + + bBlockedByInstigator=false + bCollideActors=true + bCollideComplex=true + bNoEncroachCheck=true + bNoReplicationToInstigator=false + bUseClientSideHitDetection=true + bUpdateSimulatedPosition=false + bRotationFollowsVelocity=false + bNetTemporary=false + bSyncToOriginalLocation=true + + ImpactEffects = KFImpactEffectInfo'WEP_HRG_Vampire_Arch.HRG_Vampire_SpikeFireImpacts' + + AmbientSoundPlayEvent=None + AmbientSoundStopEvent=None + + TouchTimeThreshhold=0.15 + + AssociatedPerkClass=class'KFPerk_FieldMedic' +} + diff --git a/KFGameContent/Classes/KFProj_Explosive_HRG_Kaboomstick.uc b/KFGameContent/Classes/KFProj_Explosive_HRG_Kaboomstick.uc index 3a3ee74..dc8f954 100644 --- a/KFGameContent/Classes/KFProj_Explosive_HRG_Kaboomstick.uc +++ b/KFGameContent/Classes/KFProj_Explosive_HRG_Kaboomstick.uc @@ -142,7 +142,7 @@ defaultproperties FractureMeshRadius=200.0 FracturePartVel=500.0 //ExplosionEffects=KFImpactEffectInfo'WEP_HX25_Pistol_ARCH.HX25_Pistol_Submunition_Explosion' - ExplosionSound=AkEvent'WW_WEP_SA_HX25.Play_WEP_SA_HX25_Explosion' + ExplosionSound=AkEvent'ww_wep_hrg_kaboomstick.WEP_HRG_Kaboomstick_Projectile_Explo' ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Kaboomstick_ARCH.WEP_HRG_Kaboomstick_Explosion' //ExplosionSound=AkEvent'WW_WEP_Seeker_6.Play_WEP_Seeker_6_Explosion' diff --git a/KFGameContent/Classes/KFProj_MedicGrenade_Mini.uc b/KFGameContent/Classes/KFProj_MedicGrenade_Mini.uc index c6f9264..9deafcc 100644 --- a/KFGameContent/Classes/KFProj_MedicGrenade_Mini.uc +++ b/KFGameContent/Classes/KFProj_MedicGrenade_Mini.uc @@ -27,6 +27,7 @@ simulated event HitWall(vector HitNormal, actor Wall, PrimitiveComponent WallCom * Returns true if projectile actually bounced / was allowed to bounce */ simulated function bool Bounce( vector HitNormal, Actor BouncedOff ) { + SetLocation(Location + HitNormal); super.Bounce(HitNormal, BouncedOff); // stop and drop diff --git a/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc b/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc index a3049f2..27900a4 100644 --- a/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc +++ b/KFGameContent/Classes/KFProj_Mine_Reconstructor.uc @@ -29,9 +29,6 @@ var float DampenFactor; /** Dampen amount for parallel angle to velocity */ var float DampenFactorParallel; -/** How much to offset the mine when spawning inside of collision */ -var float SpawnCollisionOffsetAmt; - /** Vector to offset the ground FX particle system by when landing */ var vector LandedFXOffset; @@ -175,8 +172,6 @@ simulated function SetInheritedScale(float Scale, float ChargePercentage) /** Adds our puke mine to the pool */ simulated event PostBeginPlay() { - local vector Hitlocation, HitNormal; - // Cache team num TeamNum = GetTeamNum(); @@ -197,13 +192,6 @@ simulated event PostBeginPlay() if( Role == ROLE_Authority ) { - // If we're spawning in collision for some reason, offset it towards the instigator to keep it in play - Instigator.Trace( HitLocation, HitNormal, Location, Instigator.Location, false,,, TRACEFLAG_Bullet ); - if( !IsZero(HitLocation) ) - { - SetLocation( HitLocation + HitNormal*SpawnCollisionOffsetAmt ); - } - SetTimer( FuseDuration, false, nameOf(Timer_Explode) ); } } @@ -864,8 +852,6 @@ defaultproperties // Since we're still using an extent cylinder, we need a line at 0 ExtraLineCollisionOffsets.Add(()) - SpawnCollisionOffsetAmt=28.f - // Collision size we should use when waiting to be triggered ExplodeTriggerRadius=60.f ExplodeTriggerHeight=22.f diff --git a/KFGameContent/Classes/KFSeasonalEventStats_Xmas2020.uc b/KFGameContent/Classes/KFSeasonalEventStats_Xmas2020.uc new file mode 100644 index 0000000..371f4c2 --- /dev/null +++ b/KFGameContent/Classes/KFSeasonalEventStats_Xmas2020.uc @@ -0,0 +1,110 @@ +//============================================================================= +// KFSeasonalEventStats_Xmas2020 +//============================================================================= +// Tracks event-specific challenges/accomplishments for Xmas 2020 +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFSeasonalEventStats_Xmas2020 extends KFSeasonalEventStats; + +var transient private const int RosesRequired, TomesRequired, EndlessWaveRequired, XmasEventIndex; + +private event Initialize(string MapName) +{ + local string CapsMapName; + CapsMapName = Caps(MapName); + + bObjectiveIsValidForMap[0] = 0; // Collect 3 roses in Elysium + bObjectiveIsValidForMap[1] = 0; // Collect 4 tomes in Elysium + bObjectiveIsValidForMap[2] = 0; // Complete one wave in Elysium's Botanica arena + bObjectiveIsValidForMap[3] = 0; // Complete one wave in Elysium's Loremaster Sanctum arena + bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Elysium + + if (CapsMapName == "KF-ELYSIUM") + { + bObjectiveIsValidForMap[0] = 1; + bObjectiveIsValidForMap[1] = 1; + bObjectiveIsValidForMap[2] = 1; + bObjectiveIsValidForMap[3] = 1; + bObjectiveIsValidForMap[4] = 1; + } + + SetSeasonalEventStatsMax(RosesRequired, TomesRequired, 0, 0, 0); +} + +private event GrantEventItems() +{ + if (Outer.IsEventObjectiveComplete(0) && + Outer.IsEventObjectiveComplete(1) && + Outer.IsEventObjectiveComplete(2) && + Outer.IsEventObjectiveComplete(3) && + Outer.IsEventObjectiveComplete(4)) + { + GrantEventItem(8608); + } +} + +simulated function OnTryCompleteObjective(int ObjectiveIndex, int EventIndex) +{ + local int ObjIdx; + + // Collect 3 roses in Elysium + ObjIdx = 0; + if (bObjectiveIsValidForMap[ObjIdx] != 0 && ObjectiveIndex == ObjIdx && EventIndex == XmasEventIndex) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= RosesRequired) + { + FinishedObjective(XmasEventIndex, ObjIdx); + } + } + + // Collect 4 tomes in Elysium + ObjIdx = 1; + if (bObjectiveIsValidForMap[ObjIdx] != 0 && ObjectiveIndex == ObjIdx && EventIndex == XmasEventIndex) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= TomesRequired) + { + FinishedObjective(XmasEventIndex, ObjIdx); + } + } + + // Complete one wave in Elysium's Botanica arena + ObjIdx = 2; + if (bObjectiveIsValidForMap[ObjIdx] != 0 && ObjectiveIndex == ObjIdx && EventIndex == XmasEventIndex) + { + FinishedObjective(XmasEventIndex, ObjIdx); + } + + // Complete one wave in Elysium's Loremaster Sanctum arena + ObjIdx = 3; + if (bObjectiveIsValidForMap[ObjIdx] != 0 && ObjectiveIndex == ObjIdx && EventIndex == XmasEventIndex) + { + FinishedObjective(XmasEventIndex, ObjIdx); + } +} + +simulated event OnWaveCompleted(class GameClass, int Difficulty, int WaveNum) +{ + local int ObjIdx; + + // Complete wave 15 on Endless Hard or higher difficulty on Elysium + ObjIdx = 4; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD) + { + FinishedObjective(XmasEventIndex, ObjIdx); + } + } +} + +defaultproperties +{ + RosesRequired=3 + TomesRequired=4 + EndlessWaveRequired=15 + XmasEventIndex=SEI_Winter +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFSeqAct_ProgressSeasonalObjective.uc b/KFGameContent/Classes/KFSeqAct_ProgressSeasonalObjective.uc new file mode 100644 index 0000000..2ace16f --- /dev/null +++ b/KFGameContent/Classes/KFSeqAct_ProgressSeasonalObjective.uc @@ -0,0 +1,56 @@ +//============================================================================= +// KFSeqAct_ProgressSeasonalObjective +//============================================================================= +// Sequence action to allow a map to have add progress to seasonal objectives +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= + +class KFSeqAct_ProgressSeasonalObjective extends SequenceAction; + +/** Objective index for the event this is tied to */ +var() int ObjectiveIndex; + +/** Index of the event this is tied to */ +var() int EventIndex; + +/** Increment progress for all players? */ +var() bool bAllPlayersAffected; + +event Activated() +{ + local KFPlayercontroller KFPC; + local bool bIsObjectiveDataValid; + + bIsObjectiveDataValid = ObjectiveIndex >= 0 && ObjectiveIndex < 5 && EventIndex > SEI_None && EventIndex < SEI_MAX; + + if (bAllPlayersAffected) + { + foreach GetWorldInfo().AllControllers(class'KFPlayerController', KFPC) + { + if(bIsObjectiveDataValid) + { + KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex); + } + } + } + else + { + KFPC = KFPlayerController(GetWorldInfo().GetALocalPlayerController()); + if(bIsObjectiveDataValid) + { + KFPC.ClientOnTryCompleteObjective(ObjectiveIndex, EventIndex); + } + } +} + +defaultproperties +{ + ObjName="Progress Seasonal Objective" + ObjCategory="Killing Floor" + + ObjectiveIndex=-1 + EventIndex=-1 + bAllPlayersAffected=true +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFSprayActor_HRG_Vampire.uc b/KFGameContent/Classes/KFSprayActor_HRG_Vampire.uc new file mode 100644 index 0000000..6d9ba8c --- /dev/null +++ b/KFGameContent/Classes/KFSprayActor_HRG_Vampire.uc @@ -0,0 +1,749 @@ +//============================================================================= +// KFSprayActor_HRG_Vampire +//============================================================================= +// Base class for spray actor that sucks enemies blood +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= +class KFSprayActor_HRG_Vampire extends KFSprayActor + hidecategories(Object, Movement, Display, Attachment, Collision, Physics, Advanced, Debug, Mobile) + placeable; + + +/** Transient PSCs to workaround issue with setting the BonePSC in an archetype */ +var transient array BoneChainComponents; +var transient array BoneChainComponents_1stP; + +/** Firebug Perk can modify the flame length, we need an alternative anim for that */ +var(SprayMesh) AnimSet AltSprayAnimSet; + +var(SuckerConfig) int MaxNumberOfZedsZapped; +var(SuckerConfig) int MaxDistanceToBeZapped; +var(SuckerConfig) float ZapInterval; +var(SuckerConfig) int ChainDamage; + +var KFWeap_HRG_Vampire OwnerWeapon; + +/*************************************** + + INHERITED FROM SPRAY AND NOT MODIFIED + + ***************************************/ + +event PreBeginPlay() +{ + super.PreBeginPlay(); + SetBoneChainComponents(); +} + +/** + * Set (or create) PSC's for the BoneChain. Use this when creating an archetype template spray + * effect to workaround an issue where assigning a transient default BoneChain PSC doesn't work. + */ +simulated function SetBoneChainComponents() +{ + local int Idx; + + for (Idx = 0; Idx < BoneChain.length; ++Idx) + { + if ( Idx < BoneChainComponents.Length ) + { + BoneChain[Idx].BonePSC0 = BoneChainComponents[Idx]; + } + if ( Idx < BoneChainComponents_1stP.Length ) + { + BoneChain[Idx].BonePSC1 = BoneChainComponents_1stP[Idx]; + } + } +} + + + +simulated function BeginSpray() +{ + local KFPerk InstigatorPerk; + + if( bDeleteMe ) + { + return; + } + + super.BeginSpray(); + + if( OwningKFPawn != none ) + { + InstigatorPerk = OwningKFPawn.GetPerk(); + if( InstigatorPerk != none ) + { + SplashDamage = default.SplashDamage; + } + + //SetSprayLength(); + } +} + +/*************************************** + + END INHERITED FROM SPRAY AND NOT MODIFIED + + ***************************************/ + + +/** + * Overridden to handle the rotation sound pitching for the flamethrower sound + */ +simulated event Tick(float DeltaTime) +{ + super.Tick(DeltaTime); + + // Set the rotation speed for the flamethrower sound + if( !bDetached && OwningKFPawn != none && WorldInfo.NetMode != NM_DedicatedServer ) + { + OwningKFPawn.SetWeaponComponentRTPCValue( "FlamethrowerRotation", RotationSpeed); + } +} + +simulated function CleanupEndFire() +{ + super.CleanupEndFire(); + SprayMeshExitCollision(); +} + + +simulated event SprayMeshHit(Actor _TouchActor) +{ + local KFPawn_Monster TouchActor; + //if (Role == ROLE_Authority) + //{ + //`Warn("TOUCHED IN: "$_TouchActor.Location$""); + //if the sprayed actor is a monster, then we start zapping enemies + + if(_TouchActor.IsA('KFPawn_Monster')) + { + TouchActor = KFPawn_Monster(_TouchActor); + if(OwnerWeapon != none && TouchActor != OwnerWeapon.oZedCurrentlyBeingSprayed) + { + OwnerWeapon.SetCurrentSprayedZed(TouchActor); + } + } + else + { + SprayMeshExitCollision(); + } + + //} + /*if (!CheckRecentlyZapped(_TouchActor)) + { + NewActorInfo.HitActor = _TouchActor; + NewActorInfo.HitTime = WorldInfo.TimeSeconds; + vRecentlyZappedActors.AddItem(NewActorInfo); + }*/ + + super.SprayMeshHit(_TouchActor); +} + + + +simulated event SprayMeshExitCollision() +{ + if (OwnerWeapon == none) + { + return; + } + OwnerWeapon.SetCurrentSprayedZed(none); +} +/** + * @brief Changes the flame's length if the Firebug's Range skill is selected + * + * @param InstigatorPerk Instigator's current perk + */ +/*simulated function SetSprayLength() +{ + local AnimSet TempAnimSet; + local KFPlayerReplicationInfo OwningPawnPRI; + + if ( default.AltSprayAnimSet == None ) + { + return; // only once length available + } + + // Firebug range skill can affect the flame weapons range + OwningPawnPRI = KFPlayerReplicationInfo(OwningKFPawn.PlayerReplicationInfo); + if( OwningPawnPRI != none ) + { + TempAnimSet = OwningPawnPRI.bExtraFireRange ? default.AltSprayAnimSet : default.SprayAnimSet; + } + + // Don't set the anim set to nothing if the archetype is screwed up + // Don't set the anim set and tree if they do not need to be changed + if( TempAnimSet == none || TempAnimSet == SkeletalSprayMesh.AnimSets[0] ) + { + return; + } + + SkeletalSprayMesh.AnimSets[0] = TempAnimSet; + SkeletalSprayMesh.UpdateAnimations(); + SetupFX(); +}*/ + +DefaultProperties +{ + Physics=PHYS_Interpolating + TickGroup=TG_PostAsyncWork + bStatic=false + bCollideActors=TRUE + bBlockActors=false + bWorldGeometry=false + // This must not be bCollideWorld or it will get pushed around in FarMoveActor + bCollideWorld=false + bProjTarget=false + bIgnoreEncroachers=FALSE + bNoEncroachCheck=TRUE + RemoteRole=ROLE_None + GravityScaleRange=(X=0.f,Y=-15.f) + GravityScaleInTime=0.5f + MomentumScale=0.15f + MyDamageType=class'KFDT_EMP' + + // --------------------------------------------- + // Splash damage + SplashGlancingDotLimit=-0.9f + SplashRotInterpSpeed=8.f + SplashLocInterpSpeed=40.f + bDoCollideComplex=TRUE + SprayDamageScaleDistRange=(X=300,Y=300) + SprayDamage=(X=10,Y=10) + SplashDamageRadius=300.f + SplashDamage=10 + SplashDamageFalloffExponent=1.f + + // --------------------------------------------- + // Per-bone Fire FX + PerBoneSprayFXGlobalScale=1.f + bDoPerBoneSprayFX=TRUE + + // --------------------------------------------- + // Material params + MaterialHeatRampTime=0.65f + MaterialHeatRange=(X=0.f,Y=0.8f) + MaterialFadeOutTime=0.2f + MaterialCurrentFadeVal=1.f + MatFadePow=2.f + + // --------------------------------------------- + // Content + Begin Object Class=KFSkeletalMeshComponent Name=FlameCore0 + CollideActors=true + BlockActors=false + BlockZeroExtent=true + BlockNonZeroExtent=true + bUpdateSkelWhenNotRendered=TRUE + bIgnoreControllersWhenNotRendered=FALSE + bOverrideAttachmentOwnerVisibility=TRUE + CastShadow=FALSE + bAcceptsStaticDecals=FALSE + bAcceptsDynamicDecals=FALSE + Rotation=(Roll=-16384) + SkeletalMesh=SkeletalMesh'FX_Flamethrower_MESH.WEP_Flamethrower_Flame_A' + AnimTreeTemplate=AnimTree'FX_Flamethrower_ANIM.WEP_Flamethrower_Flame_AT' + AnimSets(0)=AnimSet'FX_Flamethrower_ANIM.WEP_Flamethrower_Flame_Anim' + End Object + SkeletalSprayMesh=FlameCore0 + CollisionComponent=FlameCore0 + Components.Add(FlameCore0) + + SkelMesh=SkeletalMesh'FX_Flamethrower_MESH.WEP_Flamethrower_Flame_A' + SprayAnimSet=AnimSet'FX_Flamethrower_ANIM.WEP_Flamethrower_Flame_Anim' + SprayAnimTreeTemplate=AnimTree'FX_Flamethrower_ANIM.WEP_Flamethrower_Flame_AT' + + AltSprayAnimSet=AnimSet'FX_Flamethrower_ANIM.Wep_Caulk_Flame_Anim' + +// bLeaveStickyFire=FALSE +// StickyFireMinTimeBetweenSpawns=0.25f +// StickyFireOwnerSafeRadius=64 +// StickyFireInitialDelay=0.5f +// StickyFireTestLocInterpSpeed=5.f +// StickyFireTestLocThreshold=64.f + + ImpactEffects=KFImpactEffectInfo'WEP_Flamethrower_ARCH.Flame_Impacts' + + SprayEndEffect=ParticleSystem'WEP_Flamethrower_EMIT.FX_End_muzzleflash_01' + SprayStartEffect=ParticleSystem'WEP_Flamethrower_EMIT.FX_Start_muzzleflash' + + SplashGlancingEffect=ParticleSystem'WEP_Flamethrower_EMIT.FX_flame_deflect_01' + Begin Object Class=KFParticleSystemComponent Name=SplashGlancingPSC0 + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + SplashGlancingPSC=SplashGlancingPSC0 + Components.Add(SplashGlancingPSC0) + + SplashDirectEffect=ParticleSystem'WEP_Flamethrower_EMIT.FX_Flame_impact_01' + Begin Object Class=KFParticleSystemComponent Name=SplashDirectPSC0 + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + SplashDirectPSC=SplashDirectPSC0 + Components.Add(SplashDirectPSC0) + + SplashPawnEffect=ParticleSystem'WEP_Flamethrower_EMIT.FX_Flame_impact_player_01' + Begin Object Class=KFParticleSystemComponent Name=SplashPawnPSC0 + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + SplashPawnPSC=SplashPawnPSC0 + Components.Add(SplashPawnPSC0) + + Begin Object Class=KFParticleSystemComponent Name=SplashMaterialBasedPSC0 + bAutoActivate=FALSE + Template=None // filled in by the code based on what was hit + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + SplashMaterialBasedPSC=SplashMaterialBasedPSC0 + Components.Add(SplashMaterialBasedPSC0) + + // per-bone fire fx + LastBoneChainIndexThatCanSpawnSplashEffects=11 + + // bone01 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone01_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone01_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone02 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone02_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone02_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone03 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone03_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone03_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + Rotation=(Yaw=32768) + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone04 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone04_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone04_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone05 + Begin Object Class=KFParticleSystemComponent Name=Bone05_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone05_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone06 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone06_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone06_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone07 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone07_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone07_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone08 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone08_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone08_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone09 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone09_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone09_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone10 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone10_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone10_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone11 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone11_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone11_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone12 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone12_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone12_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + // bone13 + // 3rd person + Begin Object Class=KFParticleSystemComponent Name=Bone13_PSC0 + bOwnerNoSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + // first person + Begin Object Class=KFParticleSystemComponent Name=Bone13_PSC1 + bOnlyOwnerSee=TRUE + bAutoActivate=FALSE + TranslucencySortPriority=1 + SecondsBeforeInactive=0 + End Object + + BoneChain(0)={(BoneName=Bone01, + MaterialParam=0.0, + BoneScale=1.f, + EffectScale=1.0f, + ParticleSystemTemplate=none, + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_Initial_spawn_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone01_PSC0, + BonePSC1=Bone01_PSC1)} + BoneChain(1)={(BoneName=Bone02, + MaterialParam=0.04, + BoneScale=1.f, + EffectScale=1.0f, + ParticleSystemTemplate=none, + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_Initial_spawn_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone01_PSC0, + BonePSC1=Bone01_PSC1)} + BoneChain(2)={(BoneName=Bone03, + MaterialParam=0.080000, + BoneScale=1.f, + EffectScale=0.250000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_reverse_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_reverse_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone02_PSC0, + BonePSC1=Bone02_PSC1)} + BoneChain(3)={(BoneName=Bone04, + MaterialParam=0.130000, + BoneScale=1.f, + EffectScale=0.250000, + ParticleSystemTemplate=None, + ParticleSystemTemplate1P=None, + ParticleActivationDelay=0.0f, + BonePSC0=Bone03_PSC0, + BonePSC1=Bone03_PSC1)} + BoneChain(4)={(BoneName=Bone05, + MaterialParam=0.190000, + BoneScale=1.f, + EffectScale=0.500000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone04_PSC0, + BonePSC1=Bone04_PSC1)} + BoneChain(5)={(BoneName=Bone06, + MaterialParam=0.240000, + BoneScale=1.f, + EffectScale=0.500000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone05_PSC0, + BonePSC1=Bone05_PSC1)} + BoneChain(6)={(BoneName=Bone07, + MaterialParam=0.310000, + BoneScale=1.f, + EffectScale=1.800000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone06_PSC0, + BonePSC1=Bone06_PSC1)} + BoneChain(7)={(BoneName=Bone08, + MaterialParam=0.370000, + BoneScale=1.f, + EffectScale=0.500000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone07_PSC0, + BonePSC1=Bone07_PSC1)} + BoneChain(8)={(BoneName=Bone09, + MaterialParam=0.440000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone08_PSC0, + BonePSC1=Bone08_PSC1)} + BoneChain(9)={(BoneName=Bone10, + MaterialParam=0.500000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone09_PSC0, + BonePSC1=Bone09_PSC1)} + BoneChain(10)={(BoneName=Bone11, + MaterialParam=0.560000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone10_PSC0, + BonePSC1=Bone10_PSC1)} + BoneChain(11)={(BoneName=Bone12, + MaterialParam=0.620000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone11_PSC0, + BonePSC1=Bone11_PSC1)} + BoneChain(12)={(BoneName=Bone13, + MaterialParam=0.690000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone12_PSC0, + BonePSC1=Bone12_PSC1)} + BoneChain(13)={(BoneName=Bone14, + MaterialParam=0.760000, + BoneScale=1.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_End_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f, + BonePSC0=Bone13_PSC0, + BonePSC1=Bone13_PSC1)} + BoneChain(14)={(BoneName=Bone15, + MaterialParam=0.820000, + BoneScale=0.f, + EffectScale=1.000000, + ParticleSystemTemplate=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_End_01_3P', + ParticleSystemTemplate1P=ParticleSystem'WEP_Flamethrower_EMIT.Materials.FX_Flamethrower_BSpawns_01_1P', + ParticleActivationDelay=0.0f)} + + BoneChainComponents={(Bone01_PSC0, Bone01_PSC0, Bone02_PSC0, Bone03_PSC0, Bone04_PSC0, Bone05_PSC0, Bone06_PSC0, + Bone07_PSC0, Bone08_PSC0, Bone09_PSC0, Bone10_PSC0, Bone11_PSC0, Bone12_PSC0, Bone13_PSC0)} + BoneChainComponents_1stP={(Bone01_PSC1, Bone01_PSC1, Bone02_PSC1, Bone03_PSC1, Bone04_PSC1, Bone05_PSC1, Bone06_PSC1, + Bone07_PSC1, Bone08_PSC1, Bone09_PSC1, Bone10_PSC1, Bone11_PSC1, Bone12_PSC1, Bone13_PSC1)} + + // pointlight at far end of spray + Begin Object Class=PointLightComponent Name=FlamePointLight2 + LightColor=(R=245,G=190,B=140,A=255) + Brightness=4.f + Radius=500.f + FalloffExponent=10.f + CastShadows=False + CastStaticShadows=FALSE + CastDynamicShadows=TRUE + bCastPerObjectShadows=false + bEnabled=FALSE + LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE) + End Object + + // Muzzle Flash point light + // want this light to illuminate characters only, so Marcus gets the glow + Begin Object Class=PointLightComponent Name=FlamePointLight0 + LightColor=(R=250,G=150,B=85,A=255) + Brightness=6.0f + FalloffExponent=10.f + Radius=750.f + CastShadows=False + CastStaticShadows=FALSE + CastDynamicShadows=TRUE + bCastPerObjectShadows=false + bEnabled=FALSE + LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE) + End Object + + SprayLights(0)=(Light=FlamePointLight0,BoneChainIndex=1,FlickerIntensity=5.f,FlickerInterpSpeed=15.f) + SprayLights(1)=(Light=FlamePointLight2,BoneChainIndex=9,FlickerIntensity=5.f,FlickerInterpSpeed=15.f) + +// MaterialHeatRampTime=0.65f +// MaterialHeatRange=(X=0.f,Y=0.8f) +// MaterialFadeOutTime=0.2f +// MaterialCurrentFadeVal=1.f +// MatFadePow=2.f +// Begin Object Class=AudioComponent Name=SplashMaterialBasedAC0 +// // cue will be filled in from physicalmaterial data +// SoundCue=None +// bStopWhenOwnerDestroyed=TRUE +// bUseOwnerLocation=FALSE +// End Object +// SplashMaterialBasedAC=SplashMaterialBasedAC0 + + // Splash audio + Begin Object Class=AkComponent name=CurrentSplashAkSoundComponent + bStopWhenOwnerDestroyed=true + bForceOcclusionUpdateInterval=true + OcclusionUpdateInterval=0.2; + End Object + CurrentSplashAKC=CurrentSplashAkSoundComponent + Components.Add(CurrentSplashAkSoundComponent) + + SplashPawnAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Play_WEP_SA_Flamethrower_Impact_Flesh' + SplashDirectAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Play_WEP_SA_Flamethrower_Impact_Default' + SplashGlancingAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Play_WEP_SA_Flamethrower_Impact_Default' + + SplashPawnStopAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Stop_WEP_SA_Flamethrower_Impact_Flesh_Loop' + SplashDirectStopAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Stop_WEP_SA_Flamethrower_Impact_Default_Loop' + SplashGlancingStopAKEvent=AkEvent'WW_WEP_SA_Flamethrower.Stop_WEP_SA_Flamethrower_Impact_Default_Loop' + + Begin Object Class=KFParticleSystemComponent Name=StartFirePSC0 + bAutoActivate=TRUE + TickGroup=TG_PostUpdateWork + End Object + SprayStartPSC=StartFirePSC0 + + SeedSprayVel=10000.f//5000.f + SeedDecel=28000.f//13000.f + SeedMaxAge=0.4f + SeedMinChainLength=0.f + SeedSimFreq=60.f + SeedWarmupTime=0.25f + VelocityScaleZ=0.3f//0.15f + + bUseExtentTracing=true + SpraySocketName=MuzzleFlash + + //ImpactProjectileClass=class'KFProj_GroundFire' + + ImpactProjectileInterval=0.099 + + +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeapAttach_HRG_Vampire.uc b/KFGameContent/Classes/KFWeapAttach_HRG_Vampire.uc new file mode 100644 index 0000000..ce7d181 --- /dev/null +++ b/KFGameContent/Classes/KFWeapAttach_HRG_Vampire.uc @@ -0,0 +1,496 @@ +//============================================================================= +// KFWeapAttach_HRG_Vampire +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2020 Tripwire Interactive LLC +//============================================================================= +class KFWeapAttach_HRG_Vampire extends KFWeapAttach_SprayBase; + +var transient ParticleSystemComponent ChargingPSC; +var transient ParticleSystemComponent ChargedPSC; +var ParticleSystem ChargingEffect; +var ParticleSystem ChargedEffect; +var ParticleSystem BloodStolenEffect; +var bool bIsCharging; +var bool bIsFullyCharged; +var bool bIsChargeEffectsActive; +var bool bIsBloodParticlesEffectActive; +var bool bIsDisabledSprayVisualAndMesh; + +var repnotify float StartFireTime; + +var int ChargeLevel; + +var float FXScalingFactorByCharge; +var float ChargeRTPC; + +var KFPawn_Monster oZedCurrentlyBeingSprayed; +var KFPawn_Monster oZedPreviouslyBeingSprayed; + +var KFWeap_HRG_Vampire Weapon; + +var KFEmit_DirectionalPath BloodStolenParticles[15]; +var int NumBloodStolenParticlesForPool; + +var transient float BloodStolenControlTime; + +var float RateUpdateDestinationBloodParticles; +var transient float UpdateDestinationBloodParticlesTime; + +var class BloodSplashClass; + +var bool bHasToStopDoingFireAnim; +var bool bHasToStopDoingFireAnimB; + +/** Blood Particles */ +var(BloodParticles) float SpeedBloodParticles; +var(BloodParticles) float SpawnRateBloodParticles; +var(BloodParticles) float SpeedBloodParticles_3P; +var(BloodParticles) float SpawnRateBloodParticles_3P; +var(BloodParticles) float HalfAngleSpawnCone; +var(BloodParticles) float CurveTurnRateUntilDestinationFinal; +var(BloodParticles) float CurveTurnRateUntilDestinationMidPoint; +var(BloodParticles) float LimitDistanceFinalPoint; +var(BloodParticles) float LimitDistanceMidPoint; + +simulated function PostBeginPlay() +{ + local int Index; + + super.PostBeginPlay(); + UpdateDestinationBloodParticlesTime = RateUpdateDestinationBloodParticles; + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + BloodStolenParticles[Index] = Spawn(class'KFEmit_DirectionalPath'); + BloodStolenParticles[Index].DeactivateEmitter(); + BloodStolenParticles[Index].SetTemplate(BloodStolenEffect, true); + } +} + +simulated function StartFire() +{ + StartFireTime = WorldInfo.TimeSeconds; + bIsCharging = false; + bIsFullyCharged = false; + bIsDisabledSprayVisualAndMesh = false; + + if (ChargingPSC == none) + { + ChargingPSC = new(self) class'ParticleSystemComponent'; + + if (WeapMesh != none) + { + WeapMesh.AttachComponentToSocket(ChargingPSC, 'MuzzleFlash'); + } + else + { + AttachComponent(ChargingPSC); + } + ChargingPSC.SetTemplate(ChargingEffect); + } + + if (ChargedPSC == none) + { + ChargedPSC = new(self) class'ParticleSystemComponent'; + + if (WeapMesh != none) + { + WeapMesh.AttachComponentToSocket(ChargedPSC, 'MuzzleFlash'); + } + else + { + AttachComponent(ChargedPSC); + } + ChargedPSC.SetTemplate(ChargedEffect); + } + ChargingPSC.SetActive( false ); + ChargedPSC.SetActive( false ); +} + +simulated event Tick(float DeltaTime) +{ + local int Index; + local vector MuzzleFlashSocketLocation, BloodParticlesMidPointSocketLocation; + local KFEmit_DirectionalPath EmitterToRemove; + local vector VectorParameterParticle; + local vector ChargePercentageVector; + local Rotator DestinationRotation, BloodParticlesMidPointSocketRotation; + local vector BloodSplashVelocity; + + if(bIsChargeEffectsActive) + { + if(bIsCharging) + { + ChargingPSC.SetActive( true, true ); + ChargePercentageVector.X = ChargeRTPC; + ChargePercentageVector.Y = ChargeRTPC; + ChargePercentageVector.Z = ChargeRTPC; + ChargingPSC.SetVectorParameter( name("BlobCharge"), ChargePercentageVector); + } + + if(bIsFullyCharged) + { + ChargedPSC.SetActive( true, true ); + ChargingPSC.SetFloatParameter( name("InflateBlob"), ChargeRTPC); + } + } + + if (bIsDisabledSprayVisualAndMesh) + { + TurnOffFireSpray(); + ActiveFlameSpray.CleanupEndFire(); + } + + //Spawning blood particles if conditions met + if (bIsBloodParticlesEffectActive) + { + if(oZedCurrentlyBeingSprayed != none && oZedCurrentlyBeingSprayed.IsAliveAndWell()) + { + CreateBloodParticle(DeltaTime, oZedCurrentlyBeingSprayed); + } + } + + + // Updating blood stolen particles FX destination position + + UpdateDestinationBloodParticlesTime -= DeltaTime; + if (UpdateDestinationBloodParticlesTime <= 0) + { + UpdateDestinationBloodParticlesTime = RateUpdateDestinationBloodParticles; + + if( WeapMesh != none ) + { + GetFlameSocketLocAndRot(MuzzleFlashSocketLocation, DestinationRotation); + WeapMesh.GetSocketWorldLocationAndRotation('BloodParticlesMidPoint', BloodParticlesMidPointSocketLocation, BloodParticlesMidPointSocketRotation); + } + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + if(!BloodStolenParticles[Index].IsEnabled || BloodStolenParticles[Index] == None) + { + continue; + } + + if( BloodStolenParticles[Index].bReachDestinationFinal ) + { + EmitterToRemove = BloodStolenParticles[Index]; + //BloodStolenParticles.Remove(Index, 1); + EmitterToRemove.DeactivateEmitter(); + } + else + { + if (BloodStolenParticles[Index].ParticleSystemComponent != None) + { + VectorParameterParticle.X = WorldInfo.TimeDilation; + VectorParameterParticle.Y = WorldInfo.TimeDilation; + VectorParameterParticle.Z = WorldInfo.TimeDilation; + BloodStolenParticles[Index].ParticleSystemComponent.SetVectorParameter( name("ZedtimeScale"), VectorParameterParticle ); + } + BloodStolenParticles[Index].UpdateDestination( MuzzleFlashSocketLocation, BloodParticlesMidPointSocketLocation ); + + if (FRand() > 0.47) + { + BloodSplashVelocity.x = 0; + BloodSplashVelocity.y = RandRange(-100, 100); + BloodSplashVelocity.z = -200; + SpawnBloodSplash(BloodSplashClass, BloodStolenParticles[Index].Location, BloodSplashVelocity); + } + } + } + } + + Super.Tick(DeltaTime); +} + +simulated function FirstPersonFireEffects(Weapon W, vector HitLocation) +{ + super.FirstPersonFireEffects(W, HitLocation); +} + +simulated function bool ThirdPersonFireEffects(vector HitLocation, KFPawn P, byte ThirdPersonAnimRateByte ) +{ + local EAnimSlotStance AnimType; + local bool bResult; + bIsChargeEffectsActive = true; + bIsBloodParticlesEffectActive = true; + + //bResult = Super(KFWeaponAttachment).ThirdPersonFireEffects(HitLocation,P,ThirdPersonAnimRateByte); + + SpawnTracer(GetMuzzleLocation(), HitLocation); + + // Effects below this point are culled based on visibility and distance + if ( !ActorEffectIsRelevant(P, false, MaxFireEffectDistance) ) + { + return false; + } + + DecodeThirdPersonAnimRate( ThirdPersonAnimRateByte ); + + // Weapon shoot anims + if( !bWeapMeshIsPawnMesh && bHasToStopDoingFireAnim == false ) + { + PlayWeaponFireAnim(); + bHasToStopDoingFireAnim = true; + } + + if( P.IsDoingSpecialMove() && P.SpecialMoves[P.SpecialMove].bAllowFireAnims ) + { + AnimType = EAS_Additive; + } + else + { + AnimType = EAS_FullBody; + } + + // Character shoot anims + if ( !P.IsDoingSpecialMove() || AnimType == EAS_Additive ) + { + if(!bHasToStopDoingFireAnimB) + { + bHasToStopDoingFireAnimB = true; + PlayPawnFireAnim( P, AnimType ); + } + + // interrupt other weapon action anims (e.g. Reload) + if( !P.IsDoingSpecialMove() ) + { + P.StopBodyAnim(P.bIsCrouched ? EAS_CH_UpperBody : EAS_UpperBody, 0.1f); + } + + if ( OnWeaponStateChanged != None ) + { + OnWeaponStateChanged(true); + } + } + + CauseMuzzleFlash(P.FiringMode); + + // Wider effect distances for fire spray. Called on Instigator to go beyond the weapon mesh cull distance + if ( P.FiringMode != 1 && P.ActorEffectIsRelevant(P, false, 15000, 2000) && !bIsDisabledSprayVisualAndMesh ) + { + TurnOnFireSpray(); + bResult = true; + } + + return bResult; +} + +simulated function StopThirdPersonFireEffects(optional bool bForce) +{ + Super.StopThirdPersonFireEffects(bForce); + bIsChargeEffectsActive = false; + bIsBloodParticlesEffectActive = false; + RemoveAllBloodParticles(); + bIsDisabledSprayVisualAndMesh = false; + if (ChargingPSC != none) + { + ChargingPSC.SetActive(false); + } + if (ChargedPSC != none) + { + ChargedPSC.SetActive(false); + } + bHasToStopDoingFireAnim = false; + bHasToStopDoingFireAnimB = false; +} + +simulated function CauseMuzzleFlash(byte FiringMode) +{ + if (MuzzleFlash == None && MuzzleFlashTemplate != None) + { + AttachMuzzleFlash(); + } + + Super.CauseMuzzleFlash(FiringMode); +} + +simulated protected function TurnOnPilot() +{ + Super.TurnOnPilot(); + + if( FlamePool[0] != None && KFSprayActor_HRG_Vampire(FlamePool[0]) != None && KFSprayActor_HRG_Vampire(FlamePool[0]).OwnerWeapon == None) + { + KFSprayActor_HRG_Vampire(FlamePool[0]).OwnerWeapon = KFWeap_HRG_Vampire(KFPawn_Human(Instigator).MyKFWeapon); + } + if( FlamePool[1] != None && KFSprayActor_HRG_Vampire(FlamePool[1]) != None && KFSprayActor_HRG_Vampire(FlamePool[1]).OwnerWeapon == None) + { + KFSprayActor_HRG_Vampire(FlamePool[1]).OwnerWeapon = KFWeap_HRG_Vampire(KFPawn_Human(Instigator).MyKFWeapon); + } +} + +simulated function CreateBloodParticle(float DeltaTime, KFPawn_Monster Monster) +{ + Local KFEmit_DirectionalPath Emitter; + local vector DestinationLocation, MonsterLocation, BloodParticlesMidPointSocketLocation; + local Rotator DestinationRotation, BloodParticlesMidPointSocketRotation; + local vector BloodSplashVelocity; + local int Index; + + if( BloodStolenControlTime > 0 ) + { + BloodStolenControlTime -= DeltaTime; + return; + } + + Emitter = none; + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + if(BloodStolenParticles[Index].IsEnabled == false) + { + //`log("I gave the emitter"); + Emitter = BloodStolenParticles[Index]; + break; + } + } + + if(Emitter == none) + { + //`log("NO EMITTER"); + return; + } + + + if( WeapMesh != none && WeapMesh.SkeletalMesh != none) + { + GetFlameSocketLocAndRot(DestinationLocation, DestinationRotation); + WeapMesh.GetSocketWorldLocationAndRotation('BloodParticlesMidPoint', BloodParticlesMidPointSocketLocation, BloodParticlesMidPointSocketRotation); + } + + BloodStolenControlTime += SpawnRateBloodParticles_3P; + MonsterLocation = ActiveFlameSpray.GetLastContactPositionMeshHit(); + if (IsZero(MonsterLocation)) + { + Monster.Mesh.GetBoneLocation('Spine1'); + } + + if(MonsterLocation == vect(0,0,0)) + { + MonsterLocation = Monster.Location + vect(0,0,20); + } + + if (FRand() > 0.4) + { + BloodSplashVelocity = BloodParticlesMidPointSocketLocation - MonsterLocation; + BloodSplashVelocity = VRandCone(vect(0,0,-1), PI / 5) * 100; + SpawnBloodSplash(BloodSplashClass, MonsterLocation, BloodSplashVelocity); + } + + //Emitter = Spawn(class'KFEmit_DirectionalPath',,, MonsterLocation); + Emitter.ParticleSpeed = SpeedBloodParticles_3P; + Emitter.RateTickCheckHasReached = 0.2; + //BloodStolenParticles.AddItem(Emitter); + Emitter.SetLocation(MonsterLocation); + + Emitter.SetDestination(DestinationLocation, BloodParticlesMidPointSocketLocation, 20, 20, 50, 50, 0); + Emitter.ActivateEmitter(); + //Emitter.isEnabled = true; + +} + +simulated function SetChargePercentage(float ChargePercentage) +{ + ChargeRTPC = ChargePercentage; + bIsCharging = false; + bIsFullyCharged = false; + + if (ChargeRTPC >= 0.0) + { + bIsCharging = true; + } + + if (ChargeRTPC >= 1.0) + { + bIsFullyCharged = true; + } +} + +simulated function SetZedCurrentlyBeingSprayed(KFPawn_Monster ZedCurrentlyBeingSprayed) +{ + oZedPreviouslyBeingSprayed = oZedCurrentlyBeingSprayed; + oZedCurrentlyBeingSprayed = ZedCurrentlyBeingSprayed; +} + +simulated function DisableSprayVisualAndMesh() +{ + bIsDisabledSprayVisualAndMesh = true; +} + +function SpawnBloodSplash( class SpawnClass, vector SpawnLoc, vector SpawnVel ) +{ + local TraceHitInfo HitInfo; + local vector HitLocation, HitRotation; + local KFGoreManager GoreManager; + + // Grab the gore manager + GoreManager = KFGoreManager(WorldInfo.MyGoreEffectManager); + + if (GoreManager == none || oZedCurrentlyBeingSprayed == none) + { + return; + } + + //EffectStartTrace = Location + vect(0,0,1) * 4.f; + //EffectEndTrace = EffectStartTrace - vect(0,0,1) * 32.f; + + // Find where to put the decal + Trace(HitLocation, HitRotation, SpawnLoc + SpawnVel * 32.f, SpawnLoc, false,, HitInfo, TRACEFLAG_Bullet); + //DrawDebugLine(SpawnLoc,SpawnLoc + SpawnVel * 32.f,0,255,0,TRUE); + + // If the locations are zero (probably because this exploded in the air) set defaults + if( IsZero(HitLocation) ) + { + HitLocation = Location; + } + + if( IsZero(HitRotation) ) + { + HitRotation = vect(0,0,1); + } + + + //Put the decals + GoreManager.LeaveABloodSplatterDecal(oZedCurrentlyBeingSprayed, HitLocation, HitRotation); + + //GoreManager. LeaveAPersistentBloodSplat(HitLocation, HitNormal, 1.0); + + if (oZedCurrentlyBeingSprayed != none) + { + GoreManager.CausePersistentBlood(oZedCurrentlyBeingSprayed, class'KFDamageType', HitLocation, vect(0,0,-1), 0, false, false); + } +} + +simulated function RemoveAllBloodParticles() +{ + local int Index; + local KFEmit_DirectionalPath EmitterToRemove; + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + EmitterToRemove = BloodStolenParticles[Index]; + //BloodStolenParticles.Remove(Index, 1); + EmitterToRemove.DeactivateEmitter(); + } +} + +defaultproperties +{ + ChargeRTPC=0 + bIsChargeEffectsActive=false + bIsBloodParticlesEffectActive=false + bIsDisabledSprayVisualAndMesh=false + MuzzleFlashTemplate=KFMuzzleFlash'WEP_HRG_Vampire_Arch.Wep_HRG_Vampire_MuzzleFlash_3P' + + ChargingEffect=ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_BlobCharge_3P_01' + ChargedEffect=ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_FullCharge' + + BloodStolenEffect=ParticleSystem'WEP_HRG_Vampire_EMIT.FX_HRG_Vampire_BloodStolen_3P' + + BloodSplashClass=KFProj_BloodSplash + + RateUpdateDestinationBloodParticles = 0.7 + + NumBloodStolenParticlesForPool = 15; +} diff --git a/KFGameContent/Classes/KFWeap_AssaultRifle_M16M203.uc b/KFGameContent/Classes/KFWeap_AssaultRifle_M16M203.uc index 4178fed..becc1e7 100644 --- a/KFGameContent/Classes/KFWeap_AssaultRifle_M16M203.uc +++ b/KFGameContent/Classes/KFWeap_AssaultRifle_M16M203.uc @@ -599,6 +599,7 @@ defaultproperties HippedRecoilModifier=1.5 SecondaryAmmoTexture=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade' + bUseGrenadeAsSecondaryAmmo=true // Inventory / Grouping InventorySize=6 diff --git a/KFGameContent/Classes/KFWeap_AssaultRifle_MedicRifleGrenadeLauncher.uc b/KFGameContent/Classes/KFWeap_AssaultRifle_MedicRifleGrenadeLauncher.uc index 6fc8699..68c1047 100644 --- a/KFGameContent/Classes/KFWeap_AssaultRifle_MedicRifleGrenadeLauncher.uc +++ b/KFGameContent/Classes/KFWeap_AssaultRifle_MedicRifleGrenadeLauncher.uc @@ -565,6 +565,7 @@ defaultproperties HippedRecoilModifier=1.5 SecondaryAmmoTexture=Texture2D'ui_firemodes_tex.UI_FireModeSelect_Grenade' + bUseGrenadeAsSecondaryAmmo=true // Inventory / Grouping InventorySize=8 diff --git a/KFGameContent/Classes/KFWeap_Edged_FireAxe.uc b/KFGameContent/Classes/KFWeap_Edged_FireAxe.uc index 7369abb..3ffeb11 100644 --- a/KFGameContent/Classes/KFWeap_Edged_FireAxe.uc +++ b/KFGameContent/Classes/KFWeap_Edged_FireAxe.uc @@ -44,10 +44,10 @@ defaultproperties End Object InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Slashing_FireAxe' - InstantHitDamage(DEFAULT_FIREMODE)=80 //90 + InstantHitDamage(DEFAULT_FIREMODE)=90 //80 InstantHitDamageTypes(HEAVY_ATK_FIREMODE)=class'KFDT_Slashing_FireAxeHeavy' - InstantHitDamage(HEAVY_ATK_FIREMODE)=125 //135 + InstantHitDamage(HEAVY_ATK_FIREMODE)=135 //125 //135 InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_FireAxeBash' InstantHitDamage(BASH_FIREMODE)=20 diff --git a/KFGameContent/Classes/KFWeap_HRG_EMP_ArcGenerator.uc b/KFGameContent/Classes/KFWeap_HRG_EMP_ArcGenerator.uc index 67886a5..b00358c 100644 --- a/KFGameContent/Classes/KFWeap_HRG_EMP_ArcGenerator.uc +++ b/KFGameContent/Classes/KFWeap_HRG_EMP_ArcGenerator.uc @@ -26,9 +26,8 @@ class KFWeap_HRG_EMP_ArcGenerator extends KFWeap_FlameBase; Replication { if(role == role_authority && bNetDirty) - oZedCurrentlyBeingSprayed; + oZedCurrentlyBeingSprayed, MaxNumberOfZedsZapped, MaxDistanceToBeZapped, ZapInterval, ChainDamage; } - /** Shoot animation to play when shooting secondary fire */ var(Animations) const editconst name FireHeavyAnim; @@ -319,7 +318,6 @@ simulated function int SpawnBeam(Actor _OriginActor, Actor _DestinationActor) simulated function MarkBeamToDeactivate(BeamAttachedToActor _BeamData) { - `log(_BeamData.oAttachedZed); vAuxDeletionArray.AddItem(_BeamData); } diff --git a/KFGameContent/Classes/KFWeap_HRG_Revolver_Buckshot.uc b/KFGameContent/Classes/KFWeap_HRG_Revolver_Buckshot.uc index 4d5493e..d5bd9b7 100644 --- a/KFGameContent/Classes/KFWeap_HRG_Revolver_Buckshot.uc +++ b/KFGameContent/Classes/KFWeap_HRG_Revolver_Buckshot.uc @@ -39,8 +39,8 @@ defaultproperties GroupPriority=75 // Recoil - maxRecoilPitch=750 - minRecoilPitch=675 + maxRecoilPitch=525 //750 + minRecoilPitch=472 //675 maxRecoilYaw=300 minRecoilYaw=-300 RecoilRate=0.1 @@ -63,7 +63,7 @@ defaultproperties InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRGBuckshot' PenetrationPower(DEFAULT_FIREMODE)=2.0 NumPellets(DEFAULT_FIREMODE) = 5 - Spread(DEFAULT_FIREMODE)=0.15 + Spread(DEFAULT_FIREMODE)=0.12 //0.15 // ALTFIRE_FIREMODE InstantHitDamageTypes(ALTFIRE_FIREMODE) = class'KFDT_Ballistic_HRGBuckshot' diff --git a/KFGameContent/Classes/KFWeap_HRG_Revolver_DualBuckshot.uc b/KFGameContent/Classes/KFWeap_HRG_Revolver_DualBuckshot.uc index 5ed834f..9534d87 100644 --- a/KFGameContent/Classes/KFWeap_HRG_Revolver_DualBuckshot.uc +++ b/KFGameContent/Classes/KFWeap_HRG_Revolver_DualBuckshot.uc @@ -61,8 +61,8 @@ defaultproperties GroupPriority=75 // Recoil - maxRecoilPitch=750 - minRecoilPitch=675 + maxRecoilPitch=525 //750 + minRecoilPitch=472 //675 maxRecoilYaw=300 minRecoilYaw=-300 RecoilRate=0.1 @@ -85,7 +85,7 @@ defaultproperties InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRGBuckshot' PenetrationPower(DEFAULT_FIREMODE)=2.0 NumPellets(DEFAULT_FIREMODE)=5 - Spread(DEFAULT_FIREMODE)=0.15 + Spread(DEFAULT_FIREMODE)=0.12 //0.15 // ALTFIRE_FIREMODE FireModeIconPaths(ALTFIRE_FIREMODE)="ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle" @@ -96,7 +96,7 @@ defaultproperties InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRGBuckshot' PenetrationPower(ALTFIRE_FIREMODE)=2.0 NumPellets(ALTFIRE_FIREMODE)=5 - Spread(ALTFIRE_FIREMODE)=0.15 + Spread(ALTFIRE_FIREMODE)=0.12 //0.15 //BASH_FIREMODE InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRGBuckshot' diff --git a/KFGameContent/Classes/KFWeap_HRG_Vampire.uc b/KFGameContent/Classes/KFWeap_HRG_Vampire.uc new file mode 100644 index 0000000..99af90b --- /dev/null +++ b/KFGameContent/Classes/KFWeap_HRG_Vampire.uc @@ -0,0 +1,1375 @@ +//============================================================================= +// KFWeap_HRG_Vampire +//============================================================================= +// A gun that sucks zeds blood and use it against them +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2015 Tripwire Interactive LLC +// FFerrando @ saber3d +//============================================================================= +/* + + */ +class KFWeap_HRG_Vampire extends KFWeap_FlameBase; +//START BLOOD BALL PROPERTIES +//Props related to charging the weapon +//var float MaxChargeTime; +var float MaxChargeAmmo; +var float ChargeSpeed; + +/** While ChargeTime is below this threshold, a static min damage value (MinDamageByCharge) will be used for BloodBall instant damage */ +var float MinDamageWhileChargingThreshold; + +var float ValueIncreaseTime; +var float DmgIncreasePerCharge; +var float AOEIncreasePerCharge; +var float IncapIncreasePerCharge; + +var transient float ChargeTime; +var transient float CurrentCharge; +var transient float CurrentChargeOrigin; +var transient float CurrentChargeDesired; +var transient float CurrentChargeAmmo; +var transient float CurrentChargeAccumulatedTime; +var transient float CurrentChargeForBloodBallProjectile; + +var ParticleSystem ChargingEffect; +var ParticleSystem ChargedEffect; +var ParticleSystem BloodStolenEffect; + +var const ParticleSystem MuzzleFlashEffectL3; + +var transient ParticleSystemComponent FullyChargedPSC; +var transient ParticleSystemComponent ChargingPSC; + +var KFEmit_DirectionalPath BloodStolenParticles[15]; +var int NumBloodStolenParticlesForPool; + +var float SpeedBloodParticlesDefault; +var float SpawnRateBloodParticlesDefault; +var float HalfAngleSpawnConeDefault; +var float CurveTurnRateUntilDestinationMidPointDefault; +var float CurveTurnRateUntilDestinationFinalDefault; +var float LimitDistanceMidPointDefault; +var float LimitDistanceFinalPointDefault; + +var transient float BloodStolenControlTime; + +//var transient bool bIsFullyCharged; +var transient bool bHasCharged; + +var const WeaponFireSndInfo FullyChargedSound; + +var const WeaponFireSndInfo ChargingSound; +var const WeaponFireSndInfo ChargedSound; + +var const WeaponFireSndInfo BloodSuctionStartSound; + +var const WeaponFireSndInfo BloodSuctionEndSound; + +var const WeaponFireSndInfo BloodSuctionLoopNoAmmoAndBloodBallChargedSound; + +var bool bIsSprayDisabled; + +var float SelfDamageReductionValue; + +var float FullChargedTimerInterval; +var float ChargePercentage; + +/** Value used to lerp projectile damage and scale depending on if ChargePercentage has surpassed MinDamageWhileChargingThreshold */ +var float DamageByChargePercentage; + +var float MinScale, MaxScale; + +var int MaxDamageByCharge; +var int MinDamageByCharge; + +const SecondaryFireAnim = 'Alt_Fire'; +const SecondaryFireIronAnim = 'Alt_Fire_Iron'; +const SecondaryFireAnimEmpty = 'Alt_Fire_Empty'; +const SecondaryFireIronAnimEmpty = 'Alt_Fire_Iron_Empty'; +var bool bHasToLaunchEmptyAnim; + +var SkelControlSingleBone Control; + + +var bool bBlocked; +//END BLOOD BALL PROPERTIES + + +/** Shoot animation to play when shooting secondary fire */ +var(Animations) const editconst name FireHeavyAnim; + +/** Shoot animation to play when shooting secondary fire last shot */ +var(Animations) const editconst name FireLastHeavyAnim; + +/** Shoot animation to play when shooting secondary fire last shot when aiming */ +var(Animations) const editconst name FireLastHeavySightedAnim; + +/** Alt-fire explosion template */ +var() GameExplosion ExplosionTemplate; + +//var float MaxChargeTime, ChargePercentage, ChargeTime; +//var bool bIsFullyCharged; + +var float ReplenishingAmmoOnSuctioningTime; +var float ReplenishingAmmoOnSuctioningInterval; +var int ReplenishingAmmoOnSuctioningCount; + +var class BloodBallProjClass; + +var float SpeedBloodParticles; +var float SpawnRateBloodParticles; +var float HalfAngleSpawnCone; +var float CurveTurnRateUntilDestinationMidPoint; +var float CurveTurnRateUntilDestinationFinal; +var float LimitDistanceMidPoint; +var float LimitDistanceFinalPoint; +var float RateUpdateDestinationBloodParticles; +var transient float UpdateDestinationBloodParticlesTime; + +var int InitialAmmoSecondaryCount; + +/** Variables to scale ammo cost on primary fire (so we can use "floats" on ammo and make ammo has no cost or small cost when no hitting zeds) */ +var float AmmoCostScaleDefaultFiremode; +var float AmmoCostAccumulated; + +/** Simulate delay in start charging like waiting for first blood particle to arrive */ +var transient bool bFirstBloodParticleCreated; +var transient float DelayUntilStartCharging; +var float ScaleDelayUntilStartCharging; +var transient float CurrentStartChargingTime; +var transient bool bIsAlreadyInitializedFX; + +var class BloodSplashClass; + +var transient float TimesConsumeAmmoCalled; + +var transient bool bIsFullCharged;//Only for using in 1p +var transient bool bIsChargingSoundStarted;//Only for using in authority + +Replication +{ + if(bNetDirty) + oZedCurrentlyBeingSprayed, ChargeTime, ClientCurrentChargeDesired; + if (bNetDirty && !bNetOwner) + ClientChargePercentage, bClientDisableSprayVisualAndMesh; +} + +var KFPawn_Monster oZedPreviouslyBeingSprayed; +/**************************** HRG SPRAY STUFF*/ + +var repnotify KFPawn_Monster oZedCurrentlyBeingSprayed; +var repnotify float ClientChargePercentage; +var repnotify float ClientCurrentChargeDesired; +var repnotify bool bClientDisableSprayVisualAndMesh; + +/*********************** */ + +simulated event ReplicatedEvent(name VarName) +{ + if (VarName == nameof(ClientChargePercentage)) + { + NotifyChargePercentage(ClientChargePercentage); + } + if (VarName == nameof(oZedCurrentlyBeingSprayed)) + { + NotifyZedCurrentlyBeingSprayed(oZedCurrentlyBeingSprayed); + } + if (VarName == nameof(bClientDisableSprayVisualAndMesh) && bClientDisableSprayVisualAndMesh) + { + NotifyDisableSprayVisualAndMesh(); + } + if (VarName == nameof(ClientCurrentChargeDesired)) + { + CurrentChargeDesired = ClientCurrentChargeDesired; + } + + Super.ReplicatedEvent(VarName); +} + +simulated function PostBeginPlay() +{ + local KFPawn_Human KFPH; + local int Index; + + super.PostBeginPlay(); + + AmmoCostAccumulated = 0; + + KFPH = KFPawn_Human(Instigator); + bIsAlreadyInitializedFX = false; + if (WorldInfo.NetMode == NM_DedicatedServer || (KFPH != none && !KFPH.IsFirstPerson())) + { + return; + } + + UpdateDestinationBloodParticlesTime = RateUpdateDestinationBloodParticles; + bFirstBloodParticleCreated = false; + CurrentStartChargingTime = DelayUntilStartCharging * ScaleDelayUntilStartCharging; + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + BloodStolenParticles[Index] = Spawn(class'KFEmit_DirectionalPath'); + BloodStolenParticles[Index].SetTemplate(BloodStolenEffect, true); + //BloodStolenParticles[Index].IsEnabled=false; + BloodStolenParticles[Index].DeactivateEmitter(); + } + +} + +simulated event Tick(float DeltaTime) +{ + return; +} + +/** Handle one-hand fire anims */ +simulated function name GetWeaponFireAnim(byte FireModeNum) +{ + local bool bPlayFireLast; + + bPlayFireLast = ShouldPlayFireLast(FireModeNum); + + if ( FireModeNum == CUSTOM_FIREMODE ) + { + return FireLoopEndAnim; + } + + if ( bUsingSights ) + { + if( bPlayFireLast ) + { + if ( FireModeNum == ALTFIRE_FIREMODE ) + { + return FireLastHeavySightedAnim; + } + else + { + return FireLastSightedAnim; + } + } + else + { + return FireSightedAnims[FireModeNum]; + } + + } + else + { + if( bPlayFireLast ) + { + if ( FireModeNum == ALTFIRE_FIREMODE ) + { + return FireLastHeavyAnim; + } + else + { + return FireLastAnim; + } + } + else + { + if ( FireModeNum == ALTFIRE_FIREMODE ) + { + return FireHeavyAnim; + } + else + { + return FireAnim; + } + } + } +} + + + +/** + * Instead of a toggle, just immediately fire alternate fire. + */ +simulated function AltFireMode() +{ + // LocalPlayer Only + if ( !Instigator.IsLocallyControlled() ) + { + return; + } + + StartFire(ALTFIRE_FIREMODE); +} + +/** Disable auto-reload for alt-fire */ +simulated function bool ShouldAutoReload(byte FireModeNum) +{ + local bool bRequestReload; + + bRequestReload = Super.ShouldAutoReload(FireModeNum); + + // Must be completely empty for auto-reload or auto-switch + if ( FireModeNum == ALTFIRE_FIREMODE && AmmoCount[DEFAULT_FIREMODE] > 0 ) + { + bPendingAutoSwitchOnDryFire = false; + return false; + } + + return bRequestReload; +} + +static simulated event EFilterTypeUI GetTraderFilter() +{ + return FT_Electric; +} + + +simulated protected function TurnOnPilot() +{ + Super.TurnOnPilot(); + + if( FlamePool[0] != None && KFSprayActor_HRG_Vampire(FlamePool[0]) != None && KFSprayActor_HRG_Vampire(FlamePool[0]).OwnerWeapon == None) + { + KFSprayActor_HRG_Vampire(FlamePool[0]).OwnerWeapon = self; + } + if( FlamePool[1] != None && KFSprayActor_HRG_Vampire(FlamePool[1]) != None && KFSprayActor_HRG_Vampire(FlamePool[1]).OwnerWeapon == None) + { + KFSprayActor_HRG_Vampire(FlamePool[1]).OwnerWeapon = self; + } +} + +simulated function float FlameHeatCalc() +{ + //hack in order to make the arc gen always glow + LastBarrelHeat = 1.0f; + return 1.0f; +} + +simulated function SetCurrentSprayedZed(KFPawn_Monster _Monster) +{ + if(role != role_authority && WorldInfo.NetMode != NM_ListenServer && WorldInfo.NetMode != NM_StandAlone) + { + return; + } + + oZedPreviouslyBeingSprayed = oZedCurrentlyBeingSprayed; + oZedCurrentlyBeingSprayed = _Monster; + bNetDirty=true; + AmmoCostScaleDefaultFiremode=1.0; + + if (oZedCurrentlyBeingSprayed == none || !oZedCurrentlyBeingSprayed.IsAliveAndWell()) + { + AmmoCostScaleDefaultFiremode=default.AmmoCostScaleDefaultFiremode; + } +} + +/** + * Drop this item out in to the world + */ +function DropFrom(vector StartLocation, vector StartVelocity) +{ + super.DropFrom(StartLocation, StartVelocity); + self.SetTickIsDisabled(true); +} + +function SetOriginalValuesFromPickup( KFWeapon PickedUpWeapon ) +{ + super.SetOriginalValuesFromPickup(PickedUpWeapon); + self.SetTickIsDisabled(false); +} + +/** + * Functions to notify KFWeapAttach (used for 3P FX) about state + */ +simulated function NotifyChargePercentage(float ChargePercentageNotified) +{ + local KFPawn KFPawn; + local KFWeapAttach_HRG_Vampire KFWeapAttach; + + KFPawn = KFPawn(Instigator); + KFWeapAttach = KFWeapAttach_HRG_Vampire(KFPawn.WeaponAttachment); + + if(KFWeapAttach != none) + { + KFWeapAttach.SetChargePercentage(ChargePercentageNotified); + } +} + +simulated function NotifyZedCurrentlyBeingSprayed(KFPawn_Monster Monster) +{ + local KFPawn KFPawn; + local KFWeapAttach_HRG_Vampire KFWeapAttach; + + KFPawn = KFPawn(Instigator); + KFWeapAttach = KFWeapAttach_HRG_Vampire(KFPawn.WeaponAttachment); + + if(KFWeapAttach != none) + { + KFWeapAttach.SetZedCurrentlyBeingSprayed(Monster); + } +} + +simulated function NotifyDisableSprayVisualAndMesh() +{ + local KFPawn KFPawn; + local KFWeapAttach_HRG_Vampire KFWeapAttach; + + KFPawn = KFPawn(Instigator); + KFWeapAttach = KFWeapAttach_HRG_Vampire(KFPawn.WeaponAttachment); + + if(KFWeapAttach != none) + { + KFWeapAttach.DisableSprayVisualAndMesh(); + } +} + + +simulated function CreateBloodParticle(KFPawn_Monster Monster) +{ + Local KFEmit_DirectionalPath Emitter; + local vector DestinationLocation, MonsterLocation, BloodParticlesMidPointSocketLocation; + local Rotator DestinationRotation, BloodParticlesMidPointSocketRotation; + local vector BloodSplashVelocity; + local int Index; + + if (!IsInState('FiringSuctioning')) + { + return; + } + Emitter = none; + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + if(BloodStolenParticles[Index].IsEnabled == false) + { + Emitter = BloodStolenParticles[Index]; + break; + } + } + + if(Emitter == none) + { + return; + } + + if(MySkelMesh != none) + { + GetFlameSocketLocAndRot(DestinationLocation, DestinationRotation); + MySkelMesh.GetSocketWorldLocationAndRotation('BloodParticlesMidPoint', BloodParticlesMidPointSocketLocation, BloodParticlesMidPointSocketRotation); + } + + + MonsterLocation = ActiveFlameSpray.GetLastContactPositionMeshHit(); + if (IsZero(MonsterLocation)) + { + Monster.Mesh.GetBoneLocation('Spine1'); + } + + + if(MonsterLocation == vect(0,0,0)) + { + MonsterLocation = Monster.Location + vect(0,0,20); + } + + + if (FRand() > 0.4) + { + BloodSplashVelocity = BloodParticlesMidPointSocketLocation - MonsterLocation; + BloodSplashVelocity = VRandCone(vect(0,0,-1), PI / 5) * 100; + SpawnBloodSplash(BloodSplashClass, MonsterLocation, BloodSplashVelocity); + } + + + //Emitter = Spawn(class'KFEmit_DirectionalPath',,, MonsterLocation); + + Emitter.ParticleSpeed = SpeedBloodParticles; + //BloodStolenParticles.AddItem(Emitter); + + Emitter.SetLocation(MonsterLocation); + Emitter.SetDestination( DestinationLocation, + BloodParticlesMidPointSocketLocation, + LimitDistanceFinalPoint, + LimitDistanceMidPoint, + CurveTurnRateUntilDestinationFinal, + CurveTurnRateUntilDestinationMidPoint, + HalfAngleSpawnCone); + + Emitter.ActivateEmitter(); + + + + + //Emitter.isEnabled = true; + +} + +simulated function SpawnBloodSplash( class SpawnClass, vector SpawnLoc, vector SpawnVel ) +{ + local TraceHitInfo HitInfo; + local vector HitLocation, HitRotation; + local KFGoreManager GoreManager; + + // Grab the gore manager + GoreManager = KFGoreManager(WorldInfo.MyGoreEffectManager); + + if (GoreManager == none || oZedCurrentlyBeingSprayed == none) + { + return; + } + + //EffectStartTrace = Location + vect(0,0,1) * 4.f; + //EffectEndTrace = EffectStartTrace - vect(0,0,1) * 32.f; + + // Find where to put the decal + Trace(HitLocation, HitRotation, SpawnLoc + SpawnVel * 32.f, SpawnLoc, false,, HitInfo, TRACEFLAG_Bullet); + //DrawDebugLine(SpawnLoc,SpawnLoc + SpawnVel * 32.f,0,255,0,TRUE); + + // If the locations are zero (probably because this exploded in the air) set defaults + if( IsZero(HitLocation) ) + { + HitLocation = Location; + } + + if( IsZero(HitRotation) ) + { + HitRotation = vect(0,0,1); + } + + + //Put the decals + GoreManager.LeaveABloodSplatterDecal(oZedCurrentlyBeingSprayed, HitLocation, HitRotation); + + //GoreManager. LeaveAPersistentBloodSplat(HitLocation, HitNormal, 1.0); + + if (oZedCurrentlyBeingSprayed != none) + { + GoreManager.CausePersistentBlood(oZedCurrentlyBeingSprayed, class'KFDamageType', HitLocation, vect(0,0,-1), 0, false, false); + } +} + +simulated function RemoveAllBloodParticles() +{ + local int Index; + local KFEmit_DirectionalPath EmitterToRemove; + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + EmitterToRemove = BloodStolenParticles[Index]; + //BloodStolenParticles.Remove(Index, 1); + EmitterToRemove.DeactivateEmitter(); + } +} + +simulated function OnStartFire() +{ + local KFPawn PawnInst; + + PawnInst = KFPawn(Instigator); + if (PawnInst != none) + { + PawnInst.OnStartFire(); + } +} + +simulated function InitBloodBallFX() +{ + if (FullyChargedPSC == none) + { + FullyChargedPSC = new(self) class'ParticleSystemComponent'; + + if(MySkelMesh != none) + { + MySkelMesh.AttachComponentToSocket(FullyChargedPSC, 'MuzzleFlash'); + } + else + { + AttachComponent(FullyChargedPSC); + } + + FullyChargedPSC.SetTemplate(ChargedEffect); + } + + FullyChargedPSC.SetActive( false ); + + if (ChargingPSC == none) + { + ChargingPSC = new(self) class'ParticleSystemComponent'; + + if(MySkelMesh != none) + { + MySkelMesh.AttachComponentToSocket(ChargingPSC, 'MuzzleFlash'); + } + else + { + AttachComponent(ChargingPSC); + } + ChargingPSC.SetTemplate(ChargingEffect); + } + + ChargingPSC.SetActive( false ); +} + +// Placing the actual Weapon Firing end state here since we need it to happen at the end of the actual firing loop. +simulated function Timer_StopFireEffects() +{ + // Simulate weapon firing effects on the local client + if (WorldInfo.NetMode == NM_Client) + { + Instigator.WeaponStoppedFiring(self, false); + } + + ClearFlashCount(); + ClearFlashLocation(); +} + +simulated function name GetLoopEndFireAnim(byte FireModeNum) +{ + if (FireModeNum == DEFAULT_FIREMODE) + { + return ''; + } + + return super.GetLoopEndFireAnim(FireModeNum); +} + +simulated function KFProjectile SpawnProjectile(class KFProjClass, vector RealStartLoc, vector AimDir) +{ + local KFProj_BloodBall_HRG_Vampire BloodBall; + local KFProjectile Projectile; + Projectile = super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir); + BloodBall = KFProj_BloodBall_HRG_Vampire(Projectile); + //Calc and set scaling values + if (BloodBall != none) + { + BloodBall.SetInheritedScale(CurrentChargeForBloodBallProjectile, DamageByChargePercentage); + return BloodBall; + } + //If reaches here, projectile will be CRYSTALIZED SPIKE + return Projectile; +} + +simulated function DisableRecoil() +{ + maxRecoilPitch = 0; + minRecoilPitch = 0; + maxRecoilYaw = 0; + minRecoilYaw = 0; +} + +simulated function RestoreRecoil() +{ + maxRecoilPitch = default.maxRecoilPitch; + minRecoilPitch = default.minRecoilPitch; + maxRecoilYaw = default.maxRecoilYaw; + minRecoilYaw = default.minRecoilYaw; +} + +function InitializeAmmo() +{ + super.InitializeAmmo(); + AmmoCount[1] = InitialAmmoSecondaryCount; +} + +simulated function ConsumeAmmo( byte FireModeNum ) +{ + local byte AmmoType; + local KFPerk InstigatorPerk; + + if (FireModeNum == DEFAULT_FIREMODE) + { + //Code from super.ConsumeAmmo() +`if(`notdefined(ShippingPC)) + if( bInfiniteAmmo ) + { + return; + } +`endif + + AmmoType = GetAmmoType(FireModeNum); + + InstigatorPerk = GetPerk(); + if( InstigatorPerk != none && InstigatorPerk.GetIsUberAmmoActive( self ) ) + { + return; + } + + TimesConsumeAmmoCalled+=AmmoCost[FireModeNum]; + + // If AmmoCount is being replicated, don't allow the client to modify it here + if ( Role == ROLE_Authority || bAllowClientAmmoTracking ) + { + // Don't consume ammo if magazine size is 0 (infinite ammo with no reload) + if (MagazineCapacity[AmmoType] > 0 && AmmoCount[AmmoType] > 0) + { + AmmoCostAccumulated += AmmoCost[FireModeNum] * AmmoCostScaleDefaultFiremode; + CurrentChargeDesired = FMin(1.0, (float(AmmoConsumed) + AmmoCostAccumulated) / MaxChargeAmmo); + if (CurrentChargeDesired > 0) + { + bHasCharged = true; + } + if (WorldInfo.NetMode == NM_DedicatedServer) + { + ClientCurrentChargeDesired = CurrentChargeDesired; + } + + if (AmmoCostAccumulated >= AmmoCost[FireModeNum]) + { + AmmoCostAccumulated=0; + AmmoConsumed+=AmmoCost[CurrentFireMode]; + CurrentChargeDesired = FMin(1.0, float(AmmoConsumed) / MaxChargeAmmo); + if (WorldInfo.NetMode == NM_DedicatedServer) + { + ClientCurrentChargeDesired = CurrentChargeDesired; + } + // Ammo cost needs to be firemodenum because it is independent of ammo type. + AmmoCount[AmmoType] = Max(AmmoCount[AmmoType] - AmmoCost[FireModeNum], 0); + } + } + } + return; + } + else + { + super.ConsumeAmmo(FireModeNum); + } +} + +simulated function Timer_CreateBloodParticle() +{ + if (oZedCurrentlyBeingSprayed != none && oZedCurrentlyBeingSprayed.IsAliveAndWell()) + { + CreateBloodParticle(oZedCurrentlyBeingSprayed); + } +} + +simulated state FiringSuctioning extends SprayingFire +{ + // Overriden to not call FireAmmunition right at the start of the state + simulated event BeginState( Name PreviousStateName ) + { + Super.BeginState(PreviousStateName); + NotifyBeginState(); + if ( KFPawn(Owner).IsLocallyControlled() ) + { + PlaySoundBase(BloodSuctionStartSound.FirstPersonCue); + } + else + { + PlaySoundBase(BloodSuctionStartSound.DefaultCue); + } + CurrentCharge = 0; + bHasCharged = false; + global.OnStartFire(); + + bIsSprayDisabled = false; + AmmoCostScaleDefaultFiremode=default.AmmoCostScaleDefaultFiremode; + CurrentCharge = 0; + CurrentChargeOrigin = 0; + CurrentChargeDesired = 0; + CurrentChargeForBloodBallProjectile = 0; + + if (WorldInfo.NetMode == NM_DedicatedServer) + { + ClientCurrentChargeDesired = 0; + } + TimesConsumeAmmoCalled = 0; + bIsChargingSoundStarted = false; + } + + simulated function EndState(Name NextStateName) + { + local KFPawn_Human KFPH; + + Super.EndState(NextStateName); + NotifyEndState(); + + ClearZedTimeResist(); + ClearPendingFire(CurrentFireMode); + ClearTimer(nameof(RefireCheckTimer)); + + KFPawn(Instigator).bHasStartedFire = false; + KFPawn(Instigator).bNetDirty = true; + + if (oZedCurrentlyBeingSprayed == None || !oZedCurrentlyBeingSprayed.IsAliveAndWell()) + { + if ( KFPawn(Owner).IsLocallyControlled() ) + { + PlaySoundBase(BloodSuctionEndSound.FirstPersonCue); + } + else + { + PlaySoundBase(BloodSuctionEndSound.DefaultCue); + } + } + + KFPawn(Instigator).SetWeaponAmbientSound(none); + KFPawn(Instigator).SetSecondaryWeaponAmbientSound(none); + + //BLOOD PARTICLES AND BALL MANAGEMENT + KFPH = KFPawn_Human(Instigator); + if (!(WorldInfo.NetMode == NM_DedicatedServer) || !(KFPH != none && !KFPH.IsFirstPerson())) + { + RemoveAllBloodParticles(); + CurrentChargeAccumulatedTime = 0; + if( ChargingPSC != none) + { + ChargingPSC.SetActive( false ); + } + if (FullyChargedPSC != none) + { + FullyChargedPSC.SetActive( false ); + } + } + + CurrentChargeForBloodBallProjectile = CurrentChargeDesired; + CurrentCharge = 0; + CurrentChargeOrigin = 0; + CurrentChargeDesired = 0; + } + + simulated function bool ShouldRefire() + { + if (!HasAmmo(CurrentFireMode)) + { + return StillFiring(CurrentFireMode); + } + return StillFiring(CurrentFireMode) || TimesConsumeAmmoCalled < MinAmmoConsumed; + } + + simulated function ConsumeAmmo( byte FireMode ) + { + global.ConsumeAmmo(FireMode); + } + + + simulated event Tick(float DeltaTime) + { + //In this tick enters: + //- Role == Role_Authority + //- WorldInfo.NetMode == NM_DedicatedServer + //- WorldInfo.NetMode == NM_StandAlone + + //Blood particle variables + local int Index; + local vector MuzzleFlashSocketLocation, BloodParticlesMidPointSocketLocation; + local Rotator DestinationRotation, BloodParticlesMidPointSocketRotation; + local KFEmit_DirectionalPath EmitterToRemove; + local vector VectorParameterParticle; + local vector BloodSplashVelocity; + local KFPawn_Human KFPH; + + //Charging variables + local vector ChargePercentageVector; + + local float InstantHitDamageValue; + + + Super.Tick(DeltaTime); + + if (!HasAmmo(CurrentFireMode) && !bIsSprayDisabled) + { + if (CurrentChargeDesired <= 0) + { + GoToState('Active'); + } + else + { + + TurnOffFireSpray(); + KFPawn(Instigator).SetWeaponAmbientSound(BloodSuctionLoopNoAmmoAndBloodBallChargedSound.DefaultCue, BloodSuctionLoopNoAmmoAndBloodBallChargedSound.FirstPersonCue); + KFPawn(Instigator).SetSecondaryWeaponAmbientSound(None, None); + oZedCurrentlyBeingSprayed = none; + DisableRecoil(); + bIsSprayDisabled = true; + bClientDisableSprayVisualAndMesh=true; + } + } + + if(oZedCurrentlyBeingSprayed == none) + { + bIsChargingSoundStarted = false; + KFPawn(Instigator).SetSecondaryWeaponAmbientSound(None, None); + } + if(oZedCurrentlyBeingSprayed != none && oZedCurrentlyBeingSprayed.IsAliveAndWell()) + { + //Replenishing secondary ammo + ReplenishingAmmoOnSuctioningTime -= DeltaTime; + if (ReplenishingAmmoOnSuctioningTime <= 0) + { + AmmoCount[ALTFIRE_FIREMODE] = Min(MagazineCapacity[ALTFIRE_FIREMODE], AmmoCount[ALTFIRE_FIREMODE] + ReplenishingAmmoOnSuctioningCount); + ReplenishingAmmoOnSuctioningTime += ReplenishingAmmoOnSuctioningInterval; + } + + //Scaling damage values depending on charge + if (CurrentChargeDesired > 0) + { + DamageByChargePercentage = FMin((CurrentChargeDesired - MinDamageWhileChargingThreshold)/(1 - MinDamageWhileChargingThreshold), 1); + InstantHitDamageValue = FMax(MinDamageByCharge, Lerp(MinDamageByCharge, MaxDamageByCharge, DamageByChargePercentage )); + InstantHitDamage[CUSTOM_FIREMODE] = InstantHitDamageValue;//TODO + InstantHitDamageTypes[CUSTOM_FIREMODE]=class'KFDT_Ballistic_HRG_Vampire_BloodBallImpact'; + if(CurrentChargeDesired >= 1.0) + { + InstantHitDamageTypes[CUSTOM_FIREMODE]=class'KFDT_Ballistic_HRG_Vampire_BloodBallHeavyImpact'; + } + + KFPawn(Instigator).SetWeaponComponentRTPCValue("Weapon_Charge", CurrentChargeDesired); //For looping component + Instigator.SetRTPCValue('Weapon_Charge', CurrentChargeDesired); //For one-shot sounds + + if (WorldInfo.NetMode == NM_DedicatedServer) + { + ClientChargePercentage = CurrentChargeDesired; + } + if (!bIsChargingSoundStarted) + { + KFPawn(Instigator).SetSecondaryWeaponAmbientSound(ChargingSound.DefaultCue, ChargingSound.FirstPersonCue); + } + bIsChargingSoundStarted = true; + } + } + + //BLOOD PARTICLES AND BALL MANAGEMENT + KFPH = KFPawn_Human(Instigator); + if (WorldInfo.NetMode == NM_DedicatedServer || (KFPH != none && !KFPH.IsFirstPerson())) + { + return; + } + + //Blood Ball and Blood Particles are managed here for 1P offline and 1P online. + + //Blood particles updating destination and removing, and spawning blood splashes. + + UpdateDestinationBloodParticlesTime -= DeltaTime; + if (UpdateDestinationBloodParticlesTime <= 0) + { + UpdateDestinationBloodParticlesTime = RateUpdateDestinationBloodParticles; + GetFlameSocketLocAndRot(MuzzleFlashSocketLocation, DestinationRotation); + if(MySkelMesh != none) + { + MySkelMesh.GetSocketWorldLocationAndRotation('BloodParticlesMidPoint', BloodParticlesMidPointSocketLocation, BloodParticlesMidPointSocketRotation); + } + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + + if (!BloodStolenParticles[Index].IsEnabled || BloodStolenParticles[Index] == None) + { + continue; + } + if( BloodStolenParticles[Index].bReachDestinationFinal ) + { + + EmitterToRemove = BloodStolenParticles[Index]; + //BloodStolenParticles.Remove(Index, 1); + EmitterToRemove.DeactivateEmitter(); + + + } + else + { + if (BloodStolenParticles[Index].ParticleSystemComponent != None) + { + VectorParameterParticle.X = WorldInfo.TimeDilation; + VectorParameterParticle.Y = WorldInfo.TimeDilation; + VectorParameterParticle.Z = WorldInfo.TimeDilation; + BloodStolenParticles[Index].ParticleSystemComponent.SetVectorParameter( name("ZedtimeScale"), VectorParameterParticle ); + } + BloodStolenParticles[Index].UpdateDestination( MuzzleFlashSocketLocation, BloodParticlesMidPointSocketLocation ); + + if (FRand() > 0.8) + { + BloodSplashVelocity.x = 0; + BloodSplashVelocity.y = RandRange(-100, 100); + BloodSplashVelocity.z = -200; + + SpawnBloodSplash(BloodSplashClass, BloodStolenParticles[Index].Location, BloodSplashVelocity); + } + } + } + + } + + for( Index = (NumBloodStolenParticlesForPool - 1) ; Index >= 0 ; Index-- ) + { + if(BloodStolenParticles[Index].IsEnabled == true) + { + bFirstBloodParticleCreated=true; + } + } + CurrentStartChargingTime = FMax(0, CurrentStartChargingTime - DeltaTime); + + if (CurrentChargeDesired > 0 && CurrentStartChargingTime <= 0) + { + CurrentChargeAccumulatedTime = FMin(CurrentChargeAccumulatedTime + DeltaTime * ChargeSpeed, CurrentChargeDesired); + CurrentCharge = CurrentChargeAccumulatedTime; + } + + if ( CurrentCharge > 0 ) + { + if( ChargingPSC != none) + { + ChargingPSC.SetActive( true, true ); + + ChargePercentageVector.X = CurrentCharge; + ChargePercentageVector.Y = CurrentCharge; + ChargePercentageVector.Z = CurrentCharge; + ChargingPSC.SetVectorParameter( name("BlobCharge"), ChargePercentageVector ); + } + + if (FullyChargedPSC != none && CurrentCharge >= 1.0) + { + if (!bIsFullCharged) + { + //WeaponPlaySound(ChargedSound.FirstPersonCue); + //PlaySoundBase(BloodSuctionEndSound.DefaultCue); + if ( KFPawn(Owner).IsLocallyControlled() ) + { + PlaySoundBase(ChargedSound.FirstPersonCue); + } + else + { + PlaySoundBase(ChargedSound.DefaultCue); + } + } + bIsFullCharged = true; + FullyChargedPSC.SetActive( true, true ); + } + } + } + simulated function HandleFinishedFiring() + { + if (bPlayingLoopingFireAnim) + { + StopLoopingFireEffects(CurrentFireMode); + } + + SetTimer(0.1f, false, 'Timer_StopFireEffects'); + + NotifyWeaponFinishedFiring(CurrentFireMode); + + super.HandleFinishedFiring(); + } + + simulated function PutDownWeapon() + { + if (bPlayingLoopingFireAnim) + { + StopLoopingFireEffects(CurrentFireMode); + } + + SetTimer(0.1f, false, 'Timer_StopFireEffects'); + + NotifyWeaponFinishedFiring(CurrentFireMode); + + super.PutDownWeapon(); + } +} + +simulated state Active +{ + simulated event BeginState( Name PreviousStateName ) + { + local KFPawn KFPawn; + local KFWeapAttach_HRG_Vampire KFWeapAttach; + + //Safest place to start firing Blood Ball (after finishing all logic for Blood Suck firing) + + if (PreviousStateName == 'FiringSuctioning' && Role == Role_Authority && bHasCharged) + { + StartFire(CUSTOM_FIREMODE); + } + + super.BeginState(PreviousStateName); + + RestoreRecoil(); + bClientDisableSprayVisualAndMesh = false; + bHasCharged = false; + bIsFullCharged = false; + + if (WorldInfo.NetMode == NM_DedicatedServer || bIsAlreadyInitializedFX) + { + return; + } + + //All of the following would make more sense to initialize it in PostBeginPlay, but at that moment KFPawn.WeaponAttachment and MySkelMesh are not populated + //Setting parameters for blood particles from 3P attachment + KFPawn = KFPawn(Instigator); + KFWeapAttach = KFWeapAttach_HRG_Vampire(KFPawn.WeaponAttachment); + if (KFWeapAttach != None) + { + SpeedBloodParticles = KFWeapAttach.SpeedBloodParticles; + SpawnRateBloodParticles = KFWeapAttach.SpawnRateBloodParticles; + HalfAngleSpawnCone = KFWeapAttach.HalfAngleSpawnCone; + CurveTurnRateUntilDestinationMidPoint = KFWeapAttach.CurveTurnRateUntilDestinationMidPoint; + CurveTurnRateUntilDestinationFinal = KFWeapAttach.CurveTurnRateUntilDestinationFinal; + LimitDistanceMidPoint = KFWeapAttach.LimitDistanceMidPoint; + LimitDistanceFinalPoint = KFWeapAttach.LimitDistanceFinalPoint; + } + + if (SpeedBloodParticles <= 0) + { + SpeedBloodParticles = SpeedBloodParticlesDefault; + } + if (SpawnRateBloodParticles <= 0) + { + SpawnRateBloodParticles = SpawnRateBloodParticlesDefault; + } + if (HalfAngleSpawnCone <= 0) + { + HalfAngleSpawnCone = HalfAngleSpawnConeDefault; + } + if (CurveTurnRateUntilDestinationMidPoint <= 0) + { + CurveTurnRateUntilDestinationMidPoint = CurveTurnRateUntilDestinationMidPointDefault; + } + if (CurveTurnRateUntilDestinationFinal <= 0) + { + CurveTurnRateUntilDestinationFinal = CurveTurnRateUntilDestinationFinalDefault; + } + if (LimitDistanceMidPoint <= 0) + { + LimitDistanceMidPoint = LimitDistanceMidPointDefault; + } + if (LimitDistanceFinalPoint <= 0) + { + LimitDistanceFinalPoint = LimitDistanceFinalPointDefault; + } + + if (KFPawn != none && !KFPawn.IsFirstPerson()) + { + return; + } + InitBloodBallFX(); + SetTimer(SpawnRateBloodParticles, true, nameOf(Timer_CreateBloodParticle)); + bIsAlreadyInitializedFX = true; + } +} + + +simulated function PerformReload(optional byte FireModeNum) +{ + super.PerformReload(FireModeNum); + + //Ammo is count on server. If reload finishes in client before ammo value comes from server, it will not fire if it is pending fire. This is a fix. + if(role != role_authority && WorldInfo.NetMode != NM_ListenServer && WorldInfo.NetMode != NM_StandAlone) + { + SetTimer(0.09f, true, nameOf(Timer_CheckPendingFire)); + SetTimer(0.5f, false, nameOf(Timer_EndCheckPendingFire)); + } + +} + +simulated function Timer_CheckPendingFire() +{ + local int i; + for( i=0; i= Amount; +} + + simulated state MineReconstructorCharge extends WeaponFiring { //For minimal code purposes, I'll directly call global.FireAmmunition after charging is released diff --git a/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhino.uc b/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhino.uc index 511cc62..fec5029 100644 --- a/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhino.uc +++ b/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhino.uc @@ -62,7 +62,7 @@ defaultproperties WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Pistol_ChiappaRhino' FireInterval(DEFAULT_FIREMODE)=+0.175 - InstantHitDamage(DEFAULT_FIREMODE)=70.0 + InstantHitDamage(DEFAULT_FIREMODE)=75.0 //70.0 InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_ChiappaRhino' PenetrationPower(DEFAULT_FIREMODE)=2.0 Spread(DEFAULT_FIREMODE)=0.01 diff --git a/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhinoDual.uc b/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhinoDual.uc index 17db23c..1178b19 100644 --- a/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhinoDual.uc +++ b/KFGameContent/Classes/KFWeap_Pistol_ChiappaRhinoDual.uc @@ -66,7 +66,7 @@ defaultproperties WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Pistol_ChiappaRhino' FireInterval(DEFAULT_FIREMODE)=+0.1 - InstantHitDamage(DEFAULT_FIREMODE)=70.0 + InstantHitDamage(DEFAULT_FIREMODE)=75.0 //70.0 InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_ChiappaRhino' PenetrationPower(DEFAULT_FIREMODE)=2.0 Spread(DEFAULT_FIREMODE)=0.01 @@ -78,7 +78,7 @@ defaultproperties WeaponFireTypes(ALTFIRE_FIREMODE)= EWFT_Projectile WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_Pistol_ChiappaRhino' FireInterval(ALTFIRE_FIREMODE)=+0.1 - InstantHitDamage(ALTFIRE_FIREMODE)=70.0 + InstantHitDamage(ALTFIRE_FIREMODE)=75.0 //70.0 InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_ChiappaRhino' PenetrationPower(ALTFIRE_FIREMODE)=2.0 Spread(ALTFIRE_FIREMODE)=0.01 diff --git a/KFGameContent/Classes/KFWeap_Rifle_FrostShotgunAxe.uc b/KFGameContent/Classes/KFWeap_Rifle_FrostShotgunAxe.uc new file mode 100644 index 0000000..42a80ac --- /dev/null +++ b/KFGameContent/Classes/KFWeap_Rifle_FrostShotgunAxe.uc @@ -0,0 +1,381 @@ +//============================================================================= +// KFWeap_Rifle_FrostShotgunAxe +//============================================================================= +// A Rifle with an axe that freezes enemies +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2019 Tripwire Interactive LLC +//============================================================================= + +class KFWeap_Rifle_FrostShotgunAxe extends KFWeap_MeleeBase; + +var float LastFireInterval; +var int iInstantHitDamageOnEnemyFrozen; +var int iNormalInstantHitDamage; + +/** Returns trader filter index based on weapon type */ +static simulated event EFilterTypeUI GetTraderFilter() +{ + return FT_Rifle; +} + +simulated event PreBeginPlay() +{ + super.PreBeginPlay(); + iNormalInstantHitDamage = InstantHitDamage[BASH_FIREMODE]; +} + +/** + * See Pawn.ProcessInstantHit + * @param DamageReduction: Custom KF parameter to handle penetration damage reduction + */ +simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optional int NumHits, optional out float out_PenetrationVal, optional int ImpactNum) +{ + local KFPerk InstigatorPerk; + + InstigatorPerk = GetPerk(); + if (InstigatorPerk != none) + { + InstigatorPerk.UpdatePerkHeadShots(Impact, InstantHitDamageTypes[FiringMode], ImpactNum); + } + + super.ProcessInstantHitEx(FiringMode, Impact, NumHits, out_PenetrationVal, ImpactNum); +} + +/** process local player impact for clientside hit detection */ +event RecieveClientImpact(byte FiringMode, const out ImpactInfo Impact, optional out float PenetrationValue, optional int ImpactNum) +{ + // skip KFWeap_MeleeBase because it does melee stuff + super(KFWeapon).RecieveClientImpact(FiringMode, Impact, PenetrationValue, ImpactNum); +} + +/** Override melee SetIronSights (which sends to heavy attack) so that this weapon ironsights normally*/ +simulated function SetIronSights(bool bNewIronSights) +{ + super(KFWeapon).SetIronSights(bNewIronSights); +} + +/** Override melee ShouldOwnerWalk which doesn't account for walking when in ironsights */ +simulated function bool ShouldOwnerWalk() +{ + return super(KFWeapon).ShouldOwnerWalk(); +} + +/** Save off the start time for the bash to determine whether this will be a normal stab or a bullet stab */ +simulated function StartFire(byte FireModeNum) +{ + // copying over auto reload functionality since MeleeBase overrides this by default + if (FireModeNum == DEFAULT_FIREMODE && ShouldAutoReload(FireModeNum)) + { + FireModeNum = RELOAD_FIREMODE; + } + + if (FireModeNum == RELOAD_FIREMODE) + { + // Skip Super/ ServerStartFire and let server wait for ServerSendToReload to force state synchronization + BeginFire(FireModeNum); + return; + } + if( FireModeNum == BASH_FIREMODE && WeaponFireTypes[FireModeNum] == EWFT_Custom ) + { + super.StartMeleeFire(FireModeNum, MeleeAttackHelper.ChooseAttackDir(), ATK_Normal); + return; + } + super.StartFire(FireModeNum); +} + +/** Override to drop the player out of ironsights first */ +simulated function AltFireMode() +{ + if (!Instigator.IsLocallyControlled()) + { + return; + } + + // break out of ironsights when starting to block + if (bUsingSights) + { + SetIronSights(false); + } + + StartFire(BLOCK_FIREMODE); +} + +simulated state MeleeBlocking +{ + simulated function BeginState(name PreviousStateName) + { + super.BeginState(PreviousStateName); + if (bUsingSights) + { + SetIronSights(false); + } + } + simulated function bool AllowIronSights() { return false; } +} + +simulated function float GetFireInterval(byte FireModeNum) +{ + if (FireModeNum == DEFAULT_FIREMODE && AmmoCount[FireModeNum] == 0) + { + return LastFireInterval; + } + + return super.GetFireInterval(FireModeNum); +} + +/** Called during reload state */ +simulated function bool CanOverrideMagReload(byte FireModeNum) +{ + if (FireModeNum == BLOCK_FIREMODE) + { + return true; + } + + return super.CanOverrideMagReload(FireModeNum); +} + +/** returns the damage amount for this attack */ +simulated function int GetMeleeDamage(byte FireModeNum, optional vector RayDir) +{ + local KFMeleeHelperWeaponFrostShotgunAxe oHelper; + local int Damage; + oHelper = KFMeleeHelperWeaponFrostShotgunAxe(MeleeAttackHelper); + if(oHelper.IsEnemyIced()) + { + InstantHitDamage[FireModeNum] = iInstantHitDamageOnEnemyFrozen; + } + else + { + InstantHitDamage[FireModeNum] = iNormalInstantHitDamage; + } + Damage = Super.GetMeleeDamage(FireModeNum, RayDir); + return Damage; +} + + + +simulated function int GetModifiedDamage(byte FireModeNum, optional vector RayDir) +{ + switch(FireModeNum) + { + case DEFAULT_FIREMODE: + return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage0 , CurrentWeaponUpgradeIndex); + break; + case ALTFIRE_FIREMODE: + return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage1 , CurrentWeaponUpgradeIndex); + break; + case BASH_FIREMODE: + return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage2 , CurrentWeaponUpgradeIndex); + break; + } + return GetUpgradedStatValue(InstantHitDamage[FireModeNum], EWUS_Damage0 , CurrentWeaponUpgradeIndex); +} + +/** Allows weapon to calculate its own damage for display in trader */ +static simulated function float CalculateTraderWeaponStatDamage() +{ + local float BaseDamage, DoTDamage; + local class DamageType; + + BaseDamage = default.InstantHitDamage[DEFAULT_FIREMODE]; + + DamageType = class(default.InstantHitDamageTypes[DEFAULT_FIREMODE]); + if (DamageType != none && DamageType.default.DoT_Type != DOT_None) + { + DoTDamage = (DamageType.default.DoT_Duration / DamageType.default.DoT_Interval) * (BaseDamage * DamageType.default.DoT_DamageScale); + } + + return BaseDamage * default.NumPellets[DEFAULT_FIREMODE] + DoTDamage; +} + +/** Allows weapon to calculate its own fire rate for display in trader */ +static simulated function float CalculateTraderWeaponStatFireRate() +{ + return 60.f / default.FireInterval[DEFAULT_FIREMODE]; // attacks per minute +} + +/** Spawn projectile is called once for each shot pellet fired */ +simulated function KFProjectile SpawnAllProjectiles(class KFProjClass, vector RealStartLoc, vector AimDir) +{ + local KFPerk InstigatorPerk; + + if (CurrentFireMode == GRENADE_FIREMODE) + { + return Super.SpawnProjectile(KFProjClass, RealStartLoc, AimDir); + } + + InstigatorPerk = GetPerk(); + if (InstigatorPerk != none) + { + Spread[CurrentFireMode] = default.Spread[CurrentFireMode] * InstigatorPerk.GetTightChokeModifier(); + } + + return super.SpawnAllProjectiles(KFProjClass, RealStartLoc, AimDir); +} + +/** Plays a 'settle' animation after a melee attack is finished */ +simulated function PlayMeleeSettleAnim() +{ + PlayAnimation(MeleeAttackSettleAnims[0], 0.0, false, 0.1); +} + +defaultproperties +{ + // MeleeBase + bMeleeWeapon=true + + // Inventory / Grouping + InventoryGroup=IG_Primary + InventorySize=7 + GroupPriority=80 //75 + WeaponSelectTexture = Texture2D'WEP_UI_Frost_Shotgun_Axe_TEX.UI_WeaponSelect_FrostGun' + // Perks + AssociatedPerkClasses(0)=class'KFPerk_Support' + AssociatedPerkClasses(1)=class'KFPerk_Berserker' + + // FOV + MeshFOV=65 + MeshIronSightFOV=45 + PlayerIronSightFOV=65 + + // Depth of field + DOF_FG_FocalRadius=50 + DOF_FG_MaxNearBlurSize=3.5 + + // Content + PackageKey = "Frost_Shotgun_Axe" + FirstPersonMeshName="WEP_1P_Frost_Shotgun_Axe_MESH.Wep_1stP_Frost_Shotgun_Axe_Rig" + FirstPersonAnimSetNames(0)="WEP_1P_Frost_Shotgun_Axe_ANIM.WEP_1stP_Frost_Shotgun_Axe" + PickupMeshName="WEP_3P_Frost_Shotgun_Axe_MESH.Wep_3rdP_Frost_Shotgun_Pickup" + AttachmentArchetypeName="WEP_Frost_Shotgun_Axe_ARCH.Wep_Frost_Shotgun_Axe_3P" + MuzzleFlashTemplateName="WEP_Frost_Shotgun_Axe_ARCH.Wep_Frost_Shotgun_Axe_MuzzleFlash" + + // Ammo + MagazineCapacity[0]=6 + SpareAmmoCapacity[0]=66 + InitialSpareMags[0]=4 + AmmoPickupScale[0]=1 + bCanBeReloaded=true + bReloadFromMagazine=false // @TODO: Turn off once animations are done + + // Zooming/Position + PlayerViewOffset = (X = 8.0,Y = 7,Z = -3.5) + IronSightPosition = (X = 0,Y = 0,Z = 0) + + // AI warning system + bWarnAIWhenAiming = true + AimWarningDelay = (X = 0.4f, Y = 0.8f) + AimWarningCooldown = 0.0f + + // Recoil + maxRecoilPitch = 1050 //550 + minRecoilPitch = 900 //400 + maxRecoilYaw = 350 //150 + minRecoilYaw = -350 //-150 + RecoilRate = 0.075 + RecoilMaxYawLimit = 500 + RecoilMinYawLimit = 65035 + RecoilMaxPitchLimit = 900 + RecoilMinPitchLimit = 64785 + RecoilISMaxYawLimit = 50 + RecoilISMinYawLimit = 65485 + RecoilISMaxPitchLimit = 500 + RecoilISMinPitchLimit = 65485 + RecoilViewRotationScale = 0.6 + + FallingRecoilModifier=1.5 + HippedRecoilModifier=1.3 + + IronSightMeshFOVCompensationScale = 1.5 + + // DEFAULT_FIREMODE + FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle' + FiringStatesArray(DEFAULT_FIREMODE)=WeaponSingleFiring + WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile + WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Frost_Shotgun_Axe' + InstantHitDamage(DEFAULT_FIREMODE)=30 //32 //30 + InstantHitDamageTypes(DEFAULT_FIREMODE) = class'KFDT_Ballistic_Frost_Shotgun_Axe' + FireInterval(DEFAULT_FIREMODE)=0.5 //0.25 // 240 RPM + Spread(DEFAULT_FIREMODE)=0.13 //0.007 + PenetrationPower(DEFAULT_FIREMODE)=2 + FireOffset = (X = 25,Y = 3.0,Z = -2.5) + NumPellets(DEFAULT_FIREMODE)=7 + AmmoCost(DEFAULT_FIREMODE)=1 + LastFireInterval=0.5 + + // RELOAD_FIREMODE + FiringStatesArray(RELOAD_FIREMODE)="Reloading" + WeaponFireTypes(RELOAD_FIREMODE)=EWFT_InstantHit + + // BASH_FIREMODE + InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Slashing_Frost_Shotgun_Axe' + InstantHitDamage(BASH_FIREMODE)=75 //120 + FiringStatesArray(BASH_FIREMODE)=MeleeChainAttacking + WeaponFireTypes(BASH_FIREMODE)=EWFT_Custom + InstantHitMomentum(BASH_FIREMODE)=10000.f + iInstantHitDamageOnEnemyFrozen = 185 //360; //300; + + // Custom animations + FireSightedAnims = (Shoot_Iron) + BonesToLockOnEmpty = (RW_Hammer) + bHasFireLastAnims = true + + // Defensive + BlockDamageMitigation=0.6f + ParryDamageMitigationPercent=0.5 + ParryStrength=4 + + // Block Effects + BlockSound=AkEvent'WW_WEP_Bullet_Impacts.Play_Block_MEL_Hammer' + ParrySound=AkEvent'WW_WEP_Bullet_Impacts.Play_Parry_Wood' + + // Fire Effects + WeaponFireSnd(DEFAULT_FIREMODE) = (DefaultCue = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Shoot_3p', FirstPersonCue = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Shoot_1p') // @TODO: Replace Me + WeaponDryFireSnd(DEFAULT_FIREMODE) = AkEvent'WW_WEP_FrostFang.Play_FrostFang_Dryfire' // @TODO: Replace Me + EjectedShellForegroundDuration = 1.5f + + // Attachments + bHasIronSights = true + bHasFlashlight = false + + WeaponFireWaveForm = ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Medium_Recoil' + + // Aim Assist + AimCorrectionSize=40.f + + // Melee + + + // Melee hitbox + Begin Object Class=KFMeleeHelperWeaponFrostShotgunAxe Name=MeleeHelper_0 + MaxHitRange=250 + HitboxChain.Add((BoneOffset=(X=+3,Z=-190))) + HitboxChain.Add((BoneOffset=(X=-3,Z=-170))) + HitboxChain.Add((BoneOffset=(X=+3,Z=-150))) + HitboxChain.Add((BoneOffset=(X=-3,Z=-130))) + HitboxChain.Add((BoneOffset=(X=+3,Z=-110))) + HitboxChain.Add((BoneOffset=(X=-3,Z=-90))) + HitboxChain.Add((BoneOffset=(X=+3,Z=-70))) + HitboxChain.Add((BoneOffset=(X=-3,Z=-50))) + HitboxChain.Add((BoneOffset=(X=+3,Z=-30))) + HitboxChain.Add((BoneOffset=(Z=10))) + WorldImpactEffects=KFImpactEffectInfo'FX_Impacts_ARCH.Bladed_melee_impact' + MeleeImpactCamShakeScale=0.03f + bUseDirectionalMelee=true + bHasChainAttacks=true + bUseMeleeHitTimer=false + // modified combo sequences + ChainSequence_F=(DIR_Left, DIR_ForwardRight, DIR_ForwardLeft, DIR_ForwardRight, DIR_ForwardLeft) + ChainSequence_B=(DIR_BackwardRight, DIR_ForwardLeft, DIR_BackwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right, DIR_Left) + ChainSequence_L=(DIR_Right, DIR_Left, DIR_ForwardRight, DIR_ForwardLeft, DIR_Right, DIR_Left) + ChainSequence_R=(DIR_Left, DIR_Right, DIR_ForwardLeft, DIR_ForwardRight, DIR_Left, DIR_Right) + End Object + MeleeAttackHelper=MeleeHelper_0 + + // Weapon Upgrades + WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.125f), (Stat=EWUS_Damage1, Scale=1.125f), (Stat=EWUS_Damage2, Scale=1.1f), (Stat=EWUS_Weight, Add=1))) + WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.25f), (Stat=EWUS_Damage1, Scale=1.25f), (Stat=EWUS_Damage2, Scale=1.2f), (Stat=EWUS_Weight, Add=2))) + + bHasToBeConsideredAsRangedWeaponForPerks=true; +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeap_RocketLauncher_SealSqueal.uc b/KFGameContent/Classes/KFWeap_RocketLauncher_SealSqueal.uc index fe7e8b8..52957e9 100644 --- a/KFGameContent/Classes/KFWeap_RocketLauncher_SealSqueal.uc +++ b/KFGameContent/Classes/KFWeap_RocketLauncher_SealSqueal.uc @@ -157,7 +157,7 @@ simulated function PrepareAndDetonate() PlayAnimation(SelectedAnim, AnimDuration); } else - { + { PlayAnimation(SelectedAnim); } } @@ -170,7 +170,8 @@ simulated function PrepareAndDetonate() // Don't want to play muzzle effects or shoot animation on detonate in 3p //IncrementFlashCount(); - AnimDuration = 1.f; + //AnimDuration value here representes the ALTFIRE FireInterval + AnimDuration = 0.75f; //1.f; if (bInSprintState) { SetTimer(AnimDuration * 0.8f, false, nameof(PlaySprintStart)); @@ -223,6 +224,17 @@ function RemoveDeployedHarpoon(optional int HarpoonIndex = INDEX_NONE, optional } } +/** Allow reloads for primary weapon to be interupted by firing secondary weapon. */ +simulated function bool CanOverrideMagReload(byte FireModeNum) +{ + if(FireModeNum == ALTFIRE_FIREMODE) + { + return true; + } + + return Super.CanOverrideMagReload(FireModeNum); +} + defaultproperties { // Content @@ -234,7 +246,7 @@ defaultproperties MuzzleFlashTemplateName="WEP_Seal_Squeal_ARCH.Wep_Seal_Squeal_MuzzleFlash" //@TODO: Replace me // Inventory / Grouping - InventorySize=8 + InventorySize=7 //8 GroupPriority=75 WeaponSelectTexture=Texture2D'WEP_UI_Seal_Squeal_TEX.UI_WeaponSelect_SealSqueal' AssociatedPerkClasses(0)=class'KFPerk_Demolitionist' @@ -250,7 +262,7 @@ defaultproperties // Ammo MagazineCapacity[0]=5 - SpareAmmoCapacity[0]=25 + SpareAmmoCapacity[0]=30 //25 InitialSpareMags[0]=1 bCanBeReloaded=true bReloadFromMagazine=true @@ -288,13 +300,12 @@ defaultproperties WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Rocket_SealSqueal' InstantHitDamage(DEFAULT_FIREMODE)=125 InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_SealSquealImpact' - FireInterval(DEFAULT_FIREMODE)=0.75 + FireInterval(DEFAULT_FIREMODE)=0.5 //0.75 Spread(DEFAULT_FIREMODE)=0 PenetrationPower(DEFAULT_FIREMODE)=0 FireOffset=(X=25,Y=3.0,Z=-2.5) // ALTFIRE_FIREMODE (remote detonate) - //FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle' FiringStatesArray(ALTFIRE_FIREMODE)=WeaponDetonating WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Custom AmmoCost(ALTFIRE_FIREMODE)=0 diff --git a/WebAdmin/Classes/QHCurrent.uc b/WebAdmin/Classes/QHCurrent.uc index 252dd36..300263c 100644 --- a/WebAdmin/Classes/QHCurrent.uc +++ b/WebAdmin/Classes/QHCurrent.uc @@ -109,6 +109,8 @@ var array playerActions; */ var bool separateSpectators; +var array notAllowedBanConsoleCommands; + function init(WebAdmin webapp) { local class achc; @@ -783,7 +785,8 @@ 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") @@ -820,53 +823,10 @@ function int handleCurrentPlayersAction(WebAdminQuery q) } `endif - else if (action ~= "banip" || action ~= "ban ip") + else if (action ~= "banip" || action ~= "ban ip" || action ~= "banid" || action ~= "ban unique id" || action ~= "banhash" || + action ~= "ban client hash" || action ~= "sessionban" || action ~= "session ban") { - 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.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.addMessage(q, repl(msgPlayerRemoved, "%s", PRI.PlayerName)); - return 1; + webadmin.addMessage(q, msgNotAllowed, MT_Error); } } } @@ -1195,6 +1155,7 @@ function handleConsole(WebAdminQuery q) local bool denied; cmd = q.request.getVariable("command"); + if (len(cmd) > 0) { denied = false; @@ -1206,6 +1167,15 @@ function handleConsole(WebAdminQuery q) break; } } + for (i = 0; i < notAllowedBanConsoleCommands.length; i++) + { + if (notAllowedBanConsoleCommands[i] ~= locs(cmd) || InStr(locs(cmd)$" ", notAllowedBanConsoleCommands[i]$" ") >= 0) + { + denied = true; + break; + } + } + if (!denied) { @@ -1730,10 +1700,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") } diff --git a/WebAdmin/Classes/QHDefaults.uc b/WebAdmin/Classes/QHDefaults.uc index 4c57fc6..b4195c2 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."$Caps(Left(policy, idx)), "selected=\"selected\""); + //q.response.subst("policy.policy", `HTMLEscape(Left(policy, idx))); + q.response.subst("policy.selected", `HTMLEscape(Left(policy, idx))); policies $= webadmin.include(q, "policy_row.inc"); q.response.subst("policy.selected."$Caps(Left(policy, idx)), ""); }