diff --git a/Engine/Classes/AccessControl.uc b/Engine/Classes/AccessControl.uc index b1f650c..06421f4 100644 --- a/Engine/Classes/AccessControl.uc +++ b/Engine/Classes/AccessControl.uc @@ -857,6 +857,7 @@ function PendingAuthTimer() if (ClientsPendingAuth[i].AuthRetryCount < MaxAuthRetryCount) { // End the auth session first before retrying + `Log("RETRYING CONNECTION - AuthRetryCount: " $ClientsPendingAuth[i].AuthRetryCount $" WHEN MAX CONNECTIONS ARE " $MaxAuthRetryCount); CachedAuthInt.EndRemoteClientAuthSession(CurClientSession.EndPointUID, CurClientSession.EndPointIP); // Get the client to end it on his end too (this should execute on client before the new auth request below) @@ -865,11 +866,13 @@ function PendingAuthTimer() // Start the new auth session if (CachedAuthInt.SendClientAuthRequest(ClientsPendingAuth[i].ClientConnection, CurClientSession.EndPointUID)) { + `Log("NEW CLIENT AUTH REQUEST SENT - SUCCESS"); ClientsPendingAuth[i].AuthTimestamp = WorldInfo.RealTimeSeconds; ClientsPendingAuth[i].AuthRetryCount++; } else { + `Log("NEW CLIENT AUTH REQUEST SENT - FAIL"); bFailed = True; } } @@ -1111,6 +1114,7 @@ function OnClientAuthComplete(bool bSuccess, UniqueNetId ClientUID, Player Clien { `log("Client failed authentication (unauthenticated UID:"@ Class'OnlineSubsystem'.static.UniqueNetIdToString(ClientUID)$"), kicking"); + `Log("Client Auth failure info: " $ExtraInfo); // Kick the client WorldInfo.Game.RejectLogin(ClientConnection, "Authentication failed"); @@ -1201,6 +1205,8 @@ function ProcessServerAuthRetryRequest(Player ClientConnection) local AuthSession CurClientSession; local LocalAuthSession CurServerSession; + `Log("PROCESS SERVER AUTH RETRY REQUEST - " $bAuthenticateServer $" - " $ ClientConnection != none); + if (bAuthenticateServer && ClientConnection != none) { bFoundAndAuthenticated = CachedAuthInt.FindClientAuthSession(ClientConnection, CurClientSession) && @@ -1386,6 +1392,8 @@ function EndListenHostAuth() local IpAddr ServerIP; local int ServerPort; //@HSL_END_XBOX + + `Log("EndListenHostAuth"); if (OnlineSub.PlayerInterface != none) { @@ -1489,6 +1497,7 @@ static final function StaticOnClientConnectionClose(Player ClientConnection) if (CurAuthInt != none && ClientConnection != none) { + `Log("StaticOnClientConnectionClose"); // If the client is authenticated, end the client auth session if (CurAuthInt.FindClientAuthSession(ClientConnection, CurClientSession) && CurClientSession.AuthStatus == AUS_Authenticated) { @@ -1548,6 +1557,7 @@ function OnDestroyOnlineGameComplete(name SessionName, bool bWasSuccessful) { if (CurClientSession.AuthStatus == AUS_Authenticated) { + `Log("OnDestroyOnlineGameComplete"); // End the client auth session CachedAuthInt.EndRemoteClientAuthSession(CurClientSession.EndPointUID, CurClientSession.EndPointIP); @@ -1638,6 +1648,7 @@ function Cleanup(optional bool bExit) // If the game is exiting, end all auth sessions if (bExit) { + `Log("AccessControl CLEAN UP"); // End all remote client auth sessions CachedAuthInt.EndAllRemoteClientAuthSessions(); diff --git a/KFGame/Classes/KFAISpawnManager.uc b/KFGame/Classes/KFAISpawnManager.uc index f1a383a..18f63aa 100644 --- a/KFGame/Classes/KFAISpawnManager.uc +++ b/KFGame/Classes/KFAISpawnManager.uc @@ -227,6 +227,11 @@ function SetupNextWave(byte NextWaveIndex, int TimeToNextWaveBuffer = 0) { local KFGameReplicationInfo KFGRI; + if (OutbreakEvent.ActiveEvent.bBossRushMode) + { + NextWaveIndex = MyKFGRI.WaveMax - 1; + } + if( NextWaveIndex < WaveSettings.Waves.Length ) { // Recycle special squads on higher difficulties @@ -250,7 +255,7 @@ function SetupNextWave(byte NextWaveIndex, int TimeToNextWaveBuffer = 0) // Initialize our recycle number NumSpecialSquadRecycles = 0; - if (MyKFGRI.IsBossWave()) + if (MyKFGRI.IsBossWave() || OutbreakEvent.ActiveEvent.bBossRushMode) { WaveTotalAI = 1; } @@ -383,7 +388,8 @@ function GetSpawnListFromSquad(byte SquadIdx, out array< KFAISpawnSquad > Squads local ESquadType LargestMonsterSquadType; local array > TempSpawnList; local class ForcedPawnClass; - + local int RandBossIndex; + Squad = SquadsList[SquadIdx]; // Start with the smallest size, and the crank it up if the squad is larger @@ -421,7 +427,17 @@ function GetSpawnListFromSquad(byte SquadIdx, out array< KFAISpawnSquad > Squads else `endif //Always have the squad type be a boss if we're spawning one in case of override - TempSpawnList.AddItem(GetBossAISpawnType()); + if (OutbreakEvent.ActiveEvent.bBossRushMode) + { + RandBossIndex = Rand(BossRushEnemies.length); + TempSpawnList.AddItem( default.AIBossClassList[BossRushEnemies[RandBossIndex]]); + BossRushEnemies.Remove(RandBossIndex, 1); + } + else + { + TempSpawnList.AddItem(GetBossAISpawnType()); + } + LargestMonsterSquadType = EST_Boss; } else diff --git a/KFGame/Classes/KFAutoPurchaseHelper.uc b/KFGame/Classes/KFAutoPurchaseHelper.uc index 27634df..cdc47a9 100644 --- a/KFGame/Classes/KFAutoPurchaseHelper.uc +++ b/KFGame/Classes/KFAutoPurchaseHelper.uc @@ -375,17 +375,26 @@ function bool CanUpgrade(STraderItem SelectedItem, out int CanCarryIndex, out in function PurchaseWeapon(STraderItem ShopItem) { local int ItemUpgradeLevel; + local KFPlayerController KFPC; + local int Price; if(!bCanPurchase(ShopItem, true)) { return; } + Price = GetAdjustedBuyPriceFor(ShopItem); + // XMAS 2021 Seasonal Objective + KFPC = Outer; + `Log("ADDING WEAPON PURCHASED"); + KFPC.AddWeaponPurchased(ShopItem.WeaponDef, Price); + // + ItemUpgradeLevel = ShopItem.SingleClassName != '' ? GetItemUpgradeLevelByClassName(ShopItem.SingleClassName) : INDEX_None; - AddDosh(-GetAdjustedBuyPriceFor(ShopItem)); + AddDosh(-Price); AddBlocks(MyKFIM.GetWeaponBlocks(ShopItem, ItemUpgradeLevel)); AddWeaponToOwnedItemList(ShopItem); } @@ -539,7 +548,7 @@ function bool AttemptBuyArmorChunk( out int InAutoFillDosh ) InAutoFillDosh -= ChunkCost; PercentArmorBought = (PercentArmorBought > 0.f && PercentArmorBought < 1.f) ? 1.f : PercentArmorBought; - ArmorItem.SpareAmmoCount = FMin(ArmorItem.SpareAmmoCount + (PercentArmorBought / 100.f * ArmorItem.MaxSpareAmmo), ArmorItem.MaxSpareAmmo); + ArmorItem.SpareAmmoCount = FMin(ArmorItem.SpareAmmoCount + PercentArmorBought, ArmorItem.MaxSpareAmmo); BoughtAmmo(PercentArmorBought, ChunkCost, EIT_Armor); } @@ -1181,7 +1190,7 @@ function SetWeaponInfo(const KFWeapon KFW, STraderItem DefaultItem) WeaponInfo.AmmoPricePerMagazine = AmmoCostScale * DefaultItem.WeaponDef.default.AmmoPricePerMag; WeaponInfo.SellPrice = GetAdjustedSellPriceFor(DefaultItem); - + WeaponInfo.DefaultItem.bCanBuyAmmo = KFW.CanBuyAmmo(); AddItemByPriority( WeaponInfo ); // if adding a dual, remove the related single diff --git a/KFGame/Classes/KFCharacterInfo_Monster.uc b/KFGame/Classes/KFCharacterInfo_Monster.uc index f1a7229..267bedc 100644 --- a/KFGame/Classes/KFCharacterInfo_Monster.uc +++ b/KFGame/Classes/KFCharacterInfo_Monster.uc @@ -139,6 +139,12 @@ var string ZEDCowboyHatMeshPath; var transient LinearColor WWLHatMonoChromeValue; var transient LinearColor WWLHatColorValue; +/************************************************************************/ +/* Tiny Skulls Weekly */ +/************************************************************************/ + +var float TinySkullPitchAudio; + /************************************************************************/ /* Script Functions */ /************************************************************************/ @@ -167,6 +173,8 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic if( CharacterMesh != none ) { + KFGRI = KFGameReplicationInfo(KFP.WorldInfo.GRI); + // Clear character customization settings KFP.DetachComponent(KFP.ThirdPersonHeadMeshComponent); for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ ) @@ -188,7 +196,16 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic KFP.Mesh.SetSkeletalMesh(CharacterMesh); } KFP.Mesh.SetScale(DefaultMeshScale); - KFP.PitchAudio(DefaultMeshScale); + + if (KFP != none && KFGRI.bIsWeeklyMode && KFGRI.CurrentWeeklyIndex == 15) + { + KFP.PitchAudio(TinySkullPitchAudio); + } + else + { + KFP.PitchAudio(DefaultMeshScale); + } + // Use material specified in the mesh asset // @note: need to add this if we allow character swap post-spawn (e.g. customization) @@ -256,7 +273,6 @@ simulated function SetCharacterMeshFromArch( KFPawn KFP, optional KFPlayerReplic } } - KFGRI = KFGameReplicationInfo(KFP.WorldInfo.GRI); if (KFP != none && KFGRI.bIsWeeklyMode && (class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 12)) { NewAttachment.StaticAttachment = StaticMesh(DynamicLoadObject(ZEDCowboyHatMeshPath, class'StaticMesh')); @@ -325,4 +341,5 @@ defaultproperties WWLHatColorValue=(R=1.0f,G=0.0f,B=0.0f) ZEDCowboyHatMeshPath = "CHR_CosmeticSet01_MESH.cowboyhat.CHR_CowboyHat_Alberts_Cosmetic" + TinySkullPitchAudio = 0.5f; } diff --git a/KFGame/Classes/KFCheatManager.uc b/KFGame/Classes/KFCheatManager.uc index 1d84007..277805c 100644 --- a/KFGame/Classes/KFCheatManager.uc +++ b/KFGame/Classes/KFCheatManager.uc @@ -764,6 +764,17 @@ exec function DebugShowVoteSkipTrader() } } +exec function DebugShowVotePauseGame() +{ + local KFPlayerReplicationInfo KFPRI; + KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo); + + if (KFPlayerController(Outer).MyGFxHUD != none && KFPRI != None) + { + KFPlayerController(Outer).RequestPauseGame(); + } +} + exec function ToggleForceCrosshair() { KFHudBase(MyHud).bForceDrawCrosshair = !KFHudBase(MyHud).bForceDrawCrosshair; diff --git a/KFGame/Classes/KFDroppedPickup.uc b/KFGame/Classes/KFDroppedPickup.uc index 0c8c1c4..2d7a4dd 100644 --- a/KFGame/Classes/KFDroppedPickup.uc +++ b/KFGame/Classes/KFDroppedPickup.uc @@ -385,6 +385,13 @@ function GiveTo(Pawn P) local class KFWInvClass; local Inventory NewInventory; local KFInventoryManager KFIM; + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + if (KFGRI != none && KFGRI.bIsEndlessPaused) + { + return; + } KFIM = KFInventoryManager(P.InvManager); if (KFIM != None) diff --git a/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2021.uc b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2021.uc new file mode 100644 index 0000000..ec37b36 --- /dev/null +++ b/KFGame/Classes/KFGFXSpecialEventObjectivesContainer_Xmas2021.uc @@ -0,0 +1,27 @@ +class KFGFXSpecialEventObjectivesContainer_Xmas2021 extends KFGFxSpecialEventObjectivesContainer; + +function Initialize(KFGFxObject_Menu NewParentMenu) +{ + super.Initialize(NewParentMenu); +} + +DefaultProperties +{ + ObjectiveIconURLs[0] = "Xmas2021_UI.Heads_For_Sale" // Decapitate 1000 Zeds on any map or mode + ObjectiveIconURLs[1] = "Xmas2021_UI.Black_Weekly" // Complete the Weekly on Carillon Hamlet + ObjectiveIconURLs[2] = "Xmas2021_UI.Filthy_Rich" // Earn 75,000 Dosh through kills, rewards and healing on Carillon Hamlet + ObjectiveIconURLs[3] = "Xmas2021_UI.Painful_Payments" // Use the trader to purchase a total of 20 weapons that cost 1500 Dosh or more on Carrion Hamlet. + ObjectiveIconURLs[4] = "Xmas2021_UI.Nonstop_Splurge" // Complete wave 15 on Endless Hard or higher difficulty on Carillon Hamlet + + //defaults + AllCompleteRewardIconURL="CHR_CosmeticSet_XMAS_05_Item_TEX.shopping_companion.holidayshoppingcompanion_precious" + ChanceDropIconURLs[0]="CHR_Cosmetic_XMAS_Item_TEX.Tickets.Krampus_Ticket" + ChanceDropIconURLs[1]="CHR_Cosmetic_XMAS_Item_TEX.Tickets.Krampus_Ticket_Golden" + IconURL="Xmas2021_UI.KF2_SmallLogo" + + UsesProgressList[0] = true + UsesProgressList[1] = false + UsesProgressList[2] = true + UsesProgressList[3] = true + UsesProgressList[4] = false +} \ No newline at end of file diff --git a/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc b/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc index e999f43..927e07c 100644 --- a/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc +++ b/KFGame/Classes/KFGFxHUD_PlayerBackpack.uc @@ -182,6 +182,15 @@ function UpdateWeapon() SetInt("backpackStoredAmmo" , CurrentSpareAmmo); LastSpareAmmo = CurrentSpareAmmo; } + + /** + Reusing this variable for showing the dosh icon for doshinegun. + Only FAMAS uses bUsesSecondaryAmmoAltHUD and for it bUsesSecondaryAmmo is true + */ + if (!bUsesSecondaryAmmo && CurrentWeapon.bUsesSecondaryAmmoAltHUD) + { + SetBool("doshAmmoIcon", true); + } } else { diff --git a/KFGame/Classes/KFGFxMoviePlayer_HUD.uc b/KFGame/Classes/KFGFxMoviePlayer_HUD.uc index 9463a8a..911e5f1 100644 --- a/KFGame/Classes/KFGFxMoviePlayer_HUD.uc +++ b/KFGame/Classes/KFGFxMoviePlayer_HUD.uc @@ -80,6 +80,7 @@ var GFxObject KFGXHUDManager; var bool bIsSkipTraderVoteActive; var bool bIsKickVoteActive; var bool bUserAlreadyStartASkipTraderVote; +var bool bIsPauseGameVoteActive; var bool bIsSpectating; var bool bIsVisible; @@ -1144,7 +1145,7 @@ function OpenChatBox() } //============================================================== -// Kick and Skip Trader Vote +// Kick, Skip Trader and Pause Game Vote //============================================================== function ShowKickVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowChoices) @@ -1152,8 +1153,9 @@ function ShowKickVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowCh if(KickVoteWidget != none) { bIsSkipTraderVoteActive = false; - bIsKickVoteActive = true; - KickVoteWidget.ShowVote(PRI, VoteDuration, bShowChoices, bIsSkipTraderVoteActive); + bIsPauseGameVoteActive = false; + bIsKickVoteActive = true; + KickVoteWidget.ShowVote(PRI, VoteDuration, bShowChoices, VT_KICK); } } @@ -1163,6 +1165,7 @@ simulated function HideKickVote() { bIsSkipTraderVoteActive = false; bIsKickVoteActive = false; + bIsPauseGameVoteActive = false; KickVoteWidget.VoteClosed(); } } @@ -1181,7 +1184,8 @@ function ShowSkipTraderVote(PlayerReplicationInfo PRI, byte VoteDuration, bool b { bIsSkipTraderVoteActive = true; bIsKickVoteActive = false; - KickVoteWidget.ShowVote(PRI, VoteDuration, bShowChoices, bIsSkipTraderVoteActive); + bIsPauseGameVoteActive = false; + KickVoteWidget.ShowVote(PRI, VoteDuration, bShowChoices, VT_SKIP_TRADER); } } @@ -1199,6 +1203,7 @@ simulated function HideSkipTraderVote() { bIsSkipTraderVoteActive = false; bIsKickVoteActive = false; + bIsPauseGameVoteActive = false; KickVoteWidget.VoteClosed(); } } @@ -1211,6 +1216,49 @@ function UpdateSkipTraderVoteCount(byte YesVotes, byte NoVotes) } } +function ShowPauseGameVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowChoices) +{ + local KFGameReplicationInfo KFGRI; + KFGRI=KFGameReplicationInfo(KFPC.WorldInfo.GRI); + + if (KickVoteWidget != none) + { + bIsPauseGameVoteActive = true; + bIsKickVoteActive = false; + bIsSkipTraderVoteActive = false; + KickVoteWidget.ShowVote(PRI, VoteDuration, bShowChoices, (KFGRI != none && KFGRI.bIsEndlessPaused) ? VT_RESUME_GAME : VT_PAUSE_GAME); + } +} + +function UpdatePauseGameTime(byte VoteDuration) +{ + if(KickVoteWidget != none) + { + KickVoteWidget.UpdateVoteDuration(VoteDuration); + } +} + +simulated function HidePauseGameVote() +{ + if(KickVoteWidget != none) + { + bIsPauseGameVoteActive = false; + bIsKickVoteActive = false; + bIsSkipTraderVoteActive = false; + KickVoteWidget.VoteClosed(); + } +} + +function UpdatePauseGameVoteCount(byte YesVotes, byte NoVotes) +{ + if(KickVoteWidget != none) + { + `Log("UPDATING PAUSE GAME VOTE COUNT - YES: "$YesVotes); + `Log("UPDATING PAUSE GAME VOTE COUNT - NO: "$NoVotes); + KickVoteWidget.UpdateVoteCount(YesVotes, NoVotes); + } +} + //============================================================== // Updates //============================================================== @@ -1347,7 +1395,7 @@ function Callback_VoiceCommsSelection( int CommsIndex ) } } -function Callback_VoteKick(bool bKickOrSkip) +function Callback_VoteKick(bool Vote) { local KFPlayerReplicationInfo KFPRI; @@ -1355,11 +1403,15 @@ function Callback_VoteKick(bool bKickOrSkip) if(bIsSkipTraderVoteActive) { - KFPRI.CastSkipTraderVote(KFPRI, bKickOrSkip); + KFPRI.CastSkipTraderVote(KFPRI, Vote); } + else if(bIsPauseGameVoteActive) + { + KFPRI.CastPauseGameVote(KFPRI, Vote); + } else { - KFPRI.CastKickVote(KFPRI, bKickOrSkip); + KFPRI.CastKickVote(KFPRI, Vote); } if(KickVoteWidget != none) diff --git a/KFGame/Classes/KFGFxPostGameContainer_MapVote.uc b/KFGame/Classes/KFGFxPostGameContainer_MapVote.uc index 73b22e8..ff63b49 100644 --- a/KFGame/Classes/KFGFxPostGameContainer_MapVote.uc +++ b/KFGame/Classes/KFGFxPostGameContainer_MapVote.uc @@ -44,30 +44,40 @@ function SetMapOptions() local int i, Counter; local array ServerMapList; local KFGameReplicationInfo KFGRI; + local bool IsWeeklyMode; local bool IsBrokenTrader; + local bool IsBossRush; KFGRI = KFGameReplicationInfo(GetPC().WorldInfo.GRI); Counter = 0; if(KFGRI != none && KFGRI.VoteCollector != none) { - ServerMapList = KFGRI.VoteCollector.MapList; - IsBrokenTrader = KFGRI.IsA('KFGameReplicationInfo_WeeklySurvival') && class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 11; - + ServerMapList = KFGRI.VoteCollector.MapList; + IsWeeklyMode = KFGRI.bIsWeeklyMode; + IsBrokenTrader = KFGRI.CurrentWeeklyIndex == 11; + IsBossRush = KFGRI.CurrentWeeklyIndex == 14; //gfx MapList = CreateArray(); for (i = 0; i < ServerMapList.length; i++) { - if (IsBrokenTrader && ( ServerMapList[i] == "KF-Biolapse" || - ServerMapList[i] == "KF-Nightmare" || - ServerMapList[i] == "KF-PowerCore_Holdout" || - ServerMapList[i] == "KF-TheDescent" || - ServerMapList[i] == "KF-KrampusLair")) + if ( IsWeeklyMode && (IsBrokenTrader || IsBossRush) && ( ServerMapList[i] == "KF-Biolapse" || + ServerMapList[i] == "KF-Nightmare" || + ServerMapList[i] == "KF-PowerCore_Holdout" || + ServerMapList[i] == "KF-TheDescent" || + ServerMapList[i] == "KF-KrampusLair")) { continue; } + /* Temporary removal of SteamFrotress for BossRush */ + if (IsWeeklyMode && IsBossRush && ServerMapList[i] == "KF-SteamFortress") + { + continue; + } + /**/ + MapObject = CreateObject("Object"); MapObject.SetString("label", class'KFCommon_LocalizedStrings'.static.GetFriendlyMapName(ServerMapList[i]) ); MapObject.SetString("mapSource", GetMapSource(ServerMapList[i]) ); diff --git a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc index d8f2f57..d551bf4 100644 --- a/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc +++ b/KFGame/Classes/KFGFxStartGameContainer_FindGame.uc @@ -182,31 +182,31 @@ function FillWhatsNew() local SWhatsNew item; WhatsNewItems.Remove(0, WhatsNewItems.Length); // Latest Update - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_DayOfTheZED_Event", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_ChopTilYouDrop", "LatestUpdate", "http://www.tripwireinteractive.com/redirect/KF2LatestUpdate/"); WhatsNewItems.AddItem(item); // KF2 Armory Season Pass 2021 item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Spring_Armory_Season_Pass", "ArmorySeasonPass", "https://store.steampowered.com/app/1524820/Killing_Floor_2__Armory_Season_Pass"); WhatsNewItems.AddItem(item); // Featured Time Limited Item - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/9119"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Christmas_PremiumTicket", "FeaturedEventItem", "https://store.steampowered.com/buyitem/232090/5588"); WhatsNewItems.AddItem(item); -// Featured Cosmetic Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_DoZ", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9120"); +// Featured Full Gear + item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_FullGearBundle_DoZ", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9119"); WhatsNewItems.AddItem(item); -// Featured Cosmetic Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_Vietnam","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/9122"); +// Featured Outfit Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Xmas_Holiday_Shopper", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9263"); WhatsNewItems.AddItem(item); // Featured Weapon Skin Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_Hellmark", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9121"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Xmas_Christmas", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9264"); + WhatsNewItems.AddItem(item); +// Featured Weapon Skin Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Xmas_Alchemist_Weapon_Skin", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9265"); + WhatsNewItems.AddItem(item); +// Featured Cosmetic Bundle + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Xmas_Alchemist","FeaturedItemBundle","https://store.steampowered.com/buyitem/232090/9266"); WhatsNewItems.AddItem(item); // Featured Weapon Bundle - item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_PiranhaPistol", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9123"); - WhatsNewItems.AddItem(item); -// Featured Weapon Bundle - item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_Halloween_CorrupterCarbine", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9124"); - WhatsNewItems.AddItem(item); - // Featured Weapon Bundle - item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_halloween_Weaponsbundle", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9125"); + item = SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_XMAS_Doshinegun", "FeaturedItemBundle", "https://store.steampowered.com/buyitem/232090/9267"); WhatsNewItems.AddItem(item); // Misc Community Links item=SetWhatsNewItem("img://UI_WhatsNew.UI_WhatsNew_CommunityHub", "Jaegorhorn", "https://steamcommunity.com/app/232090"); diff --git a/KFGame/Classes/KFGFxStartGameContainer_Options.uc b/KFGame/Classes/KFGFxStartGameContainer_Options.uc index 1d5ac6c..601ba03 100644 --- a/KFGame/Classes/KFGFxStartGameContainer_Options.uc +++ b/KFGame/Classes/KFGFxStartGameContainer_Options.uc @@ -264,13 +264,17 @@ function InitializeGameOptions() function FilterWeeklyMaps(out array List) { + local int WeeklyIndex; + if (ParentMenu.Manager.GetModeIndex(false) != EGameMode_Weekly) { return; } // Scavenger index = 11 - if (class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 11) + // BossRush index = 14 + WeeklyIndex = class'KFGameEngine'.static.GetWeeklyEventIndexMod(); + if (WeeklyIndex == 11 || WeeklyIndex == 14) { List.RemoveItem("KF-Biolapse"); List.RemoveItem("KF-Nightmare"); @@ -278,6 +282,14 @@ function FilterWeeklyMaps(out array List) List.RemoveItem("KF-TheDescent"); List.RemoveItem("KF-KrampusLair"); } + + /* Temporary removal of SteamFrotress for BossRush */ + if (WeeklyIndex == 14) + { + List.RemoveItem("KF-SteamFortress"); + } + /**/ + } function GFxObject CreateList( array TextArray, byte SelectedIndex, bool bAddNoPrefString, optional bool bIsMapList, optional byte MaxLength) diff --git a/KFGame/Classes/KFGFxStoreContainer_Main.uc b/KFGame/Classes/KFGFxStoreContainer_Main.uc index 62173e9..33f8400 100644 --- a/KFGame/Classes/KFGFxStoreContainer_Main.uc +++ b/KFGame/Classes/KFGFxStoreContainer_Main.uc @@ -454,6 +454,7 @@ DefaultProperties FeaturedItemIDs[4]=9122 FeaturedItemIDs[5]=9123 FeaturedItemIDs[6]=9124 + FeaturedItemIDs[7]=9125 ConsoleFeaturedItemIDs[0]=7783 //Whatsnew Gold Ticket PSN ConsoleFeaturedItemIDs[1]=9119 @@ -462,6 +463,7 @@ DefaultProperties ConsoleFeaturedItemIDs[4]=9122 ConsoleFeaturedItemIDs[5]=9123 ConsoleFeaturedItemIDs[6]=9124 + ConsoleFeaturedItemIDs[7]=9125 MaxFeaturedItems=5 } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxTraderContainer_PlayerInventory.uc b/KFGame/Classes/KFGFxTraderContainer_PlayerInventory.uc index d521672..4be8076 100644 --- a/KFGame/Classes/KFGFxTraderContainer_PlayerInventory.uc +++ b/KFGame/Classes/KFGFxTraderContainer_PlayerInventory.uc @@ -117,9 +117,9 @@ function RefreshPlayerInventory() PricePerRound = ( MagSize > 0 ) ? float(PricePerMag) / float(MagSize) : 0.f; BlocksRequired = -1; // This will hide the weight and - SetItemInfo( InfoSlot, ItemInfo.DefaultItem.WeaponDef, "SecondaryAmmo", TextureLocation, AmmoCount, MaxAmmoCount, BlocksRequired, true ); - SetMagInfo( MagSlot, AmmoCount, MaxAmmoCount, MagSize, PricePerMag, PricePerRound, FillAmmoCost ); - SetFillInfo( FillSlot, AmmoCount, MaxAmmoCount, PricePerRound, FillAmmoCost, AutoFillCost ); + SetItemInfo( InfoSlot, ItemInfo.DefaultItem.WeaponDef, "SecondaryAmmo", TextureLocation, AmmoCount, MaxAmmoCount, BlocksRequired, true, 0, ItemInfo.DefaultItem.bCanBuyAmmo); + SetMagInfo( MagSlot, AmmoCount, MaxAmmoCount, MagSize, PricePerMag, PricePerRound, FillAmmoCost, ItemInfo.DefaultItem.bCanBuyAmmo); + SetFillInfo( FillSlot, AmmoCount, MaxAmmoCount, PricePerRound, FillAmmoCost, AutoFillCost, ItemInfo.DefaultItem.bCanBuyAmmo ); } else { @@ -132,9 +132,9 @@ function RefreshPlayerInventory() PricePerRound = ( MagSize > 0 ) ? float(PricePerMag) / float(MagSize) : 0.f; BlocksRequired = MyTraderMenu.GetDisplayedBlocksRequiredFor(ItemInfo.DefaultItem, ItemInfo.ItemUpgradeLevel); - SetItemInfo( InfoSlot, ItemInfo.DefaultItem.WeaponDef, "ItemName", TextureLocation, AmmoCount, MaxAmmoCount, BlocksRequired, false, KFPC.GetPurchaseHelper().GetItemUpgradeLevelByClassName(ItemInfo.DefaultItem.ClassName) ); - SetMagInfo( MagSlot, AmmoCount, MaxAmmoCount, MagSize, PricePerMag, PricePerRound, FillAmmoCost ); - SetFillInfo( FillSlot, AmmoCount, MaxAmmoCount, PricePerRound, FillAmmoCost, AutoFillCost ); + SetItemInfo( InfoSlot, ItemInfo.DefaultItem.WeaponDef, "ItemName", TextureLocation, AmmoCount, MaxAmmoCount, BlocksRequired, false, KFPC.GetPurchaseHelper().GetItemUpgradeLevelByClassName(ItemInfo.DefaultItem.ClassName), ItemInfo.DefaultItem.bCanBuyAmmo ); + SetMagInfo( MagSlot, AmmoCount, MaxAmmoCount, MagSize, PricePerMag, PricePerRound, FillAmmoCost, ItemInfo.DefaultItem.bCanBuyAmmo ); + SetFillInfo( FillSlot, AmmoCount, MaxAmmoCount, PricePerRound, FillAmmoCost, AutoFillCost, ItemInfo.DefaultItem.bCanBuyAmmo ); } SetSellInfo(SellSlot, ItemInfo.SellPrice, ItemInfo.SellPrice > 0); @@ -173,7 +173,7 @@ function SetArmorInfo(out SItemInformation ArmorInfo, out int AutoFillCost) SlotObject.SetString("itemAmmo", ArmorInfo.SpareAmmoCount$"/"$ArmorInfo.MaxSpareAmmo); SlotObject.SetBool("lowAmmo", (ArmorInfo.MaxSpareAmmo > 0) ? (float(ArmorInfo.SpareAmmoCount) / float(ArmorInfo.MaxSpareAmmo)) <= LowAmmoPercentThreshold : false); - ButtonState = GetButtonState( ArmorInfo.AmmoPricePerMagazine, ArmorInfo.SpareAmmoCount, ArmorInfo.MaxSpareAmmo ); + ButtonState = GetButtonState( ArmorInfo.AmmoPricePerMagazine, ArmorInfo.SpareAmmoCount, ArmorInfo.MaxSpareAmmo, true ); SlotObject.Setint("buttonState", ButtonState ); SlotObject.Setint("magButtonState", ButtonState ); @@ -201,7 +201,7 @@ function SetGrenadeInfo(out SItemInformation GrenadeInfo, out int AutoFillCost) SlotObject.SetInt("fillCost", FillCost); SlotObject.SetBool("lowAmmo", (GrenadeInfo.MaxSpareAmmo > 0) ? (float(GrenadeInfo.SpareAmmoCount) / float(GrenadeInfo.MaxSpareAmmo)) <= LowAmmoPercentThreshold : false); SlotObject.SetString("itemAmmo", GrenadeInfo.SpareAmmoCount $"/"$GrenadeInfo.MaxSpareAmmo); - ButtonState = GetButtonState(AmmoPricePerMagazine, GrenadeInfo.SpareAmmoCount, GrenadeInfo.MaxSpareAmmo); + ButtonState = GetButtonState(AmmoPricePerMagazine, GrenadeInfo.SpareAmmoCount, GrenadeInfo.MaxSpareAmmo, true); SlotObject.Setint("magButtonState", ButtonState); SlotObject.Setint("fillButtonState", ButtonState); @@ -210,12 +210,12 @@ function SetGrenadeInfo(out SItemInformation GrenadeInfo, out int AutoFillCost) AutoFillCost += FillCost; } -function SetItemInfo(out GFxObject InfoSlot, class WeaponDef, string ItemKeyString, string TextureLocation, int AmmoCount, int MaxAmmoCount, int BlocksRequired, optional bool bSecondaryAmmo, optional int UpgradeLevel ) +function SetItemInfo(out GFxObject InfoSlot, class WeaponDef, string ItemKeyString, string TextureLocation, int AmmoCount, int MaxAmmoCount, int BlocksRequired, optional bool bSecondaryAmmo, optional int UpgradeLevel, optional bool bCanBuyAmmo = true ) { local string ItemTexPath; InfoSlot.SetString( "itemName", WeaponDef.static.GetItemLocalization(ItemKeyString) ); - InfoSlot.SetString( "itemAmmo", AmmoCount $"/" $MaxAmmoCount); + InfoSlot.SetString( "itemAmmo", AmmoCount $"/" $(bCanBuyAmmo ? MaxAmmoCount : 0 )); InfoSlot.Setint( "itemWeight", BlocksRequired ); InfoSlot.Setint("weaponTier", UpgradeLevel); @@ -226,7 +226,7 @@ function SetItemInfo(out GFxObject InfoSlot, class WeaponDef InfoSlot.SetString( "itemSource", ItemTexPath ); } -function SetMagInfo(out GFxObject MagSlot, int AmmoCount, int MaxAmmoCount, byte AmmoMagSize, int PricePerMag, float PricePerRound, int FillAmmoCost) +function SetMagInfo(out GFxObject MagSlot, int AmmoCount, int MaxAmmoCount, byte AmmoMagSize, int PricePerMag, float PricePerRound, int FillAmmoCost, bool bCanBuyAmmo) { local int MagCost; local bool bBuyPartialMag; @@ -236,14 +236,14 @@ function SetMagInfo(out GFxObject MagSlot, int AmmoCount, int MaxAmmoCount, byte MagSlot.SetString("label", MagString); MagSlot.SetInt("buttonValue", MagCost); - MagSlot.SetInt("buttonState", GetButtonState( PricePerRound, AmmoCount, MaxAmmoCount)); + MagSlot.SetInt("buttonState", GetButtonState( PricePerRound, AmmoCount, MaxAmmoCount, bCanBuyAmmo)); } -function SetFillInfo(out GFxObject FillSlot, int AmmoCount, int MaxAmmoCount, float PricePerRound, int FillAmmoCost, out int AutoFillCost) +function SetFillInfo(out GFxObject FillSlot, int AmmoCount, int MaxAmmoCount, float PricePerRound, int FillAmmoCost, out int AutoFillCost, bool bCanBuyAmmo) { FillSlot.SetString("label", FillString); FillSlot.SetInt("buttonValue", FillAmmoCost); - FillSlot.SetInt("buttonState", GetButtonState( PricePerRound, AmmoCount, MaxAmmoCount )); + FillSlot.SetInt("buttonState", GetButtonState( PricePerRound, AmmoCount, MaxAmmoCount, bCanBuyAmmo )); AutoFillCost += FillAmmoCost; } @@ -265,15 +265,15 @@ function SetAutoFill(int AutoFillCost) AutoFillObject.SetInt("buttonValue", AutoFillCost); // Only disable this button if we have all the ammo - AutoFillObject.SetInt("buttonState", GetButtonState(0, 0, AutoFillCost)); + AutoFillObject.SetInt("buttonState", GetButtonState(0, 0, AutoFillCost, true)); SetObject("autoFillCost", AutoFillObject); } // Change the look of the button dependant on if we can afford it, or are at max capacity -function int GetButtonState( float Price, int SpareAmmoCount, int MaxSpareAmmoCount ) +function int GetButtonState( float Price, int SpareAmmoCount, int MaxSpareAmmoCount, bool bCanBuyAmmo ) { - if ( SpareAmmoCount >= MaxSpareAmmoCount ) + if ( SpareAmmoCount >= MaxSpareAmmoCount || !bCanBuyAmmo) { return BS_MaxCapacity; } diff --git a/KFGame/Classes/KFGFxWidget_BaseParty.uc b/KFGame/Classes/KFGFxWidget_BaseParty.uc index 5defaaa..f0e4b62 100644 --- a/KFGame/Classes/KFGFxWidget_BaseParty.uc +++ b/KFGame/Classes/KFGFxWidget_BaseParty.uc @@ -16,6 +16,8 @@ var localized string PartyLeaderSearchingForMatchString, PartyLeaderIsUpdatingMa var localized string PartHostLeftString, PartyLeaderChangedString; var localized string DownLoadingString, RemainingString; var localized string MatchOverString;//text used to tell the player the match is over +var localized string PauseGameString; +var localized string ResumeGameString; var OnlineSubsystem OnlineSub; var TWOnlineLobby OnlineLobby; @@ -35,6 +37,7 @@ var GFxObject CreatePartyButton; var GFxObject SquadHeader; var GFxObject Notification; var GFxObject MatchStartContainer; +var GFxObject EndlessPauseButton; var int PlayerSlots; @@ -80,6 +83,8 @@ function InitializeWidget() ReadyButton = GetObject("readyButton"); SquadHeader = GetObject("squadHeader"); MatchStartContainer = GetObject("matchStartContainer"); + EndlessPauseButton = GetObject("endlessPauseButton"); + InitNotificationUI(); LocalizeText(); @@ -87,11 +92,15 @@ function InitializeWidget() UpdateInLobby(Manager.IsInLobby()); RefreshParty(); SetBool("matchOver", false); + + SetBool("endlessPauseButtonVisible", false); } function LocalizeText() { local GFxObject TextObject; + local KFGameReplicationInfo KFGRI; + local WorldInfo TempWorldInfo; TextObject = CreateObject("Object"); @@ -103,6 +112,16 @@ function LocalizeText() TextObject.SetString("selectPromptString", Localize("KFGFxWidget_ButtonPrompt", "ConfirmString", "KFGame")); TextObject.SetString("backPromptString", Localize("KFGFxWidget_ButtonPrompt", "CancelString", "KFGame")); TextObject.SetString("matchOver", MatchOverString); + + TempWorldInfo = class'WorldInfo'.static.GetWorldInfo(); + if ( TempWorldInfo != none && TempWorldInfo.GRI != none ) + { + KFGRI = KFGameReplicationInfo(TempWorldInfo.GRI); + if ( KFGRI != none ) + { + SetString("endlessPauseString", KFGRI.bIsEndlessPaused ? ResumeGameString : PauseGameString); + } + } SetObject("localizedText", TextObject); } @@ -170,7 +189,6 @@ function CreatePlayerOptions(UniqueNetId PlayerID, int SlotIndex) KFGRI.GetKFPRIArray(PRIs); } } - DataProvider = CreateArray(); OptionIndex=0; diff --git a/KFGame/Classes/KFGFxWidget_KickVote.uc b/KFGame/Classes/KFGFxWidget_KickVote.uc index 5855c36..aaf34ee 100644 --- a/KFGame/Classes/KFGFxWidget_KickVote.uc +++ b/KFGame/Classes/KFGFxWidget_KickVote.uc @@ -13,8 +13,11 @@ class KFGFxWidget_KickVote extends GFxObject; var localized string VoteKickString; var localized string VoteSkipTraderString; var localized string VoteSkipTraderDetailString; +var localized string VotePauseGameString; +var localized string VotePauseGameDetailString; +var localized string VoteResumeGameString; +var localized string VoteResumeGameDetailString; var bool bIsVoteActive; -var bool bIsSkipTraderVoteActive; var bool bShowChoicesOnTimerUpdate; var const string GBA_VoteYes; @@ -22,12 +25,23 @@ var const string GBA_VoteNo; var GFxObject KickVoteData; +enum EVoteType +{ + VT_NONE, + VT_KICK, + VT_SKIP_TRADER, + VT_PAUSE_GAME, + VT_RESUME_GAME +}; + +var EVoteType CurrentActiveVote; + function InitializeHUD() { //LocalizeText(); } -function LocalizeText(bool bIsSkipTraderVote) +function LocalizeText(EVoteType Type) { local GFxObject TempObject; local KFPlayerInput KFInput; @@ -46,14 +60,7 @@ function LocalizeText(bool bIsSkipTraderVote) TempObject.SetString("yes", Class'KFCommon_LocalizedStrings'.default.YesString); TempObject.SetString("no", Class'KFCommon_LocalizedStrings'.default.NoString); - if(bIsSkipTraderVote) - { - TempObject.SetString("voteKick", VoteSkipTraderString); - } - else - { - TempObject.SetString("voteKick", VoteKickString); - } + TempObject.SetString("voteKick", GetVoteString(Type)); SetObject("localizedText", TempObject); } @@ -65,19 +72,20 @@ function ResetVote() ActionScriptVoid("onNoReleased"); } -function ShowVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowChoices, bool bIsSkipTraderVote) +function ShowVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowChoices, EVoteType Type) { if(PRI != none) { - LocalizeText(bIsSkipTraderVote); //Added this here if the user changes their keybind, it will update + LocalizeText(Type); //Added this here if the user changes their keybind, it will update bIsVoteActive = true; - bIsSkipTraderVoteActive = bIsSkipTraderVote; + + CurrentActiveVote = Type; SendVoteToAS3(PRI.PlayerName, VoteDuration, bShowChoices); } else { bIsVoteActive = false; - bIsSkipTraderVoteActive = false; + CurrentActiveVote = VT_NONE; } } @@ -88,14 +96,7 @@ function SendVoteToAS3(string PlayerName, byte VoteDuration, bool bShowChoices) KickVoteData = CreateObject("Object"); } - if(bIsSkipTraderVoteActive) - { - KickVoteData.SetString("playerName", PlayerName@VoteSkipTraderDetailString); - } - else - { - KickVoteData.SetString("playerName", PlayerName); - } + KickVoteData.SetString("playerName", GetVotePlayerDataString(PlayerName, CurrentActiveVote)); KickVoteData.SetInt("voteDuration", VoteDuration); KickVoteData.SetBool("bShowChoices", bShowChoices); bShowChoicesOnTimerUpdate = bShowChoices; @@ -121,7 +122,7 @@ function UpdateUsingGamepad(bool bIsUsingGamepad) if(!bIsUsingGamepad) { //the gamepad text will show on the input so we need to change it back to keyboard, it is simpler to just relocalize - LocalizeText(bIsSkipTraderVoteActive); + LocalizeText(CurrentActiveVote); } } @@ -168,9 +169,36 @@ function OnNoReleased() } } +function string GetVoteString(EVoteType Type) +{ + switch(Type) + { + case VT_KICK: return VoteKickString; + case VT_SKIP_TRADER: return VoteSkipTraderString; + case VT_PAUSE_GAME: return VotePauseGameString; + case VT_RESUME_GAME: return VoteResumeGameString; + case VT_NONE: `Log("None vote type"); return VoteKickString; + default: `Log("Unkown vote type"); return VoteKickString; + } +} + +function string GetVotePlayerDataString(string PlayerName, EVoteType Type) +{ + switch(Type) + { + case VT_SKIP_TRADER: return PlayerName@VoteSkipTraderDetailString; + case VT_PAUSE_GAME: return PlayerName@VotePauseGameDetailString; + case VT_RESUME_GAME: return PlayerName@VoteResumeGameDetailString; + case VT_KICK: return PlayerName; + case VT_NONE: `Log("None vote type"); return PlayerName; + default: `Log("Unkown vote type"); return PlayerName; + } +} + DefaultProperties { //defaults GBA_VoteYes="GBA_VoteYes" GBA_VoteNo="GBA_VoteNo" + CurrentActiveVote=VT_NONE } \ No newline at end of file diff --git a/KFGame/Classes/KFGFxWidget_PartyInGame.uc b/KFGame/Classes/KFGFxWidget_PartyInGame.uc index 16c3201..95f7ec0 100644 --- a/KFGame/Classes/KFGFxWidget_PartyInGame.uc +++ b/KFGame/Classes/KFGFxWidget_PartyInGame.uc @@ -20,7 +20,8 @@ function InitializeWidget() super.InitializeWidget(); SetReadyButtonVisibility(true); - ReadyButton = GetObject("readyButton"); + ReadyButton = GetObject("readyButton"); + EndlessPauseButton = GetObject("endlessPauseButton"); MyKFPRI = KFPlayerReplicationInfo(GetPC().PlayerReplicationInfo); @@ -31,6 +32,7 @@ function InitializeWidget() } RefreshParty(); UpdateReadyButtonVisibility(); + UpdateEndlessPauseButtonVisibility(); } function UpdateReadyButtonText() @@ -52,6 +54,25 @@ function UpdateReadyButtonText() } } + +function UpdateEndlessPauseButtonText() +{ + local bool bIsConsole; + + if (EndlessPauseButton != none) + { + bIsConsole = GetPC().WorldInfo.IsConsoleBuild(); + if(bIsConsole) + { + EndlessPauseButton.SetString("label", KFGRI.bIsEndlessPaused ? (" "@default.ResumeGameString) : (" "@default.PauseGameString)); + } + else + { + EndlessPauseButton.SetString("label", KFGRI.bIsEndlessPaused ? default.ResumeGameString : default.PauseGameString); + } + } +} + function UpdateReadyButtonVisibility() { if(KFGRI == none) @@ -107,6 +128,39 @@ function UpdateReadyButtonVisibility() } } +function UpdateEndlessPauseButtonVisibility() +{ + if(KFGRI == none) + { + return; + } + + if (MyKFPRI == none) + { + //sanity check because this is happening + MyKFPRI = KFPlayerReplicationInfo(GetPC().PlayerReplicationInfo); + } + + if (GetPC().WorldInfo.NetMode != NM_Standalone && KFGRI.bMatchHasBegun && (MyKFPRI != none && MyKFPRI.bHasSpawnedIn && !KFGRI.bWaveIsActive) && !KFGRI.bMatchIsOver && KFGRI.bEndlessMode) + { + UpdateEndlessPauseButtonText(); + + if (!MyKFPRI.bVotedToPauseGame) + { + SetBool("endlessPauseButtonVisible", true); + } + } + else + { + SetBool("endlessPauseButtonVisible", false); + } + + if (EndlessPauseButton != none) + { + EndlessPauseButton.SetBool("selected", false); + } +} + /**************************************************************************** * Slot Component Updates ****************************************************************************/ @@ -118,6 +172,7 @@ function OneSecondLoop() } RefreshParty(); UpdateReadyButtonVisibility(); + UpdateEndlessPauseButtonVisibility(); } //============================================================== diff --git a/KFGame/Classes/KFGameInfo.uc b/KFGame/Classes/KFGameInfo.uc index 416610e..ec60a29 100644 --- a/KFGame/Classes/KFGameInfo.uc +++ b/KFGame/Classes/KFGameInfo.uc @@ -437,6 +437,11 @@ enum EMonsterProperties var int SpawnedMonsterProperties[EMonsterProperties]; +/** + Boss Rush + */ +var transient array< byte > BossRushEnemies; + /************************************************************************************ * @name Native ***********************************************************************************/ @@ -1636,7 +1641,14 @@ function float GetGameInfoSpawnRateMod() if (OutbreakEvent != none) { - SpawnRateMod *= 1.f / OutbreakEvent.ActiveEvent.SpawnRateMultiplier; + if (OutbreakEvent.ActiveEvent.SpawnRateMultiplier > 0.0f) + { + SpawnRateMod *= 1.f / OutbreakEvent.ActiveEvent.SpawnRateMultiplier; + } + else + { + SpawnRateMod = 0.0f; + } } if (MyKFGRI != none) @@ -2901,19 +2913,29 @@ function string GetNextMap() { MapCycleIndex = MapCycleIndex + 1 < GameMapCycles[ActiveMapCycle].Maps.length ? (MapCycleIndex + 1) : 0; - if ((class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 11 || OutbreakEvent.ActiveEvent == OutbreakEvent.SetEvents[11]) - && MyKFGRI.IsA('KFGameReplicationInfo_WeeklySurvival')) + if (MyKFGRI.IsA('KFGameReplicationInfo_WeeklySurvival')) { - if (GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-Biolapse" || - GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-Nightmare" || - GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-PowerCore_Holdout" || - GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-TheDescent" || - GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-KrampusLair") + if ((class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 11 || OutbreakEvent.ActiveEvent == OutbreakEvent.SetEvents[11]) || // Scavenger + (class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 14 || OutbreakEvent.ActiveEvent == OutbreakEvent.SetEvents[14])) // Boss Rush { + if (GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-Biolapse" || + GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-Nightmare" || + GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-PowerCore_Holdout" || + GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-TheDescent" || + GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-KrampusLair") + { continue; + } } + + /* Temporary removal of SteamFrotress for BossRush */ + if (class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 14 || OutbreakEvent.ActiveEvent == OutbreakEvent.SetEvents[14] && + GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex] == "KF-SteamFortress") + { + continue; + } + /**/ } - if ( IsMapAllowedInCycle(GameMapCycles[ActiveMapCycle].Maps[MapCycleIndex]) ) { @@ -3262,6 +3284,7 @@ function TimeReservations() if (bLogReservations) { `log("KFGameInfo.TimeReservations player" @ i @ class'OnlineSubsystem'.static.UniqueNetIdToString(stupid)@"="@string(PlayerReservations[i].Timer), bLogReservations); + `log("KFGameInfo.TimeReservations Timeout reservations: " $ReservationTimeout); } } ++i; @@ -3771,6 +3794,37 @@ function float GetTraderTime() function SkipTrader(int TimeAfterSkipTrader); +function ResumeEndlessGame() +{ + local KFPawn_Human KFPH; + + foreach WorldInfo.AllPawns( class'KFPawn_Human', KFPH ) + { + if( KFPH.GetTeamNum() != 0 ) + { + KFPH.bCanPickupInventory = true; + } + } + WorldInfo.bPlayersOnly = false; + WorldInfo.bPlayersOnlyPending = false; +} + +function PauseEndlessGame() +{ + local KFPawn_Human KFPH; + + foreach WorldInfo.AllPawns( class'KFPawn_Human', KFPH ) + { + if( KFPH.GetTeamNum() != 0 ) + { + KFPH.bCanPickupInventory = false; + } + } + + // Pause game but allow players to move around. + WorldInfo.bPlayersOnlyPending = true; +} + function bool ShouldOverrideDoshOnKill(class KilledPawn, out float DoshGiven) { return false; diff --git a/KFGame/Classes/KFGameReplicationInfo.uc b/KFGame/Classes/KFGameReplicationInfo.uc index f972c83..f5001f6 100644 --- a/KFGame/Classes/KFGameReplicationInfo.uc +++ b/KFGame/Classes/KFGameReplicationInfo.uc @@ -59,6 +59,8 @@ var class TraderVoiceGroupClass; var repnotify bool bTraderIsOpen; var repnotify bool bWaveIsActive; var repnotify bool bWaveStarted; +var bool bIsEndlessPaused; + /** Replicates at beginning and end of waves to change track / track type */ var repnotify byte MusicTrackRepCount; @@ -68,6 +70,9 @@ var repnotify byte RepKickNoVotes; var repnotify byte RepSkipTraderYesVotes; var repnotify byte RepSkipTraderNoVotes; +var repnotify byte RepPauseGameYesVotes; +var repnotify byte RepPauseGameNoVotes; + /** whether the current game can use stats */ var private const bool bIsUnrankedGame; @@ -348,6 +353,11 @@ var repnotify KFMusicTrackInfo ReplicatedMusicTrackInfo; ************************************/ var transient bool bIsBrokenTrader; +/************************************ + * Weekly Events + ************************************/ +var int CurrentWeeklyIndex; + /************************************ * Steam heartbeat ************************************/ @@ -381,7 +391,7 @@ replication if ( bNetDirty ) TraderVolume, TraderVolumeCheckType, bTraderIsOpen, NextTrader, WaveNum, bWaveIsEndless, AIRemaining, WaveTotalAICount, bWaveIsActive, MaxHumanCount, bGlobalDamage, CurrentObjective, PreviousObjective, PreviousObjectiveResult, PreviousObjectiveXPResult, PreviousObjectiveVoshResult, MusicIntensity, ReplicatedMusicTrackInfo, MusicTrackRepCount, - bIsUnrankedGame, GameSharedUnlocks, bHidePawnIcons, ConsoleGameSessionGuid, GameDifficulty, GameDifficultyModifier, BossIndex, bWaveStarted, NextObjective, bIsBrokenTrader, bIsWeeklyMode; //@HSL - JRO - 3/21/2016 - PS4 Sessions + bIsUnrankedGame, GameSharedUnlocks, bHidePawnIcons, ConsoleGameSessionGuid, GameDifficulty, GameDifficultyModifier, BossIndex, bWaveStarted, NextObjective, bIsBrokenTrader, bIsWeeklyMode, CurrentWeeklyIndex, bIsEndlessPaused; //@HSL - JRO - 3/21/2016 - PS4 Sessions if ( bNetInitial ) GameLength, WaveMax, bCustom, bVersusGame, TraderItems, GameAmmoCostScale, bAllowGrenadePurchase, MaxPerkLevel, bTradersEnabled; if ( bNetInitial || bNetDirty ) @@ -393,6 +403,8 @@ replication RepKickNoVotes, RepKickYesVotes; if( bNetDirty && VoteCollector != none && VoteCollector.bIsSkipTraderVoteInProgress) RepSkipTraderNoVotes, RepSkipTraderYesVotes; + if( bNetDirty && VoteCollector != none && VoteCollector.bIsPauseGameVoteInProgress) + RepPauseGameNoVotes, RepPauseGameYesVotes; // !SHIPPING_PC_GAME && !FINAL_RELEASE in C++ if ( bDebugSpawnManager && bNetDirty ) @@ -475,6 +487,10 @@ simulated event ReplicatedEvent(name VarName) { VoteCollector.UnPackSkipTraderVotes(); } + else if ( VarName == nameof(RepPauseGameYesVotes) || VarName == nameof(RepPauseGameNoVotes) ) + { + VoteCollector.UnPackPauseGameVotes(); + } else if( VarName == 'ServerAdInfo') { ShowPreGameServerWelcomeScreen(); @@ -1113,12 +1129,12 @@ simulated function bool CanOverrideWeeklyMusic() if (WorldInfo.NetMode == NM_Client) { - return !bIsWeeklyMode || class'KFGameEngine'.static.GetWeeklyEventIndexMod() != 12; + return (!bIsWeeklyMode || class'KFGameEngine'.static.GetWeeklyEventIndexMod() != 12 || GetNumPlayersAlive() == 0); } else { KFGI = KFGameInfo(WorldInfo.Game); - return (KFGI == none || KFGI.OutbreakEvent == none || !KFGI.OutbreakEvent.ActiveEvent.bForceWWLMusic); + return (KFGI == none || KFGI.OutbreakEvent == none || !KFGI.OutbreakEvent.ActiveEvent.bForceWWLMusic || GetNumPlayersAlive() == 0); } } @@ -1129,6 +1145,11 @@ simulated function bool IsFinalWave() simulated function bool IsBossWave() { + if (bIsWeeklyMode && CurrentWeeklyIndex == 14) + { + return true; + } + return WaveNum == WaveMax; } @@ -1825,6 +1846,22 @@ reliable server function RecieveVoteSkipTrader(PlayerReplicationInfo PRI, bool b } } +function ServerStartVotePauseGame(PlayerReplicationInfo PRI) +{ + if(VoteCollector != none) + { + VoteCollector.ServerStartVotePauseGame(PRI); + } +} + +reliable server function ReceiveVotePauseGame(PlayerReplicationInfo PRI, bool bPauseGame) +{ + if(VoteCollector != none) + { + VoteCollector.ReceiveVotePauseGame(PRI, bPauseGame); + } +} + reliable server function ReceiveVoteMap(PlayerReplicationInfo PRI, int MapIndex) { if(VoteCollector != none) @@ -1878,6 +1915,9 @@ function ChooseNextObjective(int NextWaveNum) NextObjective = none; NextObjectiveIsEndless = false; + if (bIsWeeklyMode && KFGameInfo(WorldInfo.Game).OutbreakEvent.ActiveEvent.bBossRushMode) + return; + KFMI = KFMapInfo(WorldInfo.GetMapInfo()); if (KFMI != none && NextWaveNum != WaveMax) { @@ -2202,6 +2242,12 @@ simulated function NotifyBrokenTrader() bNetDirty = true; } +simulated function NotifyWeeklyEventIndex(int EventIndex) +{ + CurrentWeeklyIndex = EventIndex; + bNetDirty = true; +} + defaultproperties { TraderItemsPath="GP_Trader_ARCH.DefaultTraderItems" diff --git a/KFGame/Classes/KFGfxMenu_StartGame.uc b/KFGame/Classes/KFGfxMenu_StartGame.uc index 1a52db4..af5d867 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_Fall2021'; case SEI_Winter: - return class'KFGFXSpecialEventObjectivesContainer_Xmas2020'; + return class'KFGFXSpecialEventObjectivesContainer_Xmas2021'; } return class'KFGFxSpecialEventObjectivesContainer'; @@ -1566,6 +1566,8 @@ function bool ShouldUseDifficultyFilter(int GameModeIndex) { //Weekly case 1: + //VSSurvival + case 2: return false; } @@ -1578,6 +1580,8 @@ function bool ShouldUseLengthFilter(int GameModeIndex) { //Weekly case 1: + //VSSurvival + case 2: //Endless case 3: // Objective Mode diff --git a/KFGame/Classes/KFGfxMenu_Trader.uc b/KFGame/Classes/KFGfxMenu_Trader.uc index a74354a..8bed295 100644 --- a/KFGame/Classes/KFGfxMenu_Trader.uc +++ b/KFGame/Classes/KFGfxMenu_Trader.uc @@ -41,7 +41,7 @@ struct native SItemInformation var STraderItem DefaultItem; var int ItemUpgradeLevel; - + StructDefaultProperties { ItemUpgradeLevel=0; diff --git a/KFGame/Classes/KFGfxMoviePlayer_Manager.uc b/KFGame/Classes/KFGfxMoviePlayer_Manager.uc index 9530b53..f88afc7 100644 --- a/KFGame/Classes/KFGfxMoviePlayer_Manager.uc +++ b/KFGame/Classes/KFGfxMoviePlayer_Manager.uc @@ -211,6 +211,9 @@ var PlayerReplicationInfo KickVotePRI; //The target PRI for current skip trader vote var PlayerReplicationInfo SkipTraderVotePRI; +// The target PRI for current pause vote +var PlayerReplicationInfo PauseGameVotePRI; + /** Cached version of the TWOnlineLobby */ var TWOnlineLobby OnlineLobby; var UniqueNetId CurrentInviteLobbyId; @@ -239,6 +242,9 @@ var const int MouseInputChangedThreshold; var bool bKickVotePopupActive; /** TRUE if the skip trader vote popup is open */ var bool bSkipTraderVotePopupActive; +/** TRUE if the pause game vote popup is open */ +var bool bPauseGameVotePopupActive; + var bool bUsingGamepad; // True if we are using a gamepad, otherwise we are using mouse and keyboard var bool bAfterLobby; // Set to true once we have readied up var bool bMenusOpen; // true if we're using menus, otherwise we're using the HUD @@ -1144,6 +1150,11 @@ function OpenMenu( byte NewMenuIndex, optional bool bShowWidgets = true ) ShowSkipTraderVote(SkipTraderVotePRI); } + if(PauseGameVotePRI != none && NewMenuIndex != UI_Trader) + { + ShowPauseGameVote(PauseGameVotePRI); + } + // Close our last menu if we are already in a menu if (bMenusOpen && NewMenuIndex != CurrentMenuIndex && CurrentMenu != none) { @@ -2076,6 +2087,70 @@ function CastNoVoteSkipTrader() } } +/********************************************************************************************* +* @name Pause Game +********************************************************************************************* */ + +function ShowPauseGameVote(PlayerReplicationInfo PRI) +{ + local KFGameReplicationInfo KFGRI; + KFGRI = KFGameReplicationInfo(GetPC().WorldInfo.GRI); + + PauseGameVotePRI = PRI; + if(bMenusOpen && CurrentMenu != TraderMenu) + { + bPauseGameVotePopupActive = true; + DelayedOpenPopup(EConfirmation, EDPPID_Misc, (KFGRI != none && KFGRI.bIsEndlessPaused) ? Class'KFGFxWidget_KickVote'.default.VoteResumeGameString : Class'KFGFxWidget_KickVote'.default.VotePauseGameString, + PauseGameVotePRI.PlayerName@Class'KFGFxWidget_KickVote'.default.VotePauseGameDetailString, + Class'KFCommon_LocalizedStrings'.default.YesString, Class'KFCommon_LocalizedStrings'.default.NoString, CastYesVotePauseGame, CastNoVotePauseGame); + } +} + +simulated function HidePauseGameVote() +{ + if( bSkipTraderVotePopupActive ) + { + bSkipTraderVotePopupActive = false; + UnloadCurrentPopup(); + } + + SkipTraderVotePRI = none; +} + +function CastYesVotePauseGame() +{ + local KFplayerReplicationInfo KFPRI; + local KFPlayerController KFPC; + + KFPC = KFPlayerController(GetPC()); + if(KFPC != none) + { + KFPRI = KFplayerReplicationInfo(KFPC.PlayerReplicationInfo); + + if(KFPRI != none) + { + KFPRI.CastPauseGameVote(KFPRI, true); + } + } +} + +function CastNoVotePauseGame() +{ + local KFplayerReplicationInfo KFPRI; + local KFPlayerController KFPC; + + KFPC = KFPlayerController(GetPC()); + if(KFPC != none) + { + KFPRI = KFplayerReplicationInfo(KFPC.PlayerReplicationInfo); + + if(KFPRI != none) + { + KFPRI.CastPauseGameVote(KFPRI, false); + } + } +} + /********************************************************************************************* * @name Kick Vote ********************************************************************************************* */ diff --git a/KFGame/Classes/KFGfxObject_Menu.uc b/KFGame/Classes/KFGfxObject_Menu.uc index 7c1e998..b963b68 100644 --- a/KFGame/Classes/KFGfxObject_Menu.uc +++ b/KFGame/Classes/KFGfxObject_Menu.uc @@ -39,11 +39,23 @@ function InitOnlineLobby() function OnR3Pressed() { local KFPlayerController KFPC; + local KFPlayerReplicationInfo KFPRI; + local KFGameReplicationInfo KFGRI; KFPC = KFPlayerController(GetPC()); - if(KFPC != none) { + KFPRI = KFPlayerReplicationInfo( GetPC().PlayerReplicationInfo ); + if (KFPRI != none) + { + KFGRI = KFGameReplicationInfo(KFPRI.WorldInfo.GRI); + if(KFGRI != none || KFGRI.bEndlessMode) + { + KFPC.RequestPauseGame(); + return; + } + } + KFPC.RequestSwitchTeam(); } } @@ -191,6 +203,21 @@ function Callback_RequestTeamSwitch() } } +function Callback_RequestEndlessPause() +{ + local KFPlayerController KFPC; + local KFPlayerReplicationInfo KFPRI; + + KFPC = KFPlayerController(GetPC()); + KFPRI = KFPlayerReplicationInfo( KFPC.PlayerReplicationInfo ); + + if (KFPC != none && KFPRI != none) + { + KFPRI.RequestPauseGame(KFPRI); + KFPC.MyGFxManager.CloseMenus(); + } +} + function Callback_ReadyClicked( bool bReady ) { local KFPlayerReplicationInfo KFPRI; diff --git a/KFGame/Classes/KFGfxObject_TraderItems.uc b/KFGame/Classes/KFGfxObject_TraderItems.uc index 66d0403..b18733d 100644 --- a/KFGame/Classes/KFGfxObject_TraderItems.uc +++ b/KFGame/Classes/KFGfxObject_TraderItems.uc @@ -97,7 +97,9 @@ struct native STraderItem var byte InventoryGroup; var int ItemID; //used since the list will be sorted. - + + var bool bCanBuyAmmo; + StructDefaultProperties { AltTraderFilter=FT_None diff --git a/KFGame/Classes/KFLocalMessage.uc b/KFGame/Classes/KFLocalMessage.uc index 7f508fc..14e1d06 100644 --- a/KFGame/Classes/KFLocalMessage.uc +++ b/KFGame/Classes/KFLocalMessage.uc @@ -52,6 +52,29 @@ var localized string SkipTraderThisUserAlreadyStartedAVoteString; var localized string SkipTraderVoteYesReceivedString; var localized string SkipTraderVoteNoReceivedString; +var localized string PauseVoteStartedString; +var localized string PauseVoteInProgressString; +var localized string PauseVoteYesReceivedString; +var localized string PauseVoteNoReceivedString; +var localized string PauseVoteNoEnoughTimeString; +var localized string PauseVoteNoSpectatorsString; +var localized string PauseVoteTimeString; +var localized string PauseVoteSuccessString; +var localized string PauseVoteFailedString; +var localized string PauseVoteWaveActiveString; +var localized string PauseVoteWrongModeString; + +var localized string ResumeVoteStartedString; +var localized string ResumeVoteInProgressString; +var localized string ResumeVoteYesReceivedString; +var localized string ResumeVoteNoReceivedString; +var localized string ResumeVoteNoEnoughTimeString; +var localized string ResumeVoteNoSpectatorsString; +var localized string ResumeVoteTimeString; +var localized string ResumeVoteSuccessString; +var localized string ResumeVoteFailedString; +var localized string ResumeVoteWaveActiveString; + enum ELocalMessageType { LMT_AdminLogin, @@ -84,7 +107,28 @@ enum ELocalMessageType LMT_SkipTraderVoteYesReceived, LMT_SkipTraderVoteNoReceived, LMT_SkipTraderNoEnoughTime, - LMT_SkipTraderThisUserAlreadyStartedAVote + LMT_SkipTraderThisUserAlreadyStartedAVote, + LMT_PauseVoteStarted, + LMT_PauseVoteInProgress, + LMT_PauseVoteYesReceived, + LMT_PauseVoteNoReceived, + LMT_PauseVoteNoEnoughTime, + LMT_PauseVoteNoSpectators, + LMT_PauseVoteTime, + LMT_PauseVoteSuccess, + LMT_PauseVoteFailed, + LMT_PauseVoteWaveActive, + LMT_PauseVoteWrongMode, + LMT_ResumeVoteStarted, + LMT_ResumeVoteInProgress, + LMT_ResumeVoteYesReceived, + LMT_ResumeVoteNoReceived, + LMT_ResumeVoteNoEnoughTime, + LMT_ResumeVoteNoSpectators, + LMT_ResumeVoteTime, + LMT_ResumeVoteSuccess, + LMT_ResumeVoteFailed, + LMT_ResumeVoteWaveActive, }; /** Message area on HUD (index into UTHUD.MessageOffset[]) */ @@ -164,6 +208,69 @@ static function string GetString( switch (Switch) { + case LMT_ResumeVoteStarted: + return RelatedPRI_1.PlayerName@Default.ResumeVoteStartedString; + + case LMT_ResumeVoteInProgress: + return default.ResumeVoteInProgressString; + + case LMT_ResumeVoteYesReceived: + return default.ResumeVoteYesReceivedString; + + case LMT_ResumeVoteNoReceived: + return default.ResumeVoteNoReceivedString; + + case LMT_ResumeVoteNoEnoughTime: + return default.ResumeVoteNoEnoughTimeString; + + case LMT_ResumeVoteNoSpectators: + return default.ResumeVoteNoSpectatorsString; + + case LMT_ResumeVoteTime: + return default.ResumeVoteTimeString; + + case LMT_ResumeVoteSuccess: + return default.ResumeVoteSuccessString; + + case LMT_ResumeVoteFailed: + return default.ResumeVoteFailedString; + + case LMT_ResumeVoteWaveActive: + return default.ResumeVoteWaveActiveString; + + case LMT_PauseVoteStarted: + return RelatedPRI_1.PlayerName@Default.PauseVoteStartedString; + + case LMT_PauseVoteInProgress: + return default.PauseVoteInProgressString; + + case LMT_PauseVoteYesReceived: + return default.PauseVoteYesReceivedString; + + case LMT_PauseVoteNoReceived: + return default.PauseVoteNoReceivedString; + + case LMT_PauseVoteNoEnoughTime: + return default.PauseVoteNoEnoughTimeString; + + case LMT_PauseVoteNoSpectators: + return default.PauseVoteNoSpectatorsString; + + case LMT_PauseVoteTime: + return default.PauseVoteTimeString; + + case LMT_PauseVoteSuccess: + return default.PauseVoteSuccessString; + + case LMT_PauseVoteFailed: + return default.PauseVoteFailedString; + + case LMT_PauseVoteWaveActive: + return default.PauseVoteWaveActiveString; + + case LMT_PauseVoteWrongMode: + return default.PauseVoteWrongModeString; + case LMT_OtherVoteInProgress: return default.OtherVoteInProgressString; diff --git a/KFGame/Classes/KFOnlineStatsReadDingo.uc b/KFGame/Classes/KFOnlineStatsReadDingo.uc index 8dc1e07..e7538b4 100644 --- a/KFGame/Classes/KFOnlineStatsReadDingo.uc +++ b/KFGame/Classes/KFOnlineStatsReadDingo.uc @@ -69,6 +69,7 @@ defaultproperties ColumnIds.Add(STATID_ACHIEVE_Dystopia2029Collectibles) ColumnIds.Add(STATID_ACHIEVE_MoonbaseCollectibles) ColumnIds.Add(STATID_ACHIEVE_NetherholdCollectibles) + ColumnIds.Add(STATID_ACHIEVE_CarillonHamletCollectibles) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky5, Name="AchievementMrPerky5")) ColumnMappings.Add((Id=STATID_ACHIEVE_MrPerky10, Name = "AchievementMrPerky10")) @@ -126,4 +127,5 @@ defaultproperties ColumnMappings.Add((Id=STATID_ACHIEVE_Dystopia2029Collectibles,NAme="AchievementCollectDystopia2029")) ColumnMappings.Add((Id=STATID_ACHIEVE_MoonbaseCollectibles,NAme="AchievementCollectMoonbase")) ColumnMappings.Add((Id=STATID_ACHIEVE_NetherholdCollectibles,NAme="AchievementCollectNetherhold")) + ColumnMappings.Add((Id=STATID_ACHIEVE_CarillonHamletCollectibles,NAme="AchievementCollectCarillonHamlet")) } diff --git a/KFGame/Classes/KFOnlineStatsWrite.uc b/KFGame/Classes/KFOnlineStatsWrite.uc index 8817006..4948473 100644 --- a/KFGame/Classes/KFOnlineStatsWrite.uc +++ b/KFGame/Classes/KFOnlineStatsWrite.uc @@ -437,6 +437,10 @@ const KFACHID_NetherholdHard = 286; const KFACHID_NetherholdHellOnEarth = 287; const KFACHID_NetherholdCollectibles = 288; +const KFACHID_CarillonHamletHard = 289; +const KFACHID_CarillonHamletHellOnEarth = 290; +const KFACHID_CarillonHamletCollectibles = 291; + /* __TW_ANALYTICS_ */ var int PerRoundWeldXP; var int PerRoundHealXP; @@ -1165,6 +1169,11 @@ private event AddNonZedKill(class KilledClass, byte Difficulty) } } +private event AddToWeaponPurchased( class WeaponDef, int Price ) +{ + SeasonalEventStats_OnWeaponPurchased(WeaponDef, Price); +} + private native function AddToKillObjectives(class ZedClass); private native function AddToVersusKillObjectives(class KillerClass); @@ -1871,6 +1880,14 @@ final simulated function SeasonalEventStats_OnTryCompleteObjective(int Objective } } +final simulated function SeasonalEventStats_OnWeaponPurchased(class WeaponDef, int Price) +{ + if (SeasonalEventIsValid()) + { + SeasonalEvent.OnWeaponPurchased(WeaponDef, Price); + } +} + /********************************************************************************************* * @name Dailies and daily-specific tracking ********************************************************************************************* */ @@ -2022,7 +2039,8 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_AssaultRifle_Thompson, KFDT_Ballistic_Thompson,KFDT_Bludgeon_Thompson),CompletionAmount=7000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Nailgun, KFDT_Ballistic_HRGNailgun, KFDT_Bludgeon_HRGNailgun),CompletionAmount=10000)) //7000 DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_SMG_P90, KFDT_Ballistic_P90,KFDT_Bludgeon_P90),CompletionAmount=10000)) - DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_SMG_Kriss, KFDT_Ballistic_Kriss,KFDT_Bludgeon_Kriss),CompletionAmount=10000)) + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_Stunner, KFDT_Ballistic_HRG_Stunner,KFDT_Ballistic_HRG_Stunner_Alt,KFDT_Explosive_HRG_Stunner,KFDT_Bludgeon_HRG_Stunner),CompletionAmount=10000)) + DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_SMG_Kriss, KFDT_Ballistic_Kriss,KFDT_Bludgeon_Kriss),CompletionAmount=10000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_SMG_HK_UMP, KFDT_Ballistic_HK_UMP,KFDT_Bludgeon_HK_UMP),CompletionAmount=10000)) DailyEvents.Add((ObjectiveType=DOT_WeaponDamage,ObjectiveClasses=(KFWeap_HRG_BarrierRifle, KFDT_Ballistic_HRG_BarrierRifle,KFDT_Bludgeon_HRG_BarrierRifle),CompletionAmount=10000)) @@ -2256,6 +2274,9 @@ defaultproperties DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-NETHERHOLD),CompletionAmount=1)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-NETHERHOLD),CompletionAmount=2)) DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-NETHERHOLD),CompletionAmount=3)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-CARILLONHAMLET),CompletionAmount=1)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-CARILLONHAMLET),CompletionAmount=2)) + DailyEvents.Add((ObjectiveType=DOT_Maps,SecondaryType=DOST_MapCompletion,ObjectiveClasses=(KF-CARILLONHAMLET),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 30b0bea..8c82196 100644 --- a/KFGame/Classes/KFOnlineStatsWriteDingo.uc +++ b/KFGame/Classes/KFOnlineStatsWriteDingo.uc @@ -71,4 +71,5 @@ defaultproperties Properties.Add((PropertyId = STATID_ACHIEVE_Dystopia2029Collectibles, Data = (Type = SDT_Int32,Value1 = 0))) Properties.Add((PropertyId = STATID_ACHIEVE_MoonbaseCollectibles, Data = (Type = SDT_Int32, Value1 = 0))) Properties.Add((PropertyId = STATID_ACHIEVE_NetherholdCollectibles, Data = (Type = SDT_Int32, Value1 = 0))) + Properties.Add((PropertyId = STATID_ACHIEVE_CarillonHamletCollectibles, Data = (Type = SDT_Int32, Value1 = 0))) } diff --git a/KFGame/Classes/KFOutbreakEvent.uc b/KFGame/Classes/KFOutbreakEvent.uc index 5c94b95..9a5934c 100644 --- a/KFGame/Classes/KFOutbreakEvent.uc +++ b/KFGame/Classes/KFOutbreakEvent.uc @@ -93,6 +93,12 @@ struct StatAdjustments /** Speed modifier */ var() float InitialGroundSpeedModifierScale; + /** Override HitZones Information */ + var() array HitZonesOverride; + + /** WeakPoints to show special VFX*/ + var() array WeakPoints; + structdefaultproperties { HealthScale = 1.f; @@ -115,6 +121,25 @@ struct StatAdjustments } }; +struct BossRushOverridesPerWave +{ + var() array ZedsToAdjust; + var() array SpawnReplacementList; + var() float DoshOnKillGlobalModifier; + var() int ExtraDoshGrantedonWaveWon; + + structdefaultproperties + { + DoshOnKillGlobalModifier=1.0f + ExtraDoshGrantedonWaveWon=0.0f + } +}; + +struct BossRushOverrides +{ + var() array PerWaves; +}; + /** Individual property overrides that drive other behavior to allow for * a large amount of variety in our weekly event mode. */ @@ -381,6 +406,14 @@ struct WeeklyOverrides /** If WWL music should be forced */ var() bool bForceWWLMusic; + /** Boss classes availabled for boss rush mode */ + var() bool bBossRushMode; + + var() BossRushOverrides BossRushOverrideParams; + + /** Ignores damage caused by headshots. */ + var() bool bInvulnerableHeads; + structdefaultproperties { GameLength = GL_Short @@ -437,6 +470,8 @@ struct WeeklyOverrides JumpZ = -1.f DroppedItemLifespan=-1.0f bForceWWLMusic = false; + bBossRushMode = false; + bInvulnerableHeads = false; } }; @@ -636,9 +671,8 @@ function ModifyGroundSpeed(KFPawn PlayerPawn, out float GroundSpeed) //In our case, this should be better explained as a GameInfo-facing AdjustDamage. Things are being done here that would be incredibly invasive in other classes given the size of our code base. function ReduceDamage(out int Damage, Pawn Injured, Controller InstigatedBy, class DamageType, TraceHitInfo HitInfo) { - local int HitZoneIdx; + local int HitZoneIdx, WaveNum; local KFPawn InstigatorPawn; - local StatAdjustments ToAdjust; //Some events can be headshot only. Do this only if the incoming damage is against a monster-derived class // and it's one of our custom damage types. Keeps things like crush damage from being scaled to 0. @@ -649,6 +683,15 @@ function ReduceDamage(out int Damage, Pawn Injured, Controller InstigatedBy, cla { Damage = 0; } + } + else if (ActiveEvent.bInvulnerableHeads && KFPawn_Monster(Injured) != none && ClassIsChildOf(DamageType, class'KFDamageType') ) + { + HitZoneIdx = KFPawn_Monster(Injured).HitZones.Find('ZoneName', HitInfo.BoneName); + // Apply damage to head armor but not head. + if (HitZoneIdx == HZI_Head && !bool(KFPawn_Monster(Injured).ArmorZoneStatus & 1)) + { + Damage = 0; + } } if (InstigatedBy != none) @@ -665,7 +708,25 @@ function ReduceDamage(out int Damage, Pawn Injured, Controller InstigatedBy, cla } } - foreach ActiveEvent.ZedsToAdjust(ToAdjust) + if (!ActiveEvent.bBossRushMode) + { + AdjustDamageReduction(Damage, Injured, InstigatedBy, InstigatorPawn, ActiveEvent.ZedsToAdjust); + } + else + { + WaveNum = Outer.MyKFGRI.WaveNum - 1; + if ( WaveNum < ActiveEvent.BossRushOverrideParams.PerWaves.length ) + { + AdjustDamageReduction(Damage, Injured, InstigatedBy, InstigatorPawn, ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum].ZedsToAdjust); + } + } +} + +function AdjustDamageReduction(out int Damage, Pawn Injured, Controller InstigatedBy, KFPawn InstigatorPawn, array Adjustments) +{ + local StatAdjustments ToAdjust; + + foreach Adjustments(ToAdjust) { //Injured zed reduction if (Injured.class == ToAdjust.ClassToAdjust) @@ -772,7 +833,7 @@ function AdjustPawnScale(Pawn Pawn) function AdjustMonsterDefaults(out KFPawn_Monster P) { - local StatAdjustments ToAdjust; + local int WaveNum; if (P == none) { @@ -796,7 +857,29 @@ function AdjustMonsterDefaults(out KFPawn_Monster P) } //Per class overrides - foreach ActiveEvent.ZedsToAdjust(ToAdjust) + if (!ActiveEvent.bBossRushMode) + { + AdjustDefaults(P, ActiveEvent.ZedsToAdjust); + } + else + { + WaveNum = Outer.MyKFGRI.WaveNum - 1; + if ( WaveNum < ActiveEvent.BossRushOverrideParams.PerWaves.length ) + { + AdjustDefaults(P, ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum].ZedsToAdjust); + } + } +} + +function AdjustDefaults(out KFPawn_Monster P, array Adjustments) +{ + local StatAdjustments ToAdjust; + local HitZoneInfo OverrideHitZone; + local array OverridenBones; + local WeakPoint WeakPoint; + local int i; + + foreach Adjustments(ToAdjust) { if (P.class == ToAdjust.ClassToAdjust) { @@ -833,6 +916,38 @@ function AdjustMonsterDefaults(out KFPawn_Monster P) { SpawnManager.SummonBossMinions(ToAdjust.AdditionalSubSpawns.Squads, Lerp(ToAdjust.AdditionalSubSpawnCount.X, ToAdjust.AdditionalSubSpawnCount.Y, FMax(NumPlayers, 1) / float(MaxPlayers))); } + + if (ToAdjust.HitZonesOverride.Length > 0) + { + foreach ToAdjust.HitZonesOverride(OverrideHitZone) + { + for (i = 0; i < P.Hitzones.Length; ++i) + { + if (OverrideHitZone.ZoneName == P.Hitzones[i].ZoneName) + { + P.Hitzones[i].DmgScale = OverrideHitZone.DmgScale; + P.Hitzones[i].GoreHealth = OverrideHitZone.GoreHealth; + P.Hitzones[i].MaxGoreHealth = OverrideHitZone.MaxGoreHealth; + break; + } + } + } + } + + if (ToAdjust.WeakPoints.Length > 0) + { + OverridenBones.Length = 0; + + foreach ToAdjust.WeakPoints(WeakPoint) + { + OverridenBones.AddItem(WeakPoint); + } + + if (OverridenBones.Length > 0) + { + P.ServerSpawnWeakPointVFX(OverridenBones); + } + } } } } @@ -896,12 +1011,32 @@ function SetWorldInfoOverrides() } function class GetAISpawnOverrirde(EAIType AIType) +{ + local int WaveNum; + + if (!ActiveEvent.bBossRushMode) + { + return GetAISpawnOverrideInner(ActiveEvent.SpawnReplacementList, AIType); + } + else + { + WaveNum = MyKFGRI.WaveNum - 1; + if ( WaveNum < ActiveEvent.BossRushOverrideParams.PerWaves.length ) + { + return GetAISpawnOverrideInner(ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum].SpawnReplacementList, AIType); + } + } + + return AIClassList[AIType]; +} + +function class GetAISpawnOverrideInner(array SpawnReplacementList, EAIType AIType) { local SpawnReplacement Replacement; local float RandF; //Check if our current weekly event has any overrides available - foreach ActiveEvent.SpawnReplacementList(Replacement) + foreach SpawnReplacementList(Replacement) { if (Replacement.SpawnEntry == AIType) { @@ -925,6 +1060,7 @@ function class GetAISpawnOverrirde(EAIType AIType) return AIClassList[AIType]; } + // This will convert the provided Outbreak Index into an Id that corresponds to the Weekly Event. static function int GetOutbreakId(int SetEventsIndex); diff --git a/KFGame/Classes/KFPawn.uc b/KFGame/Classes/KFPawn.uc index a427045..d32bbe2 100644 --- a/KFGame/Classes/KFPawn.uc +++ b/KFGame/Classes/KFPawn.uc @@ -3045,7 +3045,7 @@ function class GetUsedWeaponPerk( Controller DamagerController, Actor Da } } - if( WeaponPerk == none && KFW != none && class'KFPerk'.static.IsBackupWeapon( KFW ) ) + if( WeaponPerk == none && KFW != none && ( class'KFPerk'.static.IsBackupWeapon( KFW ) || class'KFPerk'.static.IsDoshinegun( KFW ) )) { WeaponPerk = InstigatorPerkClass; } diff --git a/KFGame/Classes/KFPawn_Monster.uc b/KFGame/Classes/KFPawn_Monster.uc index 8bc0658..62f9b02 100644 --- a/KFGame/Classes/KFPawn_Monster.uc +++ b/KFGame/Classes/KFPawn_Monster.uc @@ -156,6 +156,13 @@ var(Combat) float HumanBaseMeleeDamage; /** Contains balance settings per game difficulty */ var class DifficultySettings; +struct native WeakPoint +{ + var name BoneName; + var vector Offset; +}; + + /********************************************************************************************* * @name Player-controlled ********************************************************************************************* */ @@ -552,6 +559,15 @@ var array ParasiteSeeds; // Max num of seeds in this character var byte MaxNumSeeds; +/********************************************************************************************* + * @name Tiny skull Weakly vfx +********************************************************************************************* */ + +`define TINY_SKULL_MAX_WEAKPOINTS 10 +var transient array WeakPointVFXComponents; +var repnotify WeakPoint WeakPoints_TS[`TINY_SKULL_MAX_WEAKPOINTS]; +var ParticleSystem WeakPointParticleTemplate; + /********************************************************************************************* * @name Delegates ********************************************************************************************* */ @@ -566,7 +582,7 @@ replication if (bNetDirty) bIsHeadless, bIsPoisoned, bPlayPanicked, bPlayShambling, MaxHeadChunkGoreWhileAlive, RepInflateMatParams, RepInflateMatParam, RepDamageInflateParam, RepBleedInflateMatParam, bDisableGoreMeshWhileAlive, - bDisableHeadless, InflateDeathGravity, InflationExplosionTimer, bUseDamageInflation, bUseExplosiveDeath; + bDisableHeadless, InflateDeathGravity, InflationExplosionTimer, bUseDamageInflation, bUseExplosiveDeath, WeakPoints_TS; if ( bNetDirty && bCanCloak ) bIsCloakingSpottedByTeam; if ( bNetDirty && bCanRage ) @@ -668,6 +684,10 @@ simulated event ReplicatedEvent(name VarName) case nameof(bIsEnraged): SetEnraged(bIsEnraged); break; + + case nameof(WeakPoints_TS): + SpawnWeakpointVFX(); + break; } super.ReplicatedEvent( VarName ); @@ -1845,6 +1865,7 @@ simulated function PlayDying(class DamageType, vector HitLoc) { local KFPlayerController KFPC; local string ClassName; + local ParticleSystemComponent WeakPointPSC; Timer_EndRallyBoost(); @@ -1879,6 +1900,16 @@ simulated function PlayDying(class DamageType, vector HitLoc) UpdateBleedIncapFX(); StopExtraVFX(`NAME_NONE); + + if (WeakPointVFXComponents.Length > 0) + { + foreach WeakPointVFXComponents(WeakPointPSC) + { + WeakPointPSC.DeactivateSystem(); + } + + WeakPointVFXComponents.Length = 0; + } } simulated function PlayInflationDeath() @@ -4778,6 +4809,48 @@ server reliable function AddParasiteSeed(KFProjectile Proj) ParasiteSeeds.AddItem(Proj); } +simulated function SpawnWeakPointVFX() +{ + local int i; + local ParticleSystemComponent VFXComponent; + + if (WeakPointParticleTemplate != none && WeakPointVFXComponents.Length == 0) + { + for (i = 0; i < `TINY_SKULL_MAX_WEAKPOINTS; ++i) + { + if (WeakPoints_TS[i].BoneName == '') + return; + + VFXComponent = new(self) class'ParticleSystemComponent'; + VFXComponent.SetTemplate( WeakPointParticleTemplate ); + Mesh.AttachComponent( VFXComponent, WeakPoints_TS[i].BoneName, WeakPoints_TS[i].Offset ); + VFXComponent.ActivateSystem(); + WeakPointVFXComponents.AddItem(VFXComponent); + } + } +} + +simulated function ServerSpawnWeakPointVFX(array WeakPoints) +{ + local int i; + + if (WeakPoints.Length == 0) + return; + + for (i = 0; i < WeakPoints.Length; ++i) + { + WeakPoints_TS[i] = WeakPoints[i]; + } + + if (WorldInfo.NetMode == NM_Standalone) + { + SpawnWeakPointVFX(); + } + else + { + bNetDirty = true; + } +} /********************************************************************************************* * @name Achievements @@ -4977,4 +5050,6 @@ DefaultProperties MaxNumSeeds=1 ZEDCowboyHatAttachName=HEAD_Attach + + WeakPointParticleTemplate=ParticleSystem'FX_Gameplay_EMIT.FX_Weak_Indicator' } diff --git a/KFGame/Classes/KFPerk.uc b/KFGame/Classes/KFPerk.uc index c78b2de..9f4e0ec 100644 --- a/KFGame/Classes/KFPerk.uc +++ b/KFGame/Classes/KFPerk.uc @@ -494,6 +494,17 @@ static function bool IsBlastBrawlers( KFWeapon KFW ) return KFW != none && KFW.Class.Name == 'KFWeap_HRG_BlastBrawlers'; } +/** + * @brief Return if a weapon is Doshinegun + * + * @param KFW Weapon to check + * @return true if backup weapon + */ +static function bool IsDoshinegun( KFWeapon KFW ) +{ + return KFW != none && KFW.Class.Name == 'KFWeap_AssaultRifle_Doshinegun'; +} + /********************************************************************************************* * @name Build / Level Management - Apply and save the updated build and level ********************************************************************************************* */ diff --git a/KFGame/Classes/KFPerk_Commando.uc b/KFGame/Classes/KFPerk_Commando.uc index f14633f..7717f38 100644 --- a/KFGame/Classes/KFPerk_Commando.uc +++ b/KFGame/Classes/KFPerk_Commando.uc @@ -82,7 +82,7 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau KFW = GetWeaponFromDamageCauser( DamageCauser ); } - if( (KFW != none && (IsWeaponOnPerk( KFW,, self.class ) || IsDual9mm(KFW) || Is9mm(KFW))) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) ) + if( (KFW != none && (IsWeaponOnPerk( KFW,, self.class ) || IsDual9mm(KFW) || Is9mm(KFW))) || IsDoshinegun(KFW) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) ) { TempDamage += InDamage * GetPassiveValue( WeaponDamage, CurrentLevel ); if( IsRapidFireActive() ) @@ -303,8 +303,6 @@ simulated function float GetZedTimeModifier( KFWeapon W ) local name StateName; StateName = W.GetStateName(); - `Log("STATE NAME: " $StateName); - if( IsProfessionalActive() && (IsWeaponOnPerk( W,, self.class ) || IsBackupWeapon( W ) || IsDual9mm( W )) ) { if( StateName == 'Reloading' || @@ -318,7 +316,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) } } // FAMAS uses alt fire as common firing. Needs a special case - if( CouldRapidFireActive() && (Is9mm(W) || IsDual9mm( W ) || IsWeaponOnPerk( W,, self.class )) && + if( CouldRapidFireActive() && (Is9mm(W) || IsDual9mm( W ) || IsDoshinegun(W) || IsWeaponOnPerk( W,, self.class )) && (ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE || (IsFAMAS(W) && StateName == 'FiringSecondaryState')) ) { return RapidFireFiringRate; diff --git a/KFGame/Classes/KFPerk_FieldMedic.uc b/KFGame/Classes/KFPerk_FieldMedic.uc index 2ab17e2..f82ab66 100644 --- a/KFGame/Classes/KFPerk_FieldMedic.uc +++ b/KFGame/Classes/KFPerk_FieldMedic.uc @@ -550,7 +550,8 @@ function GameExplosion GetExplosionTemplate() */ function bool CouldBeZedToxicCloud( class KFDT ) { - return IsZedativeActive() && IsDamageTypeOnPerk( KFDT ); + // Special case for doshinegun. Only this perk should apply. + return IsZedativeActive() && (IsDamageTypeOnPerk( KFDT ) || KFDT.Name == 'KFDT_Bludgeon_Doshinegun_Shot'); } static function float GetZedativeExplosionDelay() diff --git a/KFGame/Classes/KFPerk_Gunslinger.uc b/KFGame/Classes/KFPerk_Gunslinger.uc index 6724349..05c509b 100644 --- a/KFGame/Classes/KFPerk_Gunslinger.uc +++ b/KFGame/Classes/KFPerk_Gunslinger.uc @@ -234,7 +234,7 @@ simulated private static function float GetQuickSwitchRecoilModifier() */ simulated function float GetReloadRateScale( KFWeapon KFW ) { - if( IsWeaponOnPerk( KFW,, self.class ) && WorldInfo.TimeDilation < 1.f && !IsFanFareActive() && IsZedTimeReloadAllowed() ) + if( ( IsWeaponOnPerk( KFW,, self.class )) && WorldInfo.TimeDilation < 1.f && !IsFanFareActive() && IsZedTimeReloadAllowed() ) { return 1.f - GetPassiveValue( ZedTimeReload, GetLevel() ); } @@ -261,7 +261,7 @@ simulated function bool IsZedTimeReloadAllowed() */ simulated function bool GetUsingTactialReload( KFWeapon KFW ) { - return IsSpeedReloadActive() && IsWeaponOnPerk( KFW,, self.class ); + return IsSpeedReloadActive() && IsWeaponOnPerk( KFW,, self.class ) ; } /** @@ -322,7 +322,7 @@ simulated function float GetZedTimeModifier( KFWeapon W ) { local name StateName; - if( GetFanfareActive() && IsWeaponOnPerk( W,, self.class ) ) + if( GetFanfareActive() && ( IsWeaponOnPerk( W,, self.class ) || IsDoshinegun(W) ) ) { StateName = W.GetStateName(); if( ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE ) diff --git a/KFGame/Classes/KFPerk_Sharpshooter.uc b/KFGame/Classes/KFPerk_Sharpshooter.uc index e03b15f..2465778 100644 --- a/KFGame/Classes/KFPerk_Sharpshooter.uc +++ b/KFGame/Classes/KFPerk_Sharpshooter.uc @@ -137,7 +137,7 @@ simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCau KFW = GetWeaponFromDamageCauser( DamageCauser ); } - if( (KFW != none && IsWeaponOnPerk( KFW,, self.class )) || (DamageType != none && IsDamageTypeOnPerk(DamageType)) ) + if( (KFW != none && (IsWeaponOnPerk( KFW,, self.class ) || IsDoshinegun(KFW))) || (DamageType != none && IsDamageTypeOnPerk(DamageType)) ) { if( MyKFPM != none && HitZoneIdx == HZI_HEAD ) { diff --git a/KFGame/Classes/KFPerk_Survivalist.uc b/KFGame/Classes/KFPerk_Survivalist.uc index 969ebef..cf6c766 100644 --- a/KFGame/Classes/KFPerk_Survivalist.uc +++ b/KFGame/Classes/KFPerk_Survivalist.uc @@ -799,7 +799,7 @@ DefaultProperties PerkSkills(ESurvivalist_AmmoVest)=(Name="AmmoVest",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_AmmoVest", Increment=0.f,Rank=0,StartingValue=0.15f,MaxValue=0.15f) PerkSkills(ESurvivalist_BigPockets)=(Name="BigPockets",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_BigPockets", Increment=0.f,Rank=0,StartingValue=5.f,MaxValue=5.f) PerkSkills(ESurvivalist_Shrapnel)=(Name="ZedShrapnel",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_Shrapnel", Increment=0.f,Rank=0,StartingValue=2.f,MaxValue=2.f) - PerkSkills(ESurvivalist_MakeThingsGoBoom)=(Name="MakeThingsGoBoom",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_Boom", Increment=0.f,Rank=0,StartingValue=1.4f,MaxValue=1.4f) + PerkSkills(ESurvivalist_MakeThingsGoBoom)=(Name="MakeThingsGoBoom",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_Boom", Increment=0.f,Rank=0,StartingValue=1.5f,MaxValue=1.5f) //1.4f PerkSkills(ESurvivalist_MadMan)=(Name="MadMan",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_Madman", Increment=0.f,Rank=0,StartingValue=0.5f,MaxValue=0.5f) PerkSkills(ESurvivalist_IncapMaster)=(Name="IncapMaster",IconPath="UI_PerkTalent_TEX.Survivalist.UI_Talents_Survivalist_IncapMaster", Increment=0.f,Rank=0,StartingValue=5000.0f,MaxValue=5000.0f) @@ -876,5 +876,5 @@ DefaultProperties TacticalReloadAsReloadRateClassNames(0)="KFWeap_GrenadeLauncher_M32" - MakeThingsGoBoomExplosiveResistance=0.4f + MakeThingsGoBoomExplosiveResistance=0.5f //0.4f } diff --git a/KFGame/Classes/KFPlayerController.uc b/KFGame/Classes/KFPlayerController.uc index c630097..5e29926 100644 --- a/KFGame/Classes/KFPlayerController.uc +++ b/KFGame/Classes/KFPlayerController.uc @@ -951,6 +951,7 @@ simulated event name GetSeasonalStateName() { local int EventId; local KFMapInfo KFMI; + local bool bIsWWLWeekly; // WWL Weekly should not allow seasonal overrides EventId = class'KFGameEngine'.static.GetSeasonalEventID(); KFMI = KFMapInfo(WorldInfo.GetMapInfo()); @@ -959,20 +960,24 @@ simulated event name GetSeasonalStateName() KFMI.ModifySeasonalEventId(EventId); } + bIsWWLWeekly = class'KFGameEngine'.static.GetWeeklyEventIndexMod() == 12 && KFGameReplicationInfo(WorldInfo.GRI) != none && KFGameReplicationInfo(WorldInfo.GRI).bIsWeeklyMode; + if (bIsWWLWeekly) + return 'No_Event'; + //Remove any year information, just get 1s digit - switch (EventId % 10) - { - case SEI_Summer: - return 'Summer_Sideshow'; - case SEI_Fall: - return 'Fall'; - case SEI_Winter: - return 'Winter'; - case SEI_Spring: - return 'Spring'; - default: - return 'No_Event'; - } + switch (EventId % 10) + { + case SEI_Summer: + return 'Summer_Sideshow'; + case SEI_Fall: + return 'Fall'; + case SEI_Winter: + return 'Winter'; + case SEI_Spring: + return 'Spring'; + default: + return 'No_Event'; + } return 'No_Event'; } @@ -3596,7 +3601,7 @@ simulated function SetBossCamera( KFInterface_MonsterBoss Boss ) // overridden because to view a dying boss as a client event ResetCameraMode() { - if( PlayerCamera != none && PlayerCamera.CameraStyle != 'Boss' ) + if( PlayerCamera != none && PlayerCamera.CameraStyle != 'Boss') { super.ResetCameraMode(); } @@ -4539,7 +4544,7 @@ simulated function StartAutoTargeting() if( !PlayerInput.bUsingGamepad ) { - return; + return; } KFInput = KFPlayerInput(PlayerInput); @@ -4572,10 +4577,20 @@ static simulated function KFInterface_Usable GetCurrentUsableActor( Pawn P, opti local KFInterface_Usable BestUsableActor; local int InteractionIndex, BestInteractionIndex; + local KFGameReplicationInfo KFGRI; + BestInteractionIndex = -1; if ( P != None ) { + /* On endless mode, if game is paused players can move but not interact with objects. */ + KFGRI = KFGameReplicationInfo(P.WorldInfo.GRI); + if(KFGRI != none && KFGRI.bIsEndlessPaused) + { + return none; + } + /* */ + // Check touching -- Useful when UsedBy() is implemented by subclass instead of kismet ForEach P.TouchingActors(class'Actor', A) { @@ -4633,12 +4648,19 @@ function GetTriggerUseList(float interactDistanceToCheck, float crosshairDist, f local Trigger checkTrigger; local SeqEvent_Used UseSeq; local float aimEpsilon; + local KFGameReplicationInfo KFGRI; if (Pawn == None) { return; } + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + if(KFGRI != none && KFGRI.bIsEndlessPaused) + { + return; + } + // search of nearby actors that have use events foreach Pawn.CollidingActors(class'Trigger',checkTrigger,interactDistanceToCheck) { @@ -6807,6 +6829,8 @@ reliable server function ServerPause() function bool PerformedUseAction() { + local KFGameReplicationInfo KFGRI; + // Intentionally do not trigger Super Class so that we do not close the menu if(WorldInfo.NetMode != NM_StandAlone) @@ -6826,6 +6850,12 @@ function bool PerformedUseAction() return false; } + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + if(KFGRI != none && KFGRI.bIsEndlessPaused) + { + return false; + } + // leave vehicle if currently in one if( Vehicle(Pawn) != None ) { @@ -7388,6 +7418,12 @@ function AddNonZedKill(class KilledClass, byte Difficulty) } native reliable client private function ClientAddNonZedKill(class KilledClass, byte Difficulty); +function AddWeaponPurchased( class WeaponDef, int Price ) +{ + ClientAddWeaponPurchased( WeaponDef, Price ); +} +native reliable client private function ClientAddWeaponPurchased( class WeaponDef, int Price ); + function AddZedAssist(class MonsterClass) { ClientAddZedAssist(MonsterClass); @@ -10045,6 +10081,34 @@ exec function RequestSkipTrader() } } +exec function RequestPauseGame() +{ + local KFGameReplicationInfo KFGRI; + local KFPlayerReplicationInfo KFPRI; + + KFPRI = KFPlayerReplicationInfo(PlayerReplicationInfo); + KFGRI = KFGameReplicationInfo(KFPRI.WorldInfo.GRI); + + if (KFPRI != none) + { + if (KFGRI.bMatchHasBegun) + { + if (KFGRI.bEndlessMode && KFPRI.bHasSpawnedIn) + { + KFPRI.RequestPauseGame(KFPRI); + if (MyGFxManager != none) + { + MyGFxManager.CloseMenus(); + if (MyGFxManager.PartyWidget != none) + { + MyGFxManager.PartyWidget.SetReadyButtonVisibility(false); + } + } + } + } + } +} + /********************************************************************************************* * Networking *********************************************************************************************/ diff --git a/KFGame/Classes/KFPlayerController_WeeklySurvival.uc b/KFGame/Classes/KFPlayerController_WeeklySurvival.uc index e19d8a8..c71df50 100644 --- a/KFGame/Classes/KFPlayerController_WeeklySurvival.uc +++ b/KFGame/Classes/KFPlayerController_WeeklySurvival.uc @@ -207,6 +207,27 @@ function ResetGameplayPostProcessFX() } } +simulated function SetBossCamera( KFInterface_MonsterBoss Boss ) +{ + local KFGameReplicationInfo KFGRI; + local bool bIsBossRush; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + bIsBossRush = KFGRI.bIsWeeklyMode && KFGRI.CurrentWeeklyIndex == 14; + + if (bIsBossRush && Boss.GetHealthPercent() <= 0.0f && KFGRI.WaveNum != KFGRI.WaveMax) + { + SetTimer(5.0f, false, nameof(ResetBossCamera)); + } + + super.SetBossCamera(Boss); +} + +simulated function ResetBossCamera() +{ + super(PlayerController).ResetCameraMode(); +} + // defaultProperties { @@ -218,4 +239,4 @@ defaultProperties RhythmMethodSoundHit =AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Hit' RhythmMethodSoundTop =AkEvent'WW_UI_PlayerCharacter.Play_R_Method_Top' AracnoStompSoundEvent =AkEvent'WW_GLO_Runtime.WeeklyArcno' -} \ No newline at end of file +} diff --git a/KFGame/Classes/KFPlayerInput.uc b/KFGame/Classes/KFPlayerInput.uc index 36b37ed..34ec632 100644 --- a/KFGame/Classes/KFPlayerInput.uc +++ b/KFGame/Classes/KFPlayerInput.uc @@ -210,6 +210,8 @@ var(AutoTarget) float ForceLookAtPawnMinAngle; var(AutoTarget) float ForceLookAtPawnRotationRate; /** How fast to rotate towards ForceLookAtPawn location dampened for closer rotation**/ var(AutoTarget) float ForceLookAtPawnDampenedRotationRate; +/** Aim distance of autoaim to set head as target. */ +var(AutoTarget) float WeakBoneDistance; /********************************************************************************************* * @name Force Feedback @@ -2070,8 +2072,10 @@ function vector GetBestAutoTargetLocation(Pawn CheckTarget, out name outBoneName for(i = 0; i < WeakBones.Length; ++i) { TestLoc = KFP.Mesh.GetBoneLocation(WeakBones[i]); - if ( !IsAutoTargetWithinCone(TestLoc, CamLoc, CamDir, AutoTargetWeakspotCurve) ) + if ( !IsAutoTargetWithinCone(TestLoc, CamLoc, CamDir, AutoTargetWeakspotCurve, WeakBoneDistance) ) + { continue; // test each weakspot bone + } HitActor = Pawn.Trace(HitLoc, HitNorm, TestLoc, CamLoc, TRUE, vect(0,0,0), HitInfo, TRACEFLAG_Bullet); if( HitActor == none || HitActor == CheckTarget ) @@ -2106,7 +2110,7 @@ function vector GetBestAutoTargetLocation(Pawn CheckTarget, out name outBoneName /** * Returns true if TargetLoc falls within a given view cone */ -function bool IsAutoTargetWithinCone(vector TargetLoc, vector CamLoc, vector CamDir, const out InterpCurveFloat Curve) +function bool IsAutoTargetWithinCone(vector TargetLoc, vector CamLoc, vector CamDir, const out InterpCurveFloat Curve, optional float Margin) { local float DistToTarget, TargetRadius, TargetHeight; local float DotDiffToTarget; @@ -2138,7 +2142,7 @@ function bool IsAutoTargetWithinCone(vector TargetLoc, vector CamLoc, vector Cam } // Make sure the target is in front of us and close enough - if( UsedTargetAngle > DotDiffToTarget ) + if( UsedTargetAngle > (DotDiffToTarget + Margin)) { `log("Auto-target Cone Angle Exceeded by "$UsedTargetAngle - DotDiffToTarget, bDebugAutoTarget); return false; @@ -2982,4 +2986,6 @@ defaultproperties ForceLookAtPawnMinAngle=0.9f ForceLookAtPawnRotationRate=22 ForceLookAtPawnDampenedRotationRate=8 + + WeakBoneDistance = 0.02; //0.01; } diff --git a/KFGame/Classes/KFPlayerReplicationInfo.uc b/KFGame/Classes/KFPlayerReplicationInfo.uc index 04aeb16..8413516 100644 --- a/KFGame/Classes/KFPlayerReplicationInfo.uc +++ b/KFGame/Classes/KFPlayerReplicationInfo.uc @@ -138,6 +138,9 @@ var bool bPerkSecondarySupplyUsed; var bool bVotedToSkipTraderTime; var bool bAlreadyStartedASkipTraderVote; +var bool bVotedToPauseGame; +var bool bAlreadyStartedAPauseGameVote; + /************************************ * Not replicated Voice Comms Request * local client only -ZG @@ -851,6 +854,113 @@ reliable client function RecieveTopMaps(TopVotes VoteObject) } } +/********************************************************************************************* +`* Pause Game +********************************************************************************************* */ + +reliable client function ShowPauseGameVote(PlayerReplicationInfo PRI, byte VoteDuration, bool bShowChoices) +{ + local KFPlayerController KFPC; + + KFPC = KFPlayerController(Owner); + + if(KFPC != none && KFPC.MyGFxHUD != none) + { + KFPC.MyGFxHUD.ShowPauseGameVote(PRI, VoteDuration, bShowChoices); + } + + if(KFPC != none && KFPC.MyGFxManager != none && bShowChoices) + { + KFPC.MyGFxManager.ShowPauseGameVote(PRI); + } +} + +reliable client function UpdatePauseGameTime(byte CurrentVoteTime) +{ + local KFPlayerController KFPC; + + KFPC = KFPlayerController(Owner); + + if(KFPC != none && KFPC.MyGFxHUD != none) + { + KFPC.MyGFxHUD.UpdatePauseGameTime(CurrentVoteTime); + } +} + +reliable client function HidePauseGameVote() +{ + local KFPlayerController KFPC; + + KFPC = KFPlayerController(Owner); + + if(KFPC != none && KFPC.MyGFxHUD != none) + { + KFPC.MyGFxHUD.HidePauseGameVote(); + } + + if(KFPC != none && KFPC.MyGFxManager != none) + { + KFPC.MyGFxManager.HidePauseGameVote(); + } +} + +simulated function RequestPauseGame(PlayerReplicationInfo PRI) +{ + bVotedToPauseGame = true; + ServerRequestPauseGameVote(self); +} + +reliable server function ServerRequestPauseGameVote(PlayerReplicationInfo PRI) +{ + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + + if (KFGRI != none) + { + KFGRI.ServerStartVotePauseGame(PRI); + } +} + +simulated function CastPauseGameVote(PlayerReplicationInfo PRI, bool bSkipTrader) +{ + local KFPlayerController KFPC; + + ServerCastPauseGameVote(self, bSkipTrader); + + KFPC = KFPlayerController(Owner); + + if(KFPC != none && KFPC.MyGFxManager != none) + { + KFPC.MyGFxManager.HidePauseGameVote(); + } +} + +reliable server function ServerCastPauseGameVote(PlayerReplicationInfo PRI, bool bSkipTrader) +{ + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + + if(KFGRI != none) + { + KFGRI.ReceiveVotePauseGame(PRI, bSkipTrader); + } +} + +reliable server function ResetPauseGame() +{ + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + + if(KFGRI != none && KFGRI.VoteCollector != none) + { + KFGRI.VoteCollector.ConcludeVotePauseGame(); + } + bVotedToPauseGame = false; +} + /********************************************************************************************* `* Character Customization ********************************************************************************************* */ diff --git a/KFGame/Classes/KFProj_RicochetStickBullet.uc b/KFGame/Classes/KFProj_RicochetStickBullet.uc index fdfb9fa..b599cef 100644 --- a/KFGame/Classes/KFProj_RicochetStickBullet.uc +++ b/KFGame/Classes/KFProj_RicochetStickBullet.uc @@ -55,6 +55,9 @@ var(Projectile) ParticleSystem ProjPickupTemplate; Allows us to set a much shorter LifeSpan to prevent fly-away projectiles living a long time. */ var float LifeSpanAfterStick; +/** Wether this object can be denied as a pickup or must be always picked. */ +var bool bPickupCanBeDenied; + replication { if ( bNetDirty ) @@ -501,4 +504,5 @@ defaultproperties { PickupRadius=250 PickupHeight=250 + bPickupCanBeDenied=true } \ No newline at end of file diff --git a/KFGame/Classes/KFSeasonalEventStats.uc b/KFGame/Classes/KFSeasonalEventStats.uc index 0d65945..f592a16 100644 --- a/KFGame/Classes/KFSeasonalEventStats.uc +++ b/KFGame/Classes/KFSeasonalEventStats.uc @@ -73,4 +73,5 @@ simulated event OnWaveCompleted(class GameClass, int Difficulty, int W simulated event OnTriggerUsed(class TriggerClass); simulated event OnTryCompleteObjective(int ObjectiveIndex, int EventIndex); simulated function OnHitTaken(); -simulated function OnHitGiven(class DT); \ No newline at end of file +simulated function OnHitGiven(class DT); +simulated function OnWeaponPurchased(class WeaponDef, int Price); diff --git a/KFGame/Classes/KFUnlockManager.uc b/KFGame/Classes/KFUnlockManager.uc index fd68b9d..e595fe7 100644 --- a/KFGame/Classes/KFUnlockManager.uc +++ b/KFGame/Classes/KFUnlockManager.uc @@ -29,7 +29,10 @@ enum ESharedContentUnlock SCU_FrostFang, SCU_GravityImploder, SCU_FAMAS, - SCU_Thermite + SCU_Thermite, + SCU_BladedPistol, + SCU_ParasiteImplanter, + SCU_Doshinegun }; @@ -345,4 +348,16 @@ defaultproperties Name=KFWeap_RocketLauncher_ThermiteBore, IconPath="WEP_UI_Thermite_TEX.UI_WeaponSelect_Thermite", ID=8940)} + SharedContentList(SCU_BladedPistol)={( + Name=KFWeap_Pistol_Bladed, + IconPath="WEP_UI_BladedPistol_TEX.UI_WeaponSelect_BladedPistol", + ID=9126)} + SharedContentList(SCU_ParasiteImplanter)={( + Name=KFWeap_Rifle_ParasiteImplanter, + IconPath="WEP_UI_ParasiteImplanter_TEX.UI_WeaponSelect_ParasiteImplanter", + ID=9132)} + SharedContentList(SCU_Doshinegun)={( + Name=KFWeap_AssaultRifle_Doshinegun, + IconPath="WEP_UI_Doshinegun_TEX.UI_Weapon_Select_Doshinegun", + ID=9275)} } diff --git a/KFGame/Classes/KFVoteCollector.uc b/KFGame/Classes/KFVoteCollector.uc index 4a33f33..7c7f76f 100644 --- a/KFGame/Classes/KFVoteCollector.uc +++ b/KFGame/Classes/KFVoteCollector.uc @@ -44,6 +44,7 @@ var bool bIsSkipTraderVoteInProgress; var byte LastSkipTraderYesVoteValue; var byte LastSkipTraderNoVoteValue; var int SkipTraderVoteLimit; +var int PauseGameVoteLimit; var byte CurrentVoteTime; @@ -81,6 +82,16 @@ var TopVotes TopVotesObject; var array MapVoteList; var array MapList; + +/************************************ +* @name Pause Endless Vote Vars +************************************/ + +var sVoteInfo CurrentPauseGameVote; +var bool bIsPauseGameVoteInProgress; +var byte LastPauseGameYesVoteValue; +var byte LastPauseGameNoVoteValue; + //============================================================== // @name Kick Vote //============================================================== @@ -158,7 +169,7 @@ function ServerStartVoteKick(PlayerReplicationInfo PRI_Kickee, PlayerReplication } // A kick vote is not allowed while another vote is active - if(bIsSkipTraderVoteInProgress) + if(bIsSkipTraderVoteInProgress || bIsPauseGameVoteInProgress) { KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_OtherVoteInProgress); return; @@ -874,6 +885,280 @@ function int MapVoteSort(MapVote A, MapVote B) return Result; } +//============================================================== +// @name Pause Vote +//============================================================== + +function ServerStartVotePauseGame(PlayerReplicationInfo PRI) +{ + local int i; + local array PRIs; + local KFGameInfo KFGI; + local KFPlayerController KFPC; + local KFGameReplicationInfo KFGRI; + local byte WaveTimeRemaining; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + KFGI = KFGameInfo(WorldInfo.Game); + KFPC = KFPlayerController(PRI.Owner); + + // Spectators aren't allowed to vote + if(PRI.bOnlySpectator) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteNoSpectators : LMT_PauseVoteNoSpectators); + return; + } + + // Only pause the game if there's no wave active + if(KFGRI.bWaveIsActive) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteWaveActive : LMT_PauseVoteWaveActive); + return; + } + + if(!KFGRI.bEndlessMode) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_PauseVoteWrongMode); + return; + } + + // A pause vote is not allowed while another vote is active + if(bIsKickVoteInProgress || bIsSkipTraderVoteInProgress) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', LMT_OtherVoteInProgress); + return; + } + + WaveTimeRemaining = KFGRI.GetTraderTimeRemaining(); + if(WaveTimeRemaining <= PauseGameVoteLimit) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteNoEnoughTime : LMT_PauseVoteNoEnoughTime); + return; + } + + if( !bIsPauseGameVoteInProgress ) + { + // Clear voter array + PlayersThatHaveVoted.Length = 0; + + // Cache off these values in case player leaves before vote ends -- no cheating! + CurrentPauseGameVote.PlayerID = PRI.UniqueId; + CurrentPauseGameVote.PlayerPRI = PRI; + CurrentPauseGameVote.PlayerIPAddress = KFPC.GetPlayerNetworkAddress(); + + bIsPauseGameVoteInProgress = true; + + CurrentVoteTime = min(VoteTime, WaveTimeRemaining - PauseGameVoteLimit); + + GetKFPRIArray(PRIs); + for (i = 0; i < PRIs.Length; i++) + { + PRIs[i].ShowPauseGameVote(PRI, CurrentVoteTime, !(PRIs[i] == PRI)); + } + + KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteStarted : LMT_PauseVoteStarted, CurrentPauseGameVote.PlayerPRI); + SetTimer( CurrentVoteTime, false, nameof(ConcludeVotePauseGame), self ); + SetTimer( 1, true, nameof(UpdatePauseGameTimer), self ); + // Cast initial vote + ReceiveVotePauseGame(PRI, true); + + KFPlayerReplicationInfo(PRI).bAlreadyStartedAPauseGameVote = true; + } + else + { + // Can't start a new vote until current one is over + KFPlayerController(PRI.Owner).ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteInProgress : LMT_PauseVoteInProgress); + } +} + +reliable server function UpdatePauseGameTimer() +{ + local array PRIs; + local int i; + + CurrentVoteTime -= 1; + GetKFPRIArray(PRIs); + for (i = 0; i < PRIs.Length; i++) + { + PRIs[i].UpdatePauseGameTime(CurrentVoteTime); + } +} + +reliable server function ReceiveVotePauseGame(PlayerReplicationInfo PRI, bool bSkip) +{ + local KFPlayerController KFPC; + local KFGameReplicationInfo KFGRI; + + if(PlayersThatHaveVoted.Find(PRI) == INDEX_NONE) + { + //accept their vote + PlayersThatHaveVoted.AddItem(PRI); + if(bSkip) + { + yesVotes++; + } + else + { + noVotes++; + } + + KFPC = KFPlayerController(PRI.Owner); + if(KFPC != none) + { + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + if(bSkip) + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteYesReceived : LMT_PauseVoteYesReceived); + } + else + { + KFPC.ReceiveLocalizedMessage(class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteNoReceived : LMT_PauseVoteNoReceived); + } + } + + if( ShouldConcludePauseGameVote() ) + { + ConcludeVotePauseGame(); + } + else + { + ReplicatePauseGameVotes(); + } + } +} + +function ReplicatePauseGameVotes() +{ + local KFGameReplicationInfo KFGRI; + + RepPauseGameYesVotes = YesVotes; + RepPauseGameNoVotes = NoVotes; + + KFGRI = Outer; + KFGRI.bForceNetUpdate = true; + + if(Role == Role_Authority && WorldInfo.NetMode != NM_DedicatedServer) + { + UnPackPauseGameVotes(); + } +} + +function UnPackPauseGameVotes() +{ + local KFPlayerController KFPC; + + if(LastPauseGameYesVoteValue != RepPauseGameYesVotes || LastPauseGameNoVoteValue != RepPauseGameNoVotes) + { + NoVotes = RepPauseGameNoVotes; + YesVotes = RepPauseGameYesVotes; + + //Update UI + KFPC = KFPlayerController(GetALocalPlayerController()); + if(KFPC != none && KFPC.MyGFxHUD != none) + { + KFPC.MyGFxHUD.UpdatePauseGameVoteCount(YesVotes, NoVotes); + } + + LastPauseGameYesVoteValue = RepPauseGameYesVotes; + LastPauseGameNoVoteValue = RepPauseGameNoVotes; + } +} + +function bool ShouldConcludePauseGameVote() +{ + local array PRIs; + local int NumPRIs; + + GetKFPRIArray(PRIs); + NumPRIs = PRIs.Length; + + if( YesVotes + NoVotes >= NumPRIs || NoVotes > 0 ) + { + return true; + } + + return false; +} + +reliable server function ConcludeVotePauseGame() +{ + local array PRIs; + local int i, NumPRIs; + local KFGameInfo KFGI; + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + KFGI = KFGameInfo(WorldInfo.Game); + + if(bIsPauseGameVoteInProgress) + { + GetKFPRIArray(PRIs); + + for (i = 0; i < PRIs.Length; i++) + { + PRIs[i].HidePauseGameVote(); + } + + NumPRIs = PRIs.Length; + SetTimer( 0.f, true, nameof(UpdatePauseGameTimer), self ); + + if( NoVotes > 0) + { + bIsFailedVoteTimerActive=true; + SetTimer( KFGI.TimeBetweenFailedVotes, false, nameof(ClearFailedVoteFlag), self ); + KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteFailed : LMT_PauseVoteFailed); + } + else if( YesVotes >= NumPRIs ) + { + + //pause game + if (KFGRI.bIsEndlessPaused) + { + KFGRI.bIsEndlessPaused = false; + KFGRI.bStopCountDown = false; + KFGI.ResumeEndlessGame(); + } + else + { + KFGRI.bIsEndlessPaused = true; + KFGRI.bStopCountDown = true; + KFGI.PauseEndlessGame(); + } + + //clear everything + ResetPauseGameVote(); + + //tell server to skip trader + KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_PauseVoteSuccess : LMT_ResumeVoteSuccess); + } + else + { + //Set timer so that votes cannot be spammed + bIsFailedVoteTimerActive=true; + SetTimer( KFGI.TimeBetweenFailedVotes, false, nameof(ClearFailedVoteFlag), self ); + KFGI.BroadcastLocalized(KFGI, class'KFLocalMessage', KFGRI.bIsEndlessPaused ? LMT_ResumeVoteFailed : LMT_PauseVoteFailed); + } + + bIsPauseGameVoteInProgress = false; + CurrentPauseGameVote.PlayerPRI = none; + CurrentPauseGameVote.PlayerID = class'PlayerReplicationInfo'.default.UniqueId; + yesVotes = 0; + noVotes = 0; + } +} + +reliable server function ResetPauseGameVote() +{ + local array PRIs; + local int i; + + GetKFPRIArray(PRIs); + for (i = 0; i < PRIs.Length; i++) + { + PRIs[i].bAlreadyStartedASkipTraderVote = false; + } +} + DefaultProperties { VoteTime=30 @@ -884,4 +1169,5 @@ DefaultProperties KickedPlayers=0 TimeAfterSkipTrader=5//seconds SkipTraderVoteLimit=5//seconds + PauseGameVoteLimit=1 } \ No newline at end of file diff --git a/KFGame/Classes/KFWeapDef_BladedPistol.uc b/KFGame/Classes/KFWeapDef_BladedPistol.uc index ecddd40..55bdfce 100644 --- a/KFGame/Classes/KFWeapDef_BladedPistol.uc +++ b/KFGame/Classes/KFWeapDef_BladedPistol.uc @@ -13,7 +13,7 @@ DefaultProperties WeaponClassPath="KFGameContent.KFWeap_Pistol_Bladed" BuyPrice=600 - AmmoPricePerMag=32 + AmmoPricePerMag=38 //32 ImagePath="WEP_UI_BladedPistol_TEX.UI_WeaponSelect_BladedPistol" EffectiveRange=25 @@ -22,4 +22,6 @@ DefaultProperties UpgradePrice[1]=1500 UpgradeSellPrice[0]=550 UpgradeSellPrice[1]=1650 + + SharedUnlockId=SCU_BladedPistol } diff --git a/KFGame/Classes/KFWeapDef_Doshinegun.uc b/KFGame/Classes/KFWeapDef_Doshinegun.uc new file mode 100644 index 0000000..6e33165 --- /dev/null +++ b/KFGame/Classes/KFWeapDef_Doshinegun.uc @@ -0,0 +1,31 @@ +//============================================================================= +// KFWeaponDefintion +//============================================================================= +// A lightweight container for basic weapon properties that can be safely +// accessed without a weapon actor (UI, remote clients). +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= +class KFWeapDef_Doshinegun extends KFWeaponDefinition + abstract; + +DefaultProperties +{ + WeaponClassPath="KFGameContent.KFWeap_AssaultRifle_Doshinegun" + + BuyPrice=600 //750 + ImagePath="WEP_UI_Doshinegun_TEX.UI_Weapon_Select_Doshinegun" + + EffectiveRange=68 + + UpgradePrice[0]=600 + UpgradePrice[1]=700 + UpgradePrice[2]=1500 + + UpgradeSellPrice[0]=450 + UpgradeSellPrice[1]=975 + UpgradeSellPrice[2]=2100 + + SharedUnlockId=SCU_Doshinegun +} diff --git a/KFGame/Classes/KFWeapDef_DualBladed.uc b/KFGame/Classes/KFWeapDef_DualBladed.uc index 1546e6e..083631a 100644 --- a/KFGame/Classes/KFWeapDef_DualBladed.uc +++ b/KFGame/Classes/KFWeapDef_DualBladed.uc @@ -13,7 +13,7 @@ DefaultProperties WeaponClassPath="KFGameContent.KFWeap_Pistol_DualBladed" BuyPrice=1200 - AmmoPricePerMag=64 + AmmoPricePerMag=76 //64 ImagePath="WEP_UI_Dual_BladedPistol_TEX.UI_WeaponSelect_Dual_BladedPistol" EffectiveRange=50 @@ -23,4 +23,6 @@ DefaultProperties UpgradeSellPrice[0]=525 UpgradeSellPrice[1]=1650 + + SharedUnlockId=SCU_BladedPistol } diff --git a/KFGame/Classes/KFWeapDef_HRG_Energy.uc b/KFGame/Classes/KFWeapDef_HRG_Energy.uc index 62581aa..ae4c93f 100644 --- a/KFGame/Classes/KFWeapDef_HRG_Energy.uc +++ b/KFGame/Classes/KFWeapDef_HRG_Energy.uc @@ -15,7 +15,7 @@ DefaultProperties WeaponClassPath="KFGameContent.KFWeap_HRG_Energy" BuyPrice=1500 //1100 - AmmoPricePerMag=65 + AmmoPricePerMag=70 //65 ImagePath="WEP_UI_HRG_Energy_TEX.UI_WeaponSelect_HRG_Energy" EffectiveRange=50 diff --git a/KFGame/Classes/KFWeapDef_HRG_Stunner.uc b/KFGame/Classes/KFWeapDef_HRG_Stunner.uc new file mode 100644 index 0000000..6baa26c --- /dev/null +++ b/KFGame/Classes/KFWeapDef_HRG_Stunner.uc @@ -0,0 +1,25 @@ +//============================================================================= +// KFWeaponDefintion +//============================================================================= +// +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= +class KFWeapDef_HRG_Stunner extends KFWeaponDefinition + abstract; + +DefaultProperties +{ + WeaponClassPath="KFGameContent.KFWeap_HRG_Stunner" + + BuyPrice=1500 + AmmoPricePerMag=36 + ImagePath="ui_weaponselect_tex.UI_WeaponSelect_AA12" + + EffectiveRange=70 + + UpgradePrice[0]=1500 + + UpgradeSellPrice[0]=1125 +} diff --git a/KFGame/Classes/KFWeapDef_ParasiteImplanter.uc b/KFGame/Classes/KFWeapDef_ParasiteImplanter.uc index 5bac8a5..a354b3d 100644 --- a/KFGame/Classes/KFWeapDef_ParasiteImplanter.uc +++ b/KFGame/Classes/KFWeapDef_ParasiteImplanter.uc @@ -21,5 +21,5 @@ defaultproperties UpgradePrice[0]=1500 UpgradeSellPrice[0]=1125 - // SharedUnlockId=SCU_ParasiteImplanter + SharedUnlockId=SCU_ParasiteImplanter } diff --git a/KFGame/Classes/KFWeap_MinigunBase.uc b/KFGame/Classes/KFWeap_MinigunBase.uc index 2872cf9..005ab5a 100644 --- a/KFGame/Classes/KFWeap_MinigunBase.uc +++ b/KFGame/Classes/KFWeap_MinigunBase.uc @@ -577,6 +577,32 @@ reliable server function ServerSendToReload(byte ClientReloadAmount) bZoomActive = false; } +/** + * Detach weapon from skeletal mesh + * Reseting speeds + * @param SkeletalMeshComponent weapon is attached to. + */ +simulated function DetachWeapon() +{ + local KFPawn_Human KFPH; + local KFPlayerController KFPC; + + super.DetachWeapon(); + + KFPH = KFPawn_Human(Instigator); + if ( KFPH != None ) + { + MovementSpeedMod = 1; + KFPH.UpdateGroundSpeed(); + } + + KFPC = KFPlayerController(Instigator.Controller); + if (KFPC != none) + { + KFPC.RotationSpeedLimit = class'KFPlayerController'.default.RotationSpeedLimit; + } +} + defaultproperties { // Wind Up variables diff --git a/KFGame/Classes/KFWeapon.uc b/KFGame/Classes/KFWeapon.uc index d549903..69769c9 100644 --- a/KFGame/Classes/KFWeapon.uc +++ b/KFGame/Classes/KFWeapon.uc @@ -1025,6 +1025,8 @@ replication /** Util that makes sure the overlay component is last in the AllComponents/Components array. */ native function EnsureWeaponOverlayComponentLast(); +/** Wether the player can purchase ammo for the weapon. Will be true for most of the weapons */ +native function bool CanBuyAmmo(); /** * Handles view rotation and weapon rotation changes for the weapon. Called in script by @@ -1762,7 +1764,14 @@ function bool DenyPickupQuery(class ItemClass, Actor Pickup) } else { - bDenyPickUp = ((SpareAmmoCount[0] + AmmoCount[0]) >= GetMaxAmmoAmount(0)); + if (KFProj_RicochetStickBullet(Pickup) == none || KFProj_RicochetStickBullet(Pickup).bPickupCanBeDenied) + { + bDenyPickUp = ((SpareAmmoCount[0] + AmmoCount[0]) >= GetMaxAmmoAmount(0)); + } + else + { + bDenyPickUp = false; + } } } diff --git a/KFGame/Classes/KFWeaponSkinList.uc b/KFGame/Classes/KFWeaponSkinList.uc index f1030f6..25aaf5a 100644 --- a/KFGame/Classes/KFWeaponSkinList.uc +++ b/KFGame/Classes/KFWeaponSkinList.uc @@ -3595,6 +3595,24 @@ defaultproperties //Piranha Rusty Skins.Add((Id=9131, Weapondef=class'KFWeapDef_BladedPistol', MIC_1P=("wep_skinset50_mat.Wep_Bladed_Rustynightmare_PM"), MIC_3P="wep_skinset50_mat.3rd_Wep_Bladed_Rustynightmare_PM", MIC_Pickup="wep_skinset50_mat.3rd_Wep_Bladed_Pickup_Rustynightmare_PM")); +//Doshinegun Standard + Skins.Add((Id=9275, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("WEP_1P_Doshinegun_MAT.Wep_1stP_Doshinegun_MIC", "WEP_1P_Doshinegun_MAT.Wep_1stP_Doshinegun_Mag_MIC"), MIC_3P="wep_3p_doshinegun_mat.WEP_3P_Doshinegun_MIC", MIC_Pickup="wep_3p_doshinegun_mat.WEP_Pickup_Doshinegun_MIC")); + +//Doshinegun Baroque + Skins.Add((Id=9279, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("wep_skinset53_mat.Wep_Doshinegun_baroque_body_PM", "wep_skinset53_mat.Wep_Doshinegun_baroque_mag_PM"), MIC_3P="WEP_SkinSet53_MAT.Wep_Doshinegun_baroque_3P_PM", MIC_Pickup="WEP_SkinSet53_MAT.Wep_Doshinegun_Baroque_3P_Pickup_MIC")); + +//Doshinegun Diamond + Skins.Add((Id=9277, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("wep_skinset53_mat.Wep_Doshinegun_diamond_body_PM", "wep_skinset53_mat.Wep_Doshinegun_diamond_mag_PM"), MIC_3P="WEP_SkinSet53_MAT.Wep_Doshinegun_diamond_3P_PM", MIC_Pickup="WEP_SkinSet53_MAT.Wep_Doshinegun_Diamond_3P_Pickup_MIC")); + +//Doshinegun Dosh + Skins.Add((Id=9278, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("wep_skinset53_mat.Wep_Doshinegun_dosh_body_PM", "wep_skinset53_mat.Wep_Doshinegun_dosh_mag_PM"), MIC_3P="WEP_SkinSet53_MAT.Wep_Doshinegun_dosh_3P_PM", MIC_Pickup="WEP_SkinSet53_MAT.Wep_Doshinegun_Dosh_3P_Pickup_MIC")); + +//Doshinegun Golden Tiger + Skins.Add((Id=9280, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("wep_skinset53_mat.Wep_Doshinegun_tiger_body_PM", "wep_skinset53_mat.Wep_Doshinegun_tiger_mag_PM"), MIC_3P="WEP_SkinSet53_MAT.Wep_Doshinegun_tiger_3P_PM", MIC_Pickup="WEP_SkinSet53_MAT.Wep_Doshinegun_Tiger_3P_Pickup_MIC")); + +//Doshinegun Koi Dream + Skins.Add((Id=9276, Weapondef=class'KFWeapDef_Doshinegun', MIC_1P=("wep_skinset53_mat.Wep_Doshinegun_koidream_body_PM", "wep_skinset53_mat.Wep_Doshinegun_koidream_mag_PM"), MIC_3P="WEP_SkinSet53_MAT.Wep_Doshinegun_koidream_3P_PM", MIC_Pickup="WEP_SkinSet53_MAT.Wep_Doshinegun_koidream_3P_Pickup_MIC")); + //BeyondHorizon AA12 Skins.Add((Id=8845, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_AA12', MIC_1P=("WEP_SkinSet43_MAT.space_aa12.Space_AA12_1P_Mint_MIC"), MIC_3P="WEP_SkinSet43_MAT.space_aa12.Space_AA12_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet43_MAT.space_aa12.Space_AA12_3P_Pickup_MIC")) @@ -3720,4 +3738,124 @@ defaultproperties //Hellmark Thunder Hemoclobber Skins.Add((Id=9010, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicBat', MIC_1P=("WEP_SkinSet48_MAT.thunder_medicbat.Thunder_MedicBat_1P_Mint_MIC"), MIC_3P="WEP_SkinSet48_MAT.thunder_medicbat.Thunder_MedicBat_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet48_MAT.thunder_medicbat.Thunder_MedicBat_3P_Pickup_MIC")) + +//Alchemist Toxic Boomstick + Skins.Add((Id=9178, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet51_MAT.toxic_doublebarrel.Toxic_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_doublebarrel.Toxic_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_doublebarrel.Toxic_DoubleBarrel_3P_Pickup_MIC")) + +//Alchemist Toxic Caulk n Burn + Skins.Add((Id=9179, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet51_MAT.toxic_caulkburn.Toxic_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_caulkburn.Toxic_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_caulkburn.Toxic_CaulkBurn_3P_Pickup_MIC")) + +//Alchemist Toxic Desert Eagle + Skins.Add((Id=9180, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet51_MAT.toxic_deagle.Toxic_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_deagle.Toxic_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_deagle.Toxic_Deagle_3P_Pickup_MIC")) + +//Alchemist Toxic Flamethrower + Skins.Add((Id=9181, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet51_MAT.toxic_flamethrower.Toxic_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_flamethrower.Toxic_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_flamethrower.Toxic_Flamethrower_3P_Pickup_MIC")) + +//Alchemist Toxic HMTech-501 Grenade Rifle + Skins.Add((Id=9182, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicRifleGrenadeLauncher', MIC_1P=("WEP_SkinSet51_MAT.toxic_medicgrenadelauncher.Toxic_MedicGrenadeLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_medicgrenadelauncher.Toxic_MedicGrenadeLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_medicgrenadelauncher.Toxic_MedicGrenadeLauncher_3P_Pickup_MIC")) + +//Alchemist Toxic M32 + Skins.Add((Id=9183, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M32', MIC_1P=("WEP_SkinSet51_MAT.toxic_m32.Toxic_M32_1P_Mint_MIC", "WEP_SkinSet51_MAT.toxic_m32.Toxic_M32_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_m32.Toxic_M32_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_m32.Toxic_M32_3P_Pickup_MIC")) + +//Alchemist Toxic P90 + Skins.Add((Id=9184, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_P90', MIC_1P=("WEP_SkinSet51_MAT.toxic_p90.Toxic_P90_1P_Mint_MIC", "WEP_SkinSet51_MAT.toxic_p90.Toxic_P90_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_p90.Toxic_P90_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_p90.Toxic_P90_3P_Pickup_MIC")) + +//Alchemist Toxic RPG-7 + Skins.Add((Id=9185, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet51_MAT.toxic_rpg7.Toxic_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_rpg7.Toxic_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_rpg7.Toxic_RPG7_3P_Pickup_MIC")) + +//Alchemist Toxic Scar + Skins.Add((Id=9186, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Scar', MIC_1P=("WEP_SkinSet51_MAT.toxic_scar.Toxic_SCAR_1P_Mint_MIC", "WEP_SkinSet51_MAT.toxic_scar.Toxic_SCAR_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_scar.Toxic_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_scar.Toxic_SCAR_3P_Pickup_MIC")) + +//Alchemist Toxic Spitfire + Skins.Add((Id=9187, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Flaregun', MIC_1P=("WEP_SkinSet51_MAT.toxic_flaregun.Toxic_FlareGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.toxic_flaregun.Toxic_FlareGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.toxic_flaregun.Toxic_FlareGun_3P_Pickup_MIC")) + +//Alchemist Blaze Boomstick + Skins.Add((Id=9188, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet51_MAT.fire_doublebarrel.Fire_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_doublebarrel.Fire_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_doublebarrel.Fire_DoubleBarrel_3P_Pickup_MIC")) + +//Alchemist Blaze Caulk n Burn + Skins.Add((Id=9189, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet51_MAT.fire_caulkburn.Fire_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_caulkburn.Fire_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_caulkburn.Fire_CaulkBurn_3P_Pickup_MIC")) + +//Alchemist Blaze Desert Eagle + Skins.Add((Id=9190, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet51_MAT.fire_deagle.Fire_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_deagle.Fire_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_deagle.Fire_Deagle_3P_Pickup_MIC")) + +//Alchemist Blaze Flamethrower + Skins.Add((Id=9191, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet51_MAT.fire_flamethrower.Fire_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_flamethrower.Fire_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_flamethrower.Fire_Flamethrower_3P_Pickup_MIC")) + +//Alchemist Blaze HMTech-501 Grenade Rifle + Skins.Add((Id=9192, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicRifleGrenadeLauncher', MIC_1P=("WEP_SkinSet51_MAT.fire_medicgrenadelauncher.Fire_MedicGrenadeLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_medicgrenadelauncher.Fire_MedicGrenadeLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_medicgrenadelauncher.Fire_MedicGrenadeLauncher_3P_Pickup_MIC")) + +//Alchemist Blaze M32 + Skins.Add((Id=9193, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M32', MIC_1P=("WEP_SkinSet51_MAT.fire_m32.Fire_M32_1P_Mint_MIC", "WEP_SkinSet51_MAT.fire_m32.Fire_M32_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_m32.Fire_M32_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_m32.Fire_M32_3P_Pickup_MIC")) + +//Alchemist Blaze P90 + Skins.Add((Id=9194, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_P90', MIC_1P=("WEP_SkinSet51_MAT.fire_p90.Fire_P90_1P_Mint_MIC", "WEP_SkinSet51_MAT.fire_p90.Fire_P90_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_p90.Fire_P90_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_p90.Fire_P90_3P_Pickup_MIC")) + +//Alchemist Blaze RPG-7 + Skins.Add((Id=9195, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet51_MAT.fire_rpg7.Fire_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_rpg7.Fire_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_rpg7.Fire_RPG7_3P_Pickup_MIC")) + +//Alchemist Blaze Scar + Skins.Add((Id=9196, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Scar', MIC_1P=("WEP_SkinSet51_MAT.fire_scar.Fire_SCAR_1P_Mint_MIC", "WEP_SkinSet51_MAT.fire_scar.Fire_SCAR_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_scar.Fire_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_scar.Fire_SCAR_3P_Pickup_MIC")) + +//Alchemist Blaze Spitfire + Skins.Add((Id=9197, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Flaregun', MIC_1P=("WEP_SkinSet51_MAT.fire_flaregun.Fire_FlareGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet51_MAT.fire_flaregun.Fire_FlareGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet51_MAT.fire_flaregun.Fire_FlareGun_3P_Pickup_MIC")) + +//XMas Sweet Boomstick + Skins.Add((Id=9198, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet52_MAT.sweet_doublebarrel.Sweet_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_doublebarrel.Sweet_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_doublebarrel.Sweet_DoubleBarrel_3P_Pickup_MIC")) + +//XMas Sweet Caulk n Burn + Skins.Add((Id=9199, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet52_MAT.sweet_caulkburn.Sweet_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_caulkburn.Sweet_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_caulkburn.Sweet_CaulkBurn_3P_Pickup_MIC")) + +//XMas Sweet Desert Eagle + Skins.Add((Id=9200, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet52_MAT.sweet_deagle.Sweet_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_deagle.Sweet_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_deagle.Sweet_Deagle_3P_Pickup_MIC")) + +//XMas Sweet Flamethrower + Skins.Add((Id=9201, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet52_MAT.sweet_flamethrower.Sweet_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_flamethrower.Sweet_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_flamethrower.Sweet_Flamethrower_3P_Pickup_MIC")) + +//XMas Sweet HMTech-501 Grenade Rifle + Skins.Add((Id=9202, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicRifleGrenadeLauncher', MIC_1P=("WEP_SkinSet52_MAT.sweet_medicgrenadelauncher.Sweet_MedicGrenadeLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_medicgrenadelauncher.Sweet_MedicGrenadeLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_medicgrenadelauncher.Sweet_MedicGrenadeLauncher_3P_Pickup_MIC")) + +//XMas Sweet M32 + Skins.Add((Id=9203, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M32', MIC_1P=("WEP_SkinSet52_MAT.sweet_m32.Sweet_M32_1P_Mint_MIC", "WEP_SkinSet52_MAT.sweet_m32.Sweet_M32_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_m32.Sweet_M32_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_m32.Sweet_M32_3P_Pickup_MIC")) + +//XMas Sweet P90 + Skins.Add((Id=9204, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_P90', MIC_1P=("WEP_SkinSet52_MAT.sweet_p90.Sweet_P90_1P_Mint_MIC", "WEP_SkinSet52_MAT.sweet_p90.Sweet_P90_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_p90.Sweet_P90_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_p90.Sweet_P90_3P_Pickup_MIC")) + +//XMas Sweet RPG-7 + Skins.Add((Id=9205, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet52_MAT.sweet_rpg7.Sweet_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_rpg7.Sweet_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_rpg7.Sweet_RPG7_3P_Pickup_MIC")) + +//XMas Sweet Scar + Skins.Add((Id=9206, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Scar', MIC_1P=("WEP_SkinSet52_MAT.sweet_scar.Sweet_SCAR_1P_Mint_MIC", "WEP_SkinSet52_MAT.sweet_scar.Sweet_SCAR_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_scar.Sweet_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_scar.Sweet_SCAR_3P_Pickup_MIC")) + +//XMas Sweet Spitfire + Skins.Add((Id=9207, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Flaregun', MIC_1P=("WEP_SkinSet52_MAT.sweet_flaregun.Sweet_FlareGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sweet_flaregun.Sweet_FlareGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sweet_flaregun.Sweet_FlareGun_3P_Pickup_MIC")) + +//XMas Sour Boomstick + Skins.Add((Id=9208, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_DoubleBarrel', MIC_1P=("WEP_SkinSet52_MAT.sour_doublebarrel.Sour_DoubleBarrel_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_doublebarrel.Sour_DoubleBarrel_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_doublebarrel.Sour_DoubleBarrel_3P_Pickup_MIC")) + +//XMas Sour Caulk n Burn + Skins.Add((Id=9209, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_CaulkBurn', MIC_1P=("WEP_SkinSet52_MAT.sour_caulkburn.Sour_CaulkBurn_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_caulkburn.Sour_CaulkBurn_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_caulkburn.Sour_CaulkBurn_3P_Pickup_MIC")) + +//XMas Sour Desert Eagle + Skins.Add((Id=9210, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Deagle', MIC_1P=("WEP_SkinSet52_MAT.sour_deagle.Sour_Deagle_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_deagle.Sour_Deagle_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_deagle.Sour_Deagle_3P_Pickup_MIC")) + +//XMas Sour Flamethrower + Skins.Add((Id=9211, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_FlameThrower', MIC_1P=("WEP_SkinSet52_MAT.sour_flamethrower.Sour_Flamethrower_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_flamethrower.Sour_Flamethrower_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_flamethrower.Sour_Flamethrower_3P_Pickup_MIC")) + +//XMas Sour HMTech-501 Grenade Rifle + Skins.Add((Id=9212, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_MedicRifleGrenadeLauncher', MIC_1P=("WEP_SkinSet52_MAT.sour_medicgrenadelauncher.Sour_MedicGrenadeLauncher_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_medicgrenadelauncher.Sour_MedicGrenadeLauncher_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_medicgrenadelauncher.Sour_MedicGrenadeLauncher_3P_Pickup_MIC")) + +//XMas Sour M32 + Skins.Add((Id=9213, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_M32', MIC_1P=("WEP_SkinSet52_MAT.sour_m32.Sour_M32_1P_Mint_MIC", "WEP_SkinSet52_MAT.sour_m32.Sour_M32_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_m32.Sour_M32_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_m32.Sour_M32_3P_Pickup_MIC")) + +//XMas Sour P90 + Skins.Add((Id=9214, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_P90', MIC_1P=("WEP_SkinSet52_MAT.sour_p90.Sour_P90_1P_Mint_MIC", "WEP_SkinSet52_MAT.sour_p90.Sour_P90_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_p90.Sour_P90_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_p90.Sour_P90_3P_Pickup_MIC")) + +//XMas Sour RPG-7 + Skins.Add((Id=9215, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_RPG7', MIC_1P=("WEP_SkinSet52_MAT.sour_rpg7.Sour_RPG7_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_rpg7.Sour_RPG7_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_rpg7.Sour_RPG7_3P_Pickup_MIC")) + +//XMas Sour Scar + Skins.Add((Id=9216, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Scar', MIC_1P=("WEP_SkinSet52_MAT.sour_scar.Sour_SCAR_1P_Mint_MIC", "WEP_SkinSet52_MAT.sour_scar.Sour_SCAR_Sight_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_scar.Sour_SCAR_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_scar.Sour_SCAR_3P_Pickup_MIC")) + +//XMas Sour Spitfire + Skins.Add((Id=9217, bNeedsCodeUpdates = true, Weapondef=class'KFWeapDef_Flaregun', MIC_1P=("WEP_SkinSet52_MAT.sour_flaregun.Sour_FlareGun_1P_Mint_MIC"), MIC_3P="WEP_SkinSet52_MAT.sour_flaregun.Sour_FlareGun_3P_Mint_MIC", MIC_Pickup="WEP_SkinSet52_MAT.sour_flaregun.Sour_FlareGun_3P_Pickup_MIC")) } \ No newline at end of file diff --git a/KFGame/Classes/KFWeeklyOutbreakInformation.uc b/KFGame/Classes/KFWeeklyOutbreakInformation.uc index eca2e1d..0f0e359 100644 --- a/KFGame/Classes/KFWeeklyOutbreakInformation.uc +++ b/KFGame/Classes/KFWeeklyOutbreakInformation.uc @@ -27,7 +27,7 @@ var localized array ModifierDescriptions; cpptext { /** Num of Weekly events available */ - static const int NumWeeklyEvents = 14; + static const int NumWeeklyEvents = 16; } DefaultProperties { diff --git a/KFGame/KFOnlineStats.uci b/KFGame/KFOnlineStats.uci index 0a67293..de06714 100644 --- a/KFGame/KFOnlineStats.uci +++ b/KFGame/KFOnlineStats.uci @@ -155,4 +155,5 @@ const STATID_ACHIEVE_ElysiumEndlessWaveFifteen = 4057; const STATID_ACHIEVE_Dystopia2029Collectibles = 4058; const STATID_ACHIEVE_MoonbaseCollectibles = 4059; const STATID_ACHIEVE_NetherholdCollectibles = 4060; +const STATID_ACHIEVE_CarillonHamletCollectibles = 4061; /** `endif */ diff --git a/KFGameContent/Classes/KFAIController_ZedFleshpoundKing.uc b/KFGameContent/Classes/KFAIController_ZedFleshpoundKing.uc index 65a9de2..4e12d08 100644 --- a/KFGameContent/Classes/KFAIController_ZedFleshpoundKing.uc +++ b/KFGameContent/Classes/KFAIController_ZedFleshpoundKing.uc @@ -280,9 +280,9 @@ DefaultProperties MaxChestBeamHeightOffset=64.f PhaseThresholds[0]=1 - PhaseThresholds[1]=0.65 //0.75 - PhaseThresholds[2]=0.5 - PhaseThresholds[3]=0.2 //0.25 //0.1 + PhaseThresholds[1]=0.75 //0.65 //0.75 + PhaseThresholds[2]=0.6 //0.5 + PhaseThresholds[3]=0.3 //0.2 //0.25 //0.1 ChestBeamMinPhase=2 diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner.uc new file mode 100644 index 0000000..f7f6f0d --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner.uc @@ -0,0 +1,51 @@ +//============================================================================= +// KFDT_Ballistic_HRG_Stunner +//============================================================================= +// Damage type class for the HRG Stunner +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_HRG_Stunner extends KFDT_Ballistic_Submachinegun + abstract + hidedropdown; + +/** Allows the damage type to customize exactly which hit zones it can dismember */ +static simulated function bool CanDismemberHitZone( name InHitZoneName ) +{ + if( super.CanDismemberHitZone( InHitZoneName ) ) + { + return true; + } + + switch ( InHitZoneName ) + { + case 'lupperarm': + case 'rupperarm': + case 'chest': + case 'heart': + return true; + } + + return false; +} + +defaultproperties +{ + BloodSpread=0.4 + BloodScale=0.6 + + KDamageImpulse=1500 //900 + KDeathUpKick=-1000 //-500 + KDeathVel=600 //350 + GibImpulseScale=1.0 + + StumblePower=35 + KnockdownPower=25 + GunHitPower=25 + + //Perk + ModifierPerkList(0)=class'KFPerk_SWAT' + WeaponDef=class'KFWeapDef_HRG_Stunner' +} diff --git a/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner_Alt.uc b/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner_Alt.uc new file mode 100644 index 0000000..2ef851f --- /dev/null +++ b/KFGameContent/Classes/KFDT_Ballistic_HRG_Stunner_Alt.uc @@ -0,0 +1,49 @@ +//============================================================================= +// KFDT_Ballistic_HRG_Stunner_Alt +//============================================================================= +// Damage type class for the HRG Stunner alt fire +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Ballistic_HRG_Stunner_Alt extends KFDT_Ballistic_Submachinegun + abstract + hidedropdown; + +/** Allows the damage type to customize exactly which hit zones it can dismember */ +static simulated function bool CanDismemberHitZone( name InHitZoneName ) +{ + if( super.CanDismemberHitZone( InHitZoneName ) ) + { + return true; + } + + switch ( InHitZoneName ) + { + case 'lupperarm': + case 'rupperarm': + case 'chest': + case 'heart': + return true; + } + + return false; +} + +defaultproperties +{ + BloodSpread=0.4 + BloodScale=0.6 + + KDamageImpulse=900 + KDeathUpKick=-500 + KDeathVel=350 + + StumblePower=0 //200 + GunHitPower=0 //150 + + //Perk + ModifierPerkList(0)=class'KFPerk_SWAT' + WeaponDef=class'KFWeapDef_HRG_Stunner' +} diff --git a/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun.uc b/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun.uc new file mode 100644 index 0000000..e91f3a8 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun.uc @@ -0,0 +1,16 @@ +//============================================================================= +// KFDT_Bludgeon_Doshinegun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Bludgeon_Doshinegun extends KFDT_Bludgeon_RifleButt + abstract + hidedropdown; + +DefaultProperties +{ + //defaults + WeaponDef=class'KFWeapDef_Doshinegun' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun_Shot.uc b/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun_Shot.uc new file mode 100644 index 0000000..ef0167f --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_Doshinegun_Shot.uc @@ -0,0 +1,25 @@ +//============================================================================= +// KFDT_Bludgeon_Doshinegun_Shot +//============================================================================= +// Bills hit hard +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Bludgeon_Doshinegun_Shot extends KFDT_Bludgeon + abstract + hidedropdown; + +defaultproperties +{ + KDamageImpulse=900 + KDeathUpKick=-300 + KDeathVel=100 + + StumblePower=120 + StunPower=40 + GunHitPower=150 + + WeaponDef=class'KFWeapDef_Doshinegun' +} diff --git a/KFGameContent/Classes/KFDT_Bludgeon_HRG_Stunner.uc b/KFGameContent/Classes/KFDT_Bludgeon_HRG_Stunner.uc new file mode 100644 index 0000000..9f42f0a --- /dev/null +++ b/KFGameContent/Classes/KFDT_Bludgeon_HRG_Stunner.uc @@ -0,0 +1,16 @@ +//============================================================================= +// KFDT_Bludgeon_HRG_Stunner +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Bludgeon_HRG_Stunner extends KFDT_Bludgeon_RifleButt + abstract + hidedropdown; + +DefaultProperties +{ + //defaults + WeaponDef=class'KFWeapDef_HRG_Stunner' +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFDT_Explosive_HRG_Stunner.uc b/KFGameContent/Classes/KFDT_Explosive_HRG_Stunner.uc new file mode 100644 index 0000000..c696c76 --- /dev/null +++ b/KFGameContent/Classes/KFDT_Explosive_HRG_Stunner.uc @@ -0,0 +1,29 @@ +//============================================================================= +// KFDT_Explosive_HRG_Stunner +//============================================================================= +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFDT_Explosive_HRG_Stunner extends KFDT_Explosive + abstract + hidedropdown; + +defaultproperties +{ + bShouldSpawnPersistentBlood=true + + // physics impact + RadialDamageImpulse=3000 //5000 //20000 + GibImpulseScale=0.15 + KDeathUpKick=1000 + KDeathVel=300 + + StunPower=160 + StumblePower=40 + + //Perk + ModifierPerkList(0)=class'KFPerk_SWAT' + WeaponDef=class'KFWeapDef_HRG_Stunner' +} diff --git a/KFGameContent/Classes/KFExplosion_MineReconstructor.uc b/KFGameContent/Classes/KFExplosion_MineReconstructor.uc index 30c8652..7a6f138 100644 --- a/KFGameContent/Classes/KFExplosion_MineReconstructor.uc +++ b/KFGameContent/Classes/KFExplosion_MineReconstructor.uc @@ -259,8 +259,8 @@ DefaultProperties HealingDamageType=class'KFDT_Healing' HealingAmount=0; - fMinAmmoutHealing=4; - fMaxAmmoutHealing=40 //24; + fMinAmmoutHealing=5; //4; + fMaxAmmoutHealing=50; //40 Interval=0 MaxTime=0.0 diff --git a/KFGameContent/Classes/KFExplosion_ParasiteSeed.uc b/KFGameContent/Classes/KFExplosion_ParasiteSeed.uc index 094f85a..6dde3fb 100644 --- a/KFGameContent/Classes/KFExplosion_ParasiteSeed.uc +++ b/KFGameContent/Classes/KFExplosion_ParasiteSeed.uc @@ -85,7 +85,7 @@ DefaultProperties HealingDamageType=class'KFDT_Healing_ParasiteSeed' HealingAmount=5 //10 Interval=0.5 //1 - MaxTime=5.5 //6.5 //8 + MaxTime=5.0 //5.5 bExplodeMoreThanOnce=false bDoFullDamage=false //true diff --git a/KFGameContent/Classes/KFExplosion_ParasiteSeedHuman.uc b/KFGameContent/Classes/KFExplosion_ParasiteSeedHuman.uc index 52ad356..f4bcf85 100644 --- a/KFGameContent/Classes/KFExplosion_ParasiteSeedHuman.uc +++ b/KFGameContent/Classes/KFExplosion_ParasiteSeedHuman.uc @@ -12,7 +12,7 @@ class KFExplosion_ParasiteSeedHuman extends KFExplosion_MedicGrenade; DefaultProperties { HealingDamageType=class'KFDT_Healing_ParasiteSeed' - HealingAmount=30 //10 + HealingAmount=25 //30 //10 Interval=1.0 //1 MaxTime=0.5 //6.5 //8 diff --git a/KFGameContent/Classes/KFGameInfo_Survival.uc b/KFGameContent/Classes/KFGameInfo_Survival.uc index df92749..4f5947a 100644 --- a/KFGameContent/Classes/KFGameInfo_Survival.uc +++ b/KFGameContent/Classes/KFGameInfo_Survival.uc @@ -107,6 +107,9 @@ function StartMatch() function PlayWaveStartDialog() { + if (OutbreakEvent != none && OutbreakEvent.ActiveEvent.bBossRushMode) + return; + `DialogManager.PlayWaveStartDialog(MyKFGRI.IsBossWave()); if (WaveNum == 1) { @@ -432,7 +435,7 @@ function UpdateGameSettings() { for( i = 0; i < GameReplicationInfo.PRIArray.Length; i++ ) { - if( !GameReplicationInfo.PRIArray[i].bBot ) + if (!GameReplicationInfo.PRIArray[i].bBot && !GameReplicationInfo.PRIArray[i].bOnlySpectator && PlayerController(GameReplicationInfo.PRIArray[i].Owner) != none) { NumHumanPlayers++; } diff --git a/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc b/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc index 25995ae..e03515f 100644 --- a/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc +++ b/KFGameContent/Classes/KFGameInfo_WeeklySurvival.uc @@ -66,9 +66,13 @@ event PreBeginPlay() OutbreakEvent.UpdateGRI(); - if (Role == Role_Authority && MyKFGRI != none && OutbreakEvent.ActiveEvent.bUnlimitedWeaponPickups) + if (Role == Role_Authority && MyKFGRI != none) { - MyKFGRI.NotifyBrokenTrader(); + MyKFGRI.NotifyWeeklyEventIndex(ActiveEventIdx); + if ( OutbreakEvent.ActiveEvent.bUnlimitedWeaponPickups) + { + MyKFGRI.NotifyBrokenTrader(); + } } } @@ -226,7 +230,19 @@ function ResetPermanentZed() function float GetAdjustedAIDoshValue( class MonsterClass ) { - return super.GetAdjustedAIDoshValue(MonsterClass) * OutbreakEvent.ActiveEvent.DoshOnKillGlobalModifier; + if (!OutbreakEvent.ActiveEvent.bBossRushMode) + { + return super.GetAdjustedAIDoshValue(MonsterClass) * OutbreakEvent.ActiveEvent.DoshOnKillGlobalModifier; + } + else + { + if ((WaveNum-1) < OutbreakEvent.ActiveEvent.BossRushOverrideParams.PerWaves.length) + { + return super.GetAdjustedAIDoshValue(MonsterClass) * OutbreakEvent.ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum-1].DoshOnKillGlobalModifier; + } + } + + return super.GetAdjustedAIDoshValue(MonsterClass); } protected function ScoreMonsterKill( Controller Killer, Controller Monster, KFPawn_Monster MonsterPawn ) @@ -385,24 +401,37 @@ function SetBossIndex() { local BossSpawnReplacement Replacement; local int ReplaceIdx; + local int i; - BossIndex = Rand(default.AIBossClassList.Length); + // Ignore normal events. + if (OutbreakEvent.ActiveEvent.bBossRushMode) + { + if (BossRushEnemies.length == 0) + { + for(i=0; i < default.AIBossClassList.length; ++i) + { + BossRushEnemies.AddItem(i); + } + } + } - //Search in the replacement list for the one that the game type wanted to use - // If we find it, grab the appropriate index into the original AI class list - // so we can properly cache it. - foreach OutbreakEvent.ActiveEvent.BossSpawnReplacementList(Replacement) - { - if (Replacement.SpawnEntry == BossIndex) - { - ReplaceIdx = AIBossClassList.Find(Replacement.NewClass); - if (ReplaceIdx != INDEX_NONE) - { - BossIndex = ReplaceIdx; - break; - } - } - } + BossIndex = Rand(default.AIBossClassList.Length); + + //Search in the replacement list for the one that the game type wanted to use + // If we find it, grab the appropriate index into the original AI class list + // so we can properly cache it. + foreach OutbreakEvent.ActiveEvent.BossSpawnReplacementList(Replacement) + { + if (Replacement.SpawnEntry == BossIndex) + { + ReplaceIdx = AIBossClassList.Find(Replacement.NewClass); + if (ReplaceIdx != INDEX_NONE) + { + BossIndex = ReplaceIdx; + break; + } + } + } MyKFGRI.CacheSelectedBoss(BossIndex); } @@ -439,6 +468,10 @@ function TickZedTime( float DeltaTime ) function WaveEnded(EWaveEndCondition WinCondition) { local KFPawn_Human Pawn; + local bool bWasFirstTime; + + // This function is called multiple times in a row. Only apply it once. + bWasFirstTime = bWaveStarted; super.WaveEnded(WinCondition); @@ -456,9 +489,30 @@ function WaveEnded(EWaveEndCondition WinCondition) } } + if (WinCondition == WEC_WaveWon && bWasFirstTime) + { + GrantExtraDoshOnWaveWon(); + } + DisableGlobalDamage(); } +/** Grant dosh to every player even no matter it's state when a wave is won. */ +function GrantExtraDoshOnWaveWon() +{ + local KFPlayerController KFPC; + local int ExtraDosh; + // + if (OutbreakEvent.ActiveEvent.bBossRushMode && (WaveNum-1) < OutbreakEvent.ActiveEvent.BossRushOverrideParams.PerWaves.length) + { + ExtraDosh = OutbreakEvent.ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum-1].ExtraDoshGrantedonWaveWon; + foreach WorldInfo.AllControllers(class'KFPlayerController', KFPC) + { + KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo).AddDosh(ExtraDosh, true); + } + } +} + function ClearZedTimePCTimers() { local KFPlayerController_WeeklySurvival KFPC; diff --git a/KFGameContent/Classes/KFOutbreakEvent_Weekly.uc b/KFGameContent/Classes/KFOutbreakEvent_Weekly.uc index 532f1ea..e7c88c1 100644 --- a/KFGameContent/Classes/KFOutbreakEvent_Weekly.uc +++ b/KFGameContent/Classes/KFOutbreakEvent_Weekly.uc @@ -10,24 +10,42 @@ class KFOutbreakEvent_Weekly extends KFOutbreakEvent; function OnScoreKill(Pawn KilledPawn) { - local StatAdjustments ToAdjust; + local int WaveNum; - foreach ActiveEvent.ZedsToAdjust(ToAdjust) - { - if (ClassIsChildOf(KilledPawn.class, ToAdjust.ClassToAdjust)) - { - if (ToAdjust.bExplosiveDeath && ToAdjust.ExplosionTemplate != none) - { - //Skip if we shouldn't do the normal death explosion - if (KFPawn(KilledPawn) != none && !KFPawn(KilledPawn).WeeklyShouldExplodeOnDeath()) - { - return; - } + if (!ActiveEvent.bBossRushMode) + { + AdjustScoreKill(KilledPawn, ActiveEvent.ZedsToAdjust); + } + else + { + WaveNum = KFGameInfo_WeeklySurvival(Outer).WaveNum - 1; + if ( WaveNum < ActiveEvent.BossRushOverrideParams.PerWaves.length ) + { + AdjustScoreKill(KilledPawn, ActiveEvent.BossRushOverrideParams.PerWaves[WaveNum].ZedsToAdjust); + } + } +} - KFGameInfo_WeeklySurvival(Outer).DoDeathExplosion(KilledPawn, ToAdjust.ExplosionTemplate, ToAdjust.ExplosionIgnoreClass); - } - } - } +function AdjustScoreKill(Pawn KilledPawn, array Adjustments) +{ + local StatAdjustments ToAdjust; + + foreach Adjustments(ToAdjust) + { + if (ClassIsChildOf(KilledPawn.class, ToAdjust.ClassToAdjust)) + { + if (ToAdjust.bExplosiveDeath && ToAdjust.ExplosionTemplate != none) + { + //Skip if we shouldn't do the normal death explosion + if (KFPawn(KilledPawn) != none && !KFPawn(KilledPawn).WeeklyShouldExplodeOnDeath()) + { + return; + } + + KFGameInfo_WeeklySurvival(Outer).DoDeathExplosion(KilledPawn, ToAdjust.ExplosionTemplate, ToAdjust.ExplosionIgnoreClass); + } + } + } } function AdjustScoreDamage(Controller InstigatedBy, Pawn DamagedPawn, class damageType) @@ -594,31 +612,31 @@ defaultproperties )}, ZedsToAdjust={( - (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch',HealthScale=2.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch',HealthScale=2.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans',HealthScale=2.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing',HealthScale=2.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing',HealthScale=2.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch',HealthScale=1.75,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.25), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch',HealthScale=1.75,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.25), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans',HealthScale=1.75,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.25), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing',HealthScale=1.75,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.25), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing',HealthScale=1.75,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.25), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Cyst',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Alpha',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Slasher',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedSiren',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedStalker',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedCrawler',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedCrawlerKing',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefast',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedScrake',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpound',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Cyst', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Alpha', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_Slasher', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedSiren', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedStalker', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedCrawler', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedCrawlerKing', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefast', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedScrake', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpound', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2), - (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',bStartEnraged=true, DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2) + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn', DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.2) )}, SpawnReplacementList={( (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15), @@ -626,10 +644,270 @@ defaultproperties (SpawnEntry=AT_GoreFast,NewClass=(class'KFGameContent.KFPawn_ZedGorefastDualBlade'),PercentChance=0.15), (SpawnEntry=AT_Crawler,NewClass=(class'KFGameContent.KFPawn_ZedCrawlerKing'),PercentChance=0.15), (SpawnEntry=AT_Bloat,NewClass=(class'KFGameContent.KFPawn_ZedScrake'),PercentChance=0.05), - (SpawnEntry=AT_FleshpoundMini,NewClass=(class'KFGameContent.KFPawn_ZedFleshpound'),PercentChance=0.05) + (SpawnEntry=AT_FleshpoundMini,NewClass=(class'KFGameContent.KFPawn_ZedFleshpound'),PercentChance=0.2) )} )} + // Boss Rush + SetEvents[14]={( + EventDifficulty=2, + GameLength=GL_Short, + SpawnRateMultiplier=0, + bBossRushMode=true, + OverrideAmmoPickupModifier=1, + WaveAmmoPickupModifiers={( + 0.99, 0.99, 0.99, 0.99, 0.99 + )}, + BossRushOverrideParams={(PerWaves={( + // WAVE 1 + (ZedsToAdjust={( + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch', HealthScale=0.22,DamageDealtScale=0.7, InitialGroundSpeedModifierScale=0.75,ShieldScale=0.22), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=0.22,DamageDealtScale=0.7, InitialGroundSpeedModifierScale=0.75), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=0.22,DamageDealtScale=0.7, InitialGroundSpeedModifierScale=0.75,ShieldScale=0.22), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=0.22,DamageDealtScale=0.7, InitialGroundSpeedModifierScale=0.75,ShieldScale=0.22), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=0.22,DamageDealtScale=0.7, InitialGroundSpeedModifierScale=0.75,ShieldScale=0.22), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=0.6,DamageDealtScale=0.5, InitialGroundSpeedModifierScale=0.7), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',HealthScale=0.6,DamageDealtScale=0.3, InitialGroundSpeedModifierScale=0.6) + )}, + /*SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15), + (SpawnEntry=AT_AlphaClot,NewClass=(class'KFGameContent.KFPawn_ZedClot_AlphaKing'),PercentChance=0.15), + (SpawnEntry=AT_GoreFast,NewClass=(class'KFGameContent.KFPawn_ZedGorefastDualBlade'),PercentChance=0.15), + (SpawnEntry=AT_Crawler,NewClass=(class'KFGameContent.KFPawn_ZedCrawlerKing'),PercentChance=0.15), + (SpawnEntry=AT_Bloat,NewClass=(class'KFGameContent.KFPawn_ZedScrake'),PercentChance=0.05), + (SpawnEntry=AT_FleshpoundMini,NewClass=(class'KFGameContent.KFPawn_ZedFleshpound'),PercentChance=0.05) + )},*/ + DoshOnKillGlobalModifier=0.0f, + ExtraDoshGrantedonWaveWon=1700), + // WAVE 2 + (ZedsToAdjust={( + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0,ShieldScale=0.9), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0,ShieldScale=0.9), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0,ShieldScale=0.9), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0,ShieldScale=0.9), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',HealthScale=0.9,DamageDealtScale=0.9, InitialGroundSpeedModifierScale=1.0) + )}, + /*SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15) + )},*/ + DoshOnKillGlobalModifier=0.0f, + ExtraDoshGrantedonWaveWon=2000), + // WAVE 3 + (ZedsToAdjust={( + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0) + )}, + /*SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15) + )},*/ + DoshOnKillGlobalModifier=0.0f, + ExtraDoshGrantedonWaveWon=2300), + // WAVE 4 + (ZedsToAdjust={( + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch', HealthScale=1.1,DamageDealtScale=1.1, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.1), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=1.1,DamageDealtScale=1.1, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=1.1,DamageDealtScale=1.1, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.1), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=1.1,DamageDealtScale=1.1, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.1), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=1.1,DamageDealtScale=1.1, InitialGroundSpeedModifierScale=1.0,ShieldScale=1.1), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0) + )}, + /*SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15) + )},*/ + DoshOnKillGlobalModifier=0.0f, + ExtraDoshGrantedonWaveWon=3000), + // WAVE 5 + (ZedsToAdjust={( + (ClassToAdjust=class'KFGameContent.KFPawn_ZedMatriarch', HealthScale=1.4,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.2,ShieldScale=1.4), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=1.4,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.2), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=1.4,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.2,ShieldScale=1.4), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=1.4,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.2,ShieldScale=1.4), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=1.4,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.2,ShieldScale=1.4), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_EMP', HealthScale=1.0,DamageDealtScale=1.2, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Laser', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedDAR_Rocket', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing', HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKingSubspawn',HealthScale=1.0,DamageDealtScale=1.0, InitialGroundSpeedModifierScale=1.0) + )}, + /*SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_Alpha'),PercentChance=0.15) + )},*/ + DoshOnKillGlobalModifier=0.0f, + ExtraDoshGrantedonWaveWon=0) + )} + )} + )} + + //Tiny head + SetEvents[15]={( + EventDifficulty=2, + GameLength=GL_Normal, + ZedSpawnHeadScale=0.3, + PlayerSpawnHeadScale=0.2, + bDisableHeadless=true, + SpawnRateMultiplier=1.5, + WaveAICountScale=(0.8, 0.8, 0.8, 0.8, 0.8, 0.8), + DoshOnKillGlobalModifier=1.2, + //GlobalAmmoCostScale = 0.5, + bInvulnerableHeads = true, + BossSpawnReplacementList={( + (SpawnEntry=BAT_Matriarch,NewClass=class'KFGameContent.KFPawn_ZedHans') + )}, + SpawnReplacementList={( + (SpawnEntry=AT_Clot,NewClass=(class'KFGameContent.KFPawn_ZedClot_AlphaKing'),PercentChance=0.2), + (SpawnEntry=AT_AlphaClot,NewClass=(class'KFGameContent.KFPawn_ZedClot_AlphaKing'),PercentChance=0.2), + (SpawnEntry=AT_SlasherClot,NewClass=(class'KFGameContent.KFPawn_ZedClot_AlphaKing'),PercentChance=0.2), + //(SpawnEntry=AT_Crawler,NewClass=(class'KFGameContent.KFPawn_ZedGorefastDualBlade'),PercentChance=0.4), + (SpawnEntry=AT_Stalker,NewClass=(class'KFGameContent.KFPawn_ZedGorefastDualBlade'),PercentChance=1.0), + (SpawnEntry=AT_Bloat,NewClass=(class'KFGameContent.KFPawn_ZedBloat'),PercentChance=1.0), + (SpawnEntry=AT_Siren,NewClass=(class'KFGameContent.KFPawn_ZedSiren'),PercentChance=1.0), + (SpawnEntry=AT_Husk,NewClass=(class'KFGameContent.KFPawn_ZedHusk'),PercentChance=1.0), + (SpawnEntry=AT_GoreFast,NewClass=(class'KFGameContent.KFPawn_ZedGorefastDualBlade'),PercentChance=1.0), + (SpawnEntry=AT_FleshPound,NewClass=(class'KFGameContent.KFPawn_ZedScrake'),PercentChance=0.3), + (SpawnEntry=AT_FleshpoundMini,NewClass=(class'KFGameContent.KFPawn_ZedScrake'),PercentChance=0.3), + //(SpawnEntry=AT_EliteClot,NewClass=(class'KFGameContent.KFPawn_ZedCrawler'),PercentChance=0.6), + //(SpawnEntry=AT_EliteGoreFast,NewClass=(class'KFGameContent.KFPawn_ZedCrawler'),PercentChance=0.6), + (SpawnEntry=AT_EDAR_EMP,NewClass=(class'KFGameContent.KFPawn_ZedBloat'),PercentChance=1.0), + (SpawnEntry=AT_EDAR_Laser,NewClass=(class'KFGameContent.KFPawn_ZedBloat'),PercentChance=1.0), + (SpawnEntry=AT_EDAR_Rocket,NewClass=(class'KFGameContent.KFPawn_ZedBloat'),PercentChance=1.0) + + )}, + ZedsToAdjust={( + //bosses + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHans', HealthScale=1.2,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=armor, GoreHealth=MaxInt, DmgScale=1.3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = Spine2, Offset=(X=-5,Y=45,Z=10)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedPatriarch', HealthScale=1.2,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rfoot, GoreHealth=MaxInt, DmgScale=1.3, MaxGoreHealth=MaxInt), + (ZoneName=rcalf, GoreHealth=MaxInt, DmgScale=1.3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightLeg) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundKing', HealthScale=1.2,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=heart, GoreHealth=MaxInt, DmgScale=1.3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = Spine2, Offset=(X=30,Y=-30,Z=10)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloatKing', HealthScale=1.4,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rupperarm, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt), + (ZoneName=rforearm, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt), + (ZoneName=rhand, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt), + (ZoneName=lupperarm, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt), + (ZoneName=lforearm, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt), + (ZoneName=lhand, GoreHealth=MaxInt, DmgScale=1.5, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightForearm, Offset=(X=15,Y=0,Z=5)), + (BoneName = LeftForearm, Offset=(X=25,Y=15,Z=15)) + )}), + + //arms + (ClassToAdjust=class'KFGameContent.KFPawn_ZedHusk',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rforearm, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rupperarm, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightForearm, Offset=(X=20,Y=0,Z=5)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedScrake',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rforearm, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rupperarm, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName=RightForearm, Offset=(X=20,Y=0,Z=10)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedBloat',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rupperarm, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt), + (ZoneName=rforearm, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt), + (ZoneName=rhand, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt), + (ZoneName=lupperarm, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt), + (ZoneName=lforearm, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt), + (ZoneName=lhand, GoreHealth=MaxInt, DmgScale=4, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightForearm, Offset=(X=20,Y=0,Z=5)), + (BoneName = LeftForearm, Offset=(X=20,Y=7,Z=5)) + )}), + + //legs + (ClassToAdjust=class'KFGameContent.KFPawn_ZedSiren',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rfoot, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=lfoot, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rcalf, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=lcalf, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rthigh, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=lthigh, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightLeg, Offset=(X=0,Y=0,Z=10)), + (BoneName = LeftLeg, Offset=(X=50,Y=0,Z=10)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedClot_AlphaKing',HealthScale=1.5,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=rfoot, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rcalf, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=rthigh, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = RightLeg, Offset=(X=0,Y=0,Z=15)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedGorefastDualBlade',HealthScale=1.3,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=lfoot, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=lcalf, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt), + (ZoneName=lthigh, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = LeftLeg, Offset=(X=50,Y=0,Z=10)) + )}), + + //heart + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpoundMini',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=heart, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = Spine2, Offset=(X=25,Y=-25,Z=10)) + )}), + (ClassToAdjust=class'KFGameContent.KFPawn_ZedFleshpound',HealthScale=1.0,DamageDealtScale=1.0, HitZonesOverride = {( + (ZoneName=heart, GoreHealth=MaxInt, DmgScale=3, MaxGoreHealth=MaxInt) + )}, WeakPoints = {( + (BoneName = Spine2, Offset=(X=30,Y=-30,Z=10)) + )}) + )} + )} + //Test events from here down. These don't end up in the regular rotation. // The override ID starts from one higher than the last SetEvents entry above. // Ex: Big head = 7, Horde = 8 diff --git a/KFGameContent/Classes/KFPawn_ZedBloatKing.uc b/KFGameContent/Classes/KFPawn_ZedBloatKing.uc index 9733201..878cafe 100644 --- a/KFGameContent/Classes/KFPawn_ZedBloatKing.uc +++ b/KFGameContent/Classes/KFPawn_ZedBloatKing.uc @@ -595,25 +595,25 @@ defaultproperties //Fart is base timer +/- some random amount of the variance, giving you a range of say 25-35 seconds with a base of 30 and variance of 5 // These values are X = 0 health, Y = 100% health - DifficultyFartAttackTimers(0)=(X=5.0,Y=9.0) // Normal - DifficultyFartAttackTimers(1)=(X=4.5,Y=8.5) // Hard - DifficultyFartAttackTimers(2)=(X=4.0,Y=8.0) // Suicidal - DifficultyFartAttackTimers(3)=(X=4.0,Y=7.0) // Hell On Earth + DifficultyFartAttackTimers(0)=(X=4.0,Y=7.0) // Normal //(X=5.0,Y=9.0) + DifficultyFartAttackTimers(1)=(X=3.5,Y=6.0) // Hard //(X=4.5,Y=8.5) + DifficultyFartAttackTimers(2)=(X=3.0,Y=5.5) // Suicidal //(X=4.0,Y=8.0) + DifficultyFartAttackTimers(3)=(X=3.0,Y=5.0) // Hell On Earth //(X=4.0,Y=7.0) - DifficultyVarianceFartTimers(0)=(X=3.0,Y=4.0) // Normal - DifficultyVarianceFartTimers(1)=(X=2.5,Y=3.5) // Hard - DifficultyVarianceFartTimers(2)=(X=2.0,Y=3.0) // Suicidal - DifficultyVarianceFartTimers(3)=(X=2.0,Y=3.0) // Hell On Earth + DifficultyVarianceFartTimers(0)=(X=2.5,Y=3.5) // Normal //(X=3.0,Y=4.0) + DifficultyVarianceFartTimers(1)=(X=2.0,Y=3.0) // Hard //(X=2.5,Y=3.5) + DifficultyVarianceFartTimers(2)=(X=1.5,Y=2.5) // Suicidal //(X=2.0,Y=3.0) + DifficultyVarianceFartTimers(3)=(X=1.5,Y=2.5) // Hell On Earth //(X=2.0,Y=3.0) - DifficultyRageFartTimers(0)=(X=1.75,Y=2.5) // Normal - DifficultyRageFartTimers(1)=(X=1.25,Y=2.0) // Hard - DifficultyRageFartTimers(2)=(X=0.75,Y=1.5) // Suicidal - DifficultyRageFartTimers(3)=(X=0.75,Y=1.5) // Hell On Earth + DifficultyRageFartTimers(0)=(X=1.5,Y=2.25) // Normal //(X=1.75,Y=2.5) + DifficultyRageFartTimers(1)=(X=1.0,Y=1.75) // Hard //(X=1.25,Y=2.0) + DifficultyRageFartTimers(2)=(X=0.5,Y=1.25) // Suicidal //(X=0.75,Y=1.5) + DifficultyRageFartTimers(3)=(X=0.5,Y=1.25) // Hell On Earth //(X=0.75,Y=1.5) - DifficultyVarianceRageFartTimers(0)=(X=1.65,Y=2.1) // Normal - DifficultyVarianceRageFartTimers(1)=(X=1.15,Y=1.6) // Hard - DifficultyVarianceRageFartTimers(2)=(X=0.65,Y=1.1) // Suicidal - DifficultyVarianceRageFartTimers(3)=(X=0.65,Y=1.1) // Hell On Earth + DifficultyVarianceRageFartTimers(0)=(X=1.65,Y=2.1) // Normal //(X=1.65,Y=2.1) + DifficultyVarianceRageFartTimers(1)=(X=1.15,Y=1.6) // Hard //(X=1.15,Y=1.6) + DifficultyVarianceRageFartTimers(2)=(X=0.65,Y=1.1) // Suicidal //(X=0.65,Y=1.1) + DifficultyVarianceRageFartTimers(3)=(X=0.65,Y=1.1) // Hell On Earth //(X=0.65,Y=1.1) //Offset from center of the BK to spawn the poop monster PoopMonsterOffset=-100 @@ -622,7 +622,7 @@ defaultproperties PoopMonsterFXSocket=Poop_Attach //Amount of time between spawns - PoopMonsterSpawnDelay=2.f + PoopMonsterSpawnDelay=1.5 //2.f // Used for special crawler gas AOE attack "explosion" template FART ATTACK Begin Object Class=KFGameExplosion Name=ExploTemplate0 @@ -708,9 +708,9 @@ defaultproperties RotationRate=(Pitch=50000,Yaw=20000,Roll=50000) GroundSpeed=450.0f //160 //210 //231 //255 SprintSpeed=450.0f //260 //210 410 //315 //330 //345 //380 - RageSprintSpeedMultiplier=1.3f //1.25 1.45 //1.55 + RageSprintSpeedMultiplier=1.5f //1.3f //1.25 1.45 //1.55 - VomitRange=400.f + VomitRange=440.f //400.f VomitDamage=20 ArmorInfoClass=class'KFZedArmorInfo_BloatKing' diff --git a/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc b/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc index 9466764..ff4e9dc 100644 --- a/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc +++ b/KFGameContent/Classes/KFPawn_ZedBloatKingSubspawn.uc @@ -116,7 +116,7 @@ defaultproperties // Used for special crawler gas AOE attack "explosion" template Begin Object Class=KFGameExplosion Name=ExploTemplate0 - Damage=15 //50 //12 //16 + Damage=12 //15 //50 //12 //16 DamageRadius=350 //600 //450 //400 //425 DamageFalloffExponent=0.f DamageDelay=0.f @@ -179,7 +179,7 @@ defaultproperties MyDamageType=class'KFDT_Slashing_ZedWeak' End Object - Health=250 //55 //450 //700 //900 //810 + Health=150 //250 //55 //450 //700 //900 //810 DoshValue=10 Mass=50.f bKnockdownWhenJumpedOn=true diff --git a/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc b/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc index b5ba917..c08f199 100644 --- a/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc +++ b/KFGameContent/Classes/KFPawn_ZedFleshpoundKing.uc @@ -645,7 +645,7 @@ DefaultProperties ShieldHealthMaxDefaults[1]=2700 //3000 ShieldHealthMaxDefaults[2]=4000//2000 //3000 ShieldHealthMaxDefaults[3]=5000 - ShieldHealthScale=1.f + ShieldHealthScale=1.1f //1.f // Penetration PenetrationResistance=5.0 @@ -686,7 +686,7 @@ DefaultProperties DamageTypeModifiers.Add((DamageType=class'KFDT_Bleeding_HRG_Vampire_BloodSuck', DamageScale=(0.7))) Begin Object Class=KFGameExplosion Name=ExploTemplate0 - Damage=40 //20 + Damage=44 //40 //20 DamageRadius=900 //600 //700 DamageFalloffExponent=2.f DamageDelay=0.f @@ -714,7 +714,7 @@ DefaultProperties RagePoundExplosionTemplate=ExploTemplate0 Begin Object Class=KFGameExplosion Name=ExploTemplate1 - Damage=50 //30 + Damage=55 //50 //30 DamageRadius=900 //600 //700 DamageFalloffExponent=2.f DamageDelay=0.f @@ -760,8 +760,8 @@ DefaultProperties CollisionRadius=+0055.000000 End Object - GroundSpeed=300.f //260 - SprintSpeed=700.f //600 + GroundSpeed=345.f //300.f //260 + SprintSpeed=805.f //700.f //600 ReachedEnemyThresholdScale=1.f PhysRagdollImpulseScale=1.5f KnockdownImpulseScale=2.0f diff --git a/KFGameContent/Classes/KFPawn_ZedStalker.uc b/KFGameContent/Classes/KFPawn_ZedStalker.uc index a177123..33fed3c 100644 --- a/KFGameContent/Classes/KFPawn_ZedStalker.uc +++ b/KFGameContent/Classes/KFPawn_ZedStalker.uc @@ -546,6 +546,8 @@ DefaultProperties CloakedAkComponent=CloakedAkComponent0 Components.Add( CloakedAkComponent0 ) + ZEDCowboyHatAttachName=Hat_Attach + `if(`notdefined(ShippingPC)) DebugRadarTexture=Texture2D'UI_ZEDRadar_TEX.MapIcon_Stalker'; `endif diff --git a/KFGameContent/Classes/KFPickupFactory_Ammo.uc b/KFGameContent/Classes/KFPickupFactory_Ammo.uc index 0e35514..3a94dfe 100644 --- a/KFGameContent/Classes/KFPickupFactory_Ammo.uc +++ b/KFGameContent/Classes/KFPickupFactory_Ammo.uc @@ -42,6 +42,13 @@ simulated event SetInitialState() function GiveTo( Pawn P ) { local KFInventoryManager KFIM; + local KFGameReplicationInfo KFGRI; + + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + if(KFGRI != none && KFGRI.bIsEndlessPaused) + { + return; + } KFIM = KFInventoryManager(P.InvManager); if ( KFIM != None ) diff --git a/KFGameContent/Classes/KFProj_BloatPukeMine.uc b/KFGameContent/Classes/KFProj_BloatPukeMine.uc index 3a969dc..100115b 100644 --- a/KFGameContent/Classes/KFProj_BloatPukeMine.uc +++ b/KFGameContent/Classes/KFProj_BloatPukeMine.uc @@ -532,8 +532,8 @@ defaultproperties LifeSpan=0 FuseDuration=300 PostExplosionLifetime=1 - Speed=1000 //500 - MaxSpeed=1000 //500 + Speed=1500 //1000 //500 + MaxSpeed=1500 //1000 //500 Physics=PHYS_Falling bBounce=true bNetTemporary=false diff --git a/KFGameContent/Classes/KFProj_Bullet_HRG_Boomy.uc b/KFGameContent/Classes/KFProj_Bullet_HRG_Boomy.uc index d38754e..a241802 100644 --- a/KFGameContent/Classes/KFProj_Bullet_HRG_Boomy.uc +++ b/KFGameContent/Classes/KFProj_Bullet_HRG_Boomy.uc @@ -46,7 +46,7 @@ defaultproperties // explosion Begin Object Class=KFGameExplosion Name=ExploTemplate0 Damage=35 //30 - DamageRadius=150 //120 + DamageRadius=200 //150 //120 DamageFalloffExponent=1.f DamageDelay=0.f MomentumTransferScale=10000 diff --git a/KFGameContent/Classes/KFProj_Bullet_HRG_Stunner_Alt.uc b/KFGameContent/Classes/KFProj_Bullet_HRG_Stunner_Alt.uc new file mode 100644 index 0000000..79f3866 --- /dev/null +++ b/KFGameContent/Classes/KFProj_Bullet_HRG_Stunner_Alt.uc @@ -0,0 +1,99 @@ +//============================================================================= +// KFProj_Bullet_HRG_Boomy +//============================================================================= +// Class Description +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFProj_Bullet_HRG_Stunner_Alt extends KFProj_BallisticExplosive + hidedropdown; + +var protected KFWeapon OwnerWeapon; + +/** Initialize the projectile */ +function Init( vector Direction ) +{ + super.Init( Direction ); + + OwnerWeapon = KFWeapon( Owner ); + if( OwnerWeapon != none ) + { + OwnerWeapon.LastPelletFireTime = WorldInfo.TimeSeconds; + } +} + +/** Don't allow more than one pellet projectile to perform this check in a single frame */ +function bool ShouldWarnAIWhenFired() +{ + return super.ShouldWarnAIWhenFired() && OwnerWeapon != none && OwnerWeapon.LastPelletFireTime < WorldInfo.TimeSeconds; +} + +simulated protected function PrepareExplosionTemplate() +{ + super.PrepareExplosionTemplate(); + + /** Since bIgnoreInstigator is transient, its value must be defined here */ + ExplosionTemplate.bIgnoreInstigator = true; +} + +defaultproperties +{ + MaxSpeed=22500.0 + Speed=22500.0 + + DamageRadius=0 + + ProjDisintegrateTemplate=ParticleSystem'ZED_Siren_EMIT.FX_Siren_grenade_disable_01' + // ProjFlightTemplate=ParticleSystem'WEP_HRG_Boomy_EMIT.FX_Boomy_Tracer_ZEDTime' + ProjFlightTemplateZedTime=ParticleSystem'WEP_HRG_Boomy_EMIT.FX_Boomy_Tracer_ZEDTime' + + // Grenade explosion light + Begin Object Class=PointLightComponent Name=ExplosionPointLight + LightColor=(R=252,G=218,B=171,A=255) + Brightness=0.5f + Radius=400.f + FalloffExponent=10.f + CastShadows=False + CastStaticShadows=FALSE + CastDynamicShadows=False + bCastPerObjectShadows=false + bEnabled=FALSE + LightingChannels=(Indoor=TRUE,Outdoor=TRUE,bInitialized=TRUE) + End Object + + // explosion + Begin Object Class=KFGameExplosion Name=ExploTemplate0 + Damage=40 //50 + DamageRadius=300 //250 //150 + DamageFalloffExponent=2.f + DamageDelay=0.f + MomentumTransferScale=10000 + + // Damage Effects + MyDamageType=class'KFDT_Explosive_HRG_Stunner' + KnockDownStrength=150 + FractureMeshRadius=200.0 + FracturePartVel=500.0 + + ExplosionSound=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Alt_Fire_Explosion' + ExplosionEffects=KFImpactEffectInfo'WEP_HRG_Stunner_ARCH.WEB_HRG_Stunner_Impacts' + + // Dynamic Light + ExploLight=ExplosionPointLight + ExploLightStartFadeOutTime=0.0 + ExploLightFadeOutTime=0.3 + + bIgnoreInstigator=true + + // Camera Shake + CamShake=CameraShake'FX_CameraShake_Arch.Misc_Explosions.Light_Explosion_Rumble' + CamShakeInnerRadius=0 + CamShakeOuterRadius=300 + CamShakeFalloff=1.5f + bOrientCameraShakeTowardsEpicenter=true + End Object + ExplosionTemplate=ExploTemplate0 +} + diff --git a/KFGameContent/Classes/KFProj_Bullet_ParasiteImplanterAlt.uc b/KFGameContent/Classes/KFProj_Bullet_ParasiteImplanterAlt.uc index 8a7e5db..08dc476 100644 --- a/KFGameContent/Classes/KFProj_Bullet_ParasiteImplanterAlt.uc +++ b/KFGameContent/Classes/KFProj_Bullet_ParasiteImplanterAlt.uc @@ -317,7 +317,7 @@ defaultproperties // explosion Begin Object Class=KFGameExplosion Name=ExploTemplate0 - Damage=400 //250 + Damage=300 //400 DamageRadius=450 DamageFalloffExponent=0.5f //1.f DamageDelay=0.f diff --git a/KFGameContent/Classes/KFProj_Dosh.uc b/KFGameContent/Classes/KFProj_Dosh.uc new file mode 100644 index 0000000..fb1dcde --- /dev/null +++ b/KFGameContent/Classes/KFProj_Dosh.uc @@ -0,0 +1,240 @@ +//============================================================================= +// KFProj_Dosh +//============================================================================= +// Projectile for the doshinegun +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFProj_Dosh extends KFProj_RicochetBullet + hidedropdown; + +`define KFPROJ_DOSH_CACHED_LOCATION 20 + +var PrimitiveComponent DroppedPickupMesh; + +/** Dampen amount for every bounce */ +var() float DampenFactor; + +/** Dampen amount for parallel angle to velocity */ +var() float DampenFactorParallel; + +var transient Vector PreviousLocations [`KFPROJ_DOSH_CACHED_LOCATION]; +var transient rotator PreviousRotations [`KFPROJ_DOSH_CACHED_LOCATION]; + +// Make sure that last location always exists. +simulated event PostBeginPlay() +{ + Super.PostBeginPlay(); +} + +event Tick( float DeltaTime ) +{ + local int i; + for (i = `KFPROJ_DOSH_CACHED_LOCATION - 1; i > 0; --i) + { + PreviousLocations[i] = PreviousLocations[i-1]; + PreviousRotations[i] = PreviousRotations[i-1]; + } + + if (`KFPROJ_DOSH_CACHED_LOCATION > 0) + { + PreviousLocations[0] = Location; + PreviousRotations[0] = Rotation; + } +} + +/** + * Give a little bounce + */ +simulated event HitWall(vector HitNormal, Actor Wall, PrimitiveComponent WallComp) +{ + local TraceHitInfo HitInfo; + + // check to make sure we didn't hit a pawn + if( Pawn(Wall) == none ) + { + if (!Wall.bStatic && Wall.bCanBeDamaged && (DamageRadius == 0 || bDamageDestructiblesOnTouch) && !CheckRepeatingTouch(Wall) ) + { + HitInfo.HitComponent = WallComp; + HitInfo.Item = INDEX_None; + Wall.TakeDamage( Damage, InstigatorController, Location, MomentumTransfer * Normal(Velocity), MyDamageType, HitInfo, self); + } + } + + Bounce( HitNormal, Wall ); +} + +/** Adjusts movement/physics of projectile. + * Returns true if projectile actually bounced / was allowed to bounce */ +simulated function bool Bounce( vector HitNormal, Actor BouncedOff) +{ + Velocity = DampingFactor * (Velocity - 2.0*HitNormal*(Velocity dot HitNormal)); + if( WorldInfo.NetMode != NM_DedicatedServer ) + { + // do the impact effects + `ImpactEffectManager.PlayImpactEffects(Location, Instigator, HitNormal, ImpactEffects ); + } + + // also done from ProcessDestructibleTouchOnBounce. update LastBounced to solve problem with bouncing rapidly between world/non-world geometry + LastBounced.Actor = BouncedOff; + LastBounced.Time = WorldInfo.TimeSeconds; + + SpawnDosh(BouncedOff); + Destroy(); + + return true; +} + +function SpawnDosh(Actor BouncedOff) +{ + local KFDroppedPickup_Cash P; + local int i; + + if ( WorldInfo.NetMode == NM_Client ) + return; + + if (Pawn(BouncedOff) == none) + { + P = Spawn(class'KFDroppedPickup_Cash',,, Location, Rotation,, false); + + if (P == none) + { + for (i = 0; i < `KFPROJ_DOSH_CACHED_LOCATION; ++i) + { + P = Spawn(class'KFDroppedPickup_Cash',,, PreviousLocations[i], PreviousRotations[i],, false); + if (P != none) + { + break; + } + } + } + } + else + { + P = Spawn(class'KFDroppedPickup_Cash',,, Location, Rotation,, true); + } + + if( P == None ) + { + Destroy(); + } + else + { + P.SetPhysics(PHYS_Falling); + P.InventoryClass = class'KFInventory_Money'; + P.Inventory = Instigator.CreateInventory(P.InventoryClass); + P.Velocity = Velocity; + P.Instigator = Instigator; + P.SetPickupMesh(DroppedPickupMesh); + P.SetPickupParticles(none); + P.CashAmount = class'KFWeap_AssaultRifle_Doshinegun'.default.DoshCost; + } + +} + +//============== +// Touching +// Overridden to get bouncing off of destructible meshes +simulated function ProcessTouch(Actor Other, Vector HitLocation, Vector HitNormal) +{ + local KFPawn KFP; + local KFPawn_Human KFPH; + local KFPlayerReplicationInfo KFPRI; + + KFPH = KFPawn_Human(Other); + if ( KFPH != none && KFPH != Instigator) + { + KFPRI = KFPlayerReplicationInfo(KFPH.PlayerReplicationInfo); + if (KFPRI != none) + { + KFPRI.AddDosh(class'KFWeap_AssaultRifle_Doshinegun'.default.DoshCost); + Destroy(); + return; + } + } + else if ( Other != Instigator && Other.bCanBeDamaged && (!Other.bWorldGeometry || !Other.bStatic) ) + { + KFP = KFPawn( Other ); + if ( KFP != None ) + { + // check/ignore repeat touch events + if( CheckRepeatingTouch(Other) ) + { + return; + } + + ProcessBulletTouch(Other, HitLocation, HitNormal); + + Bounce(HitNormal, Other); + return; + } + else + { + ProcessDestructibleTouchOnBounce( Other, HitLocation, HitNormal ); + return; + } + } + + super.ProcessTouch(Other, HitLocation, HitNormal); +} + +simulated function SyncOriginalLocation() +{ + local Actor HitActor; + local vector HitLocation, HitNormal; + local TraceHitInfo HitInfo; + + if (Role < ROLE_Authority && Instigator != none && Instigator.IsLocallyControlled()) + { + HitActor = Trace(HitLocation, HitNormal, OriginalLocation, Location,,, HitInfo, TRACEFLAG_Bullet); + if (HitActor != none) + { + Bounce(HitNormal, HitActor); + } + } + + Super.SyncOriginalLocation(); +} + + + +defaultproperties +{ + MaxSpeed=7500.0 //5000.0 + Speed=7500.0 //5000.0 + GravityScale=0.57 //0.4 + + Physics=PHYS_Falling + TossZ=100 //150 + MomentumTransfer=50000.0 + + DamageRadius=0 + + bWarnAIWhenFired=true + + BouncesLeft=1 + DampingFactor=0.1 + + DampenFactor=0.250000 + DampenFactorParallel=0.400000 + LifeSpan=120 //8 + + bNetTemporary=False + NetPriority=5 + NetUpdateFrequency=200 + + ProjFlightTemplate=ParticleSystem'WEP_Doshinegun_EMIT.PS_Trail' + ProjFlightTemplateZedTime=ParticleSystem'WEP_Doshinegun_EMIT.PS_Trail' + + ImpactEffects=KFImpactEffectInfo'WEP_Doshinegun_ARCH.Dosh_Impact' + + Begin Object Class=SkeletalMeshComponent Name=PickupMesh0 + SkeletalMesh=SkeletalMesh'GP_Mesh.dosh_SM' + PhysicsAsset=PhysicsAsset'GP_Mesh.dosh_SM_Physics' + BlockNonZeroExtent=false + CastShadow=false + End Object + DroppedPickupMesh=PickupMesh0 +} diff --git a/KFGameContent/Classes/KFProj_Nail_Nailgun.uc b/KFGameContent/Classes/KFProj_Nail_Nailgun.uc index 70aea19..986b485 100644 --- a/KFGameContent/Classes/KFProj_Nail_Nailgun.uc +++ b/KFGameContent/Classes/KFProj_Nail_Nailgun.uc @@ -122,8 +122,8 @@ simulated function Landed( Vector HitNormal, actor FloorActor ) defaultproperties { - MaxSpeed=14000.0 - Speed=14000.0 + MaxSpeed=17500.0 //14000.0 + Speed=17500.0 //14000.0 bWarnAIWhenFired=true diff --git a/KFGameContent/Classes/KFSM_FleshpoundKing_ChestBeam.uc b/KFGameContent/Classes/KFSM_FleshpoundKing_ChestBeam.uc index d37a3df..b5edb87 100644 --- a/KFGameContent/Classes/KFSM_FleshpoundKing_ChestBeam.uc +++ b/KFGameContent/Classes/KFSM_FleshpoundKing_ChestBeam.uc @@ -349,9 +349,9 @@ DefaultProperties // KFSM_FleshpoundKing_ChestBeam BeamDamageType=class'KFDT_FleshpoundKing_ChestBeam' BeamExtent=(X=15.0f, Y=15.0f, Z=15.0f) - MaxBeamLength=2500.0f //1300 + MaxBeamLength=3000.0f //2500.0f //1300 DamageInterval=0.1f - DamagePerTick=10 //15 //7 + DamagePerTick=12 //10 //15 //7 DamageMomentumImpulse=100.0f TimeUntilTargetChange=0.75f diff --git a/KFGameContent/Classes/KFSeasonalEventStats_Xmas2021.uc b/KFGameContent/Classes/KFSeasonalEventStats_Xmas2021.uc new file mode 100644 index 0000000..d090f8c --- /dev/null +++ b/KFGameContent/Classes/KFSeasonalEventStats_Xmas2021.uc @@ -0,0 +1,140 @@ +//============================================================================= +// KFSeasonalEventStats_Xmas2021 +//============================================================================= +// Tracks event-specific challenges/accomplishments for Xmas 2020 +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= +class KFSeasonalEventStats_Xmas2021 extends KFSeasonalEventStats; + +var private int WeaponRequiredPrice; +var transient private const int DecapitationsRequired, DoshRequired, WeaponsRequired, EndlessWaveRequired; + +private event Initialize(string MapName) +{ + local string CapsMapName; + CapsMapName = Caps(MapName); + + bObjectiveIsValidForMap[0] = 1; // Decapitate 1000 Zeds on any map or mode + bObjectiveIsValidForMap[1] = 0; // Complete the Weekly on Carillon Hamlet + bObjectiveIsValidForMap[2] = 0; // Earn 75,000 Dosh through kills, rewards and healing on Carillon Hamlet + bObjectiveIsValidForMap[3] = 0; // Use the trader to purchase a total of 20 weapons that cost 1500 Dosh or more on Carrion Hamlet. + bObjectiveIsValidForMap[4] = 0; // Complete wave 15 on Endless Hard or higher difficulty on Carillon Hamlet + + if (CapsMapName == "KF-CARILLONHAMLET") + { + bObjectiveIsValidForMap[1] = 1; + bObjectiveIsValidForMap[2] = 1; + bObjectiveIsValidForMap[3] = 1; + bObjectiveIsValidForMap[4] = 1; + } + + SetSeasonalEventStatsMax(DecapitationsRequired, 0, DoshRequired, WeaponsRequired, 0); +} + +private event GrantEventItems() +{ + if (Outer.IsEventObjectiveComplete(0) && + Outer.IsEventObjectiveComplete(1) && + Outer.IsEventObjectiveComplete(2) && + Outer.IsEventObjectiveComplete(3) && + Outer.IsEventObjectiveComplete(4)) + { + //@TODO: Update me + GrantEventItem(9177); + } +} + +simulated function OnZedKilledByHeadshot(class MonsterClass, int Difficulty, class DT) +{ + local int ObjIdx; + + // Hellmark Station decapitate 600 zeds + ObjIdx = 0; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= DecapitationsRequired) + { + FinishedObjective(SEI_Winter, ObjIdx); + } + } +} + +simulated event OnGameWon(class GameClass, int Difficulty, int GameLength, bool bCoOp) +{ + local int ObjIdx; + ObjIdx = 1; + + // Carillon weekly + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (GameClass == class'KFGameInfo_WeeklySurvival') + { + FinishedObjective(SEI_Winter, ObjIdx); + } + } +} + +simulated event OnGameEnd(class GameClass) +{ + local int ObjIdx; + local int TotalDoshEarned; + + // Earn 75,000 Dosh through kills, rewards and healing on Carillon Hamlet + ObjIdx = 2; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + TotalDoshEarned = Outer.MyKFPC.MatchStats.TotalDoshEarned + Outer.MyKFPC.MatchStats.GetDoshEarnedInWave(); + if(TotalDoshEarned > 0) + { + IncrementSeasonalEventStat(ObjIdx, TotalDoshEarned); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= DoshRequired) + { + FinishedObjective(SEI_Winter, ObjIdx); + } + } + } +} + +simulated event OnWeaponPurchased(class WeaponDef, int Price) +{ + local int ObjIdx; + + // Purchase weapons with a price >= 1500 + ObjIdx = 3; + if (bObjectiveIsValidForMap[ObjIdx] != 0 && Price >= WeaponRequiredPrice) + { + IncrementSeasonalEventStat(ObjIdx, 1); + if (Outer.GetSeasonalEventStatValue(ObjIdx) >= WeaponsRequired) + { + FinishedObjective(SEI_Winter, ObjIdx); + } + } +} + +simulated event OnWaveCompleted(class GameClass, int Difficulty, int WaveNum) +{ + local int ObjIdx; + + // Complete wave 15 on Endless Hard or higher difficulty on Carillon + ObjIdx = 4; + if (bObjectiveIsValidForMap[ObjIdx] != 0) + { + if (WaveNum >= EndlessWaveRequired && GameClass == class'KFGameInfo_Endless' && Difficulty >= `DIFFICULTY_HARD) + { + FinishedObjective(SEI_Winter, ObjIdx); + } + } +} + +defaultproperties +{ + DecapitationsRequired=1000 + DoshRequired=75000 + WeaponsRequired=20 + EndlessWaveRequired=15 + + WeaponRequiredPrice=1500 +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFSeqCond_IsWeeklyEvent.uc b/KFGameContent/Classes/KFSeqCond_IsWeeklyEvent.uc new file mode 100644 index 0000000..cf6ed0c --- /dev/null +++ b/KFGameContent/Classes/KFSeqCond_IsWeeklyEvent.uc @@ -0,0 +1,38 @@ +//============================================================================= +// KFSeqCond_IsWeeklyEvent +//============================================================================= +// Condition to check if we are in an specified weekly event +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= +class KFSeqCond_IsWeeklyEvent extends SequenceCondition; + +var() int WeeklyIndex; + +function Activated() +{ + local KFGameInfo KFGI; + KFGI = KFGameInfo(GetWorldInfo().Game); + + if (KFGI != none) + { + if (KFGI.MyKFGRI != none && KFGI.MyKFGRI.bIsWeeklyMode && class'KFGameEngine'.static.GetWeeklyEventIndexMod() == WeeklyIndex) + { + OutputLinks[0].bHasImpulse = true; + } + else + { + OutputLinks[1].bHasImpulse = true; + } + } +} + +defaultproperties +{ + ObjColor=(R=255,G=0,B=255,A=255) + ObjName="IsWeeklyEvent" + + OutputLinks(0)=(LinkDesc="True") + OutputLinks(1)=(LinkDesc="False") +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeap_AssaultRifle_Doshinegun.uc b/KFGameContent/Classes/KFWeap_AssaultRifle_Doshinegun.uc new file mode 100644 index 0000000..614132a --- /dev/null +++ b/KFGameContent/Classes/KFWeap_AssaultRifle_Doshinegun.uc @@ -0,0 +1,221 @@ +//============================================================================= +// KFWeap_AssaultRifle_Doshinegun +//============================================================================= +// Like if we were rich... +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFWeap_AssaultRifle_Doshinegun extends KFWeap_RifleBase; + +var int DoshCost; +var transient KFPlayerReplicationInfo KFPRI; + +simulated function Activate() +{ + local KFPawn KFP; + + super.Activate(); + + KFP = KFPawn(Instigator); + if (KFP != none) + { + KFPRI = KFPlayerReplicationInfo(KFP.PlayerReplicationInfo); + } +} + +simulated function bool HasAnyAmmo() +{ + return AmmoCount[0] > 0 || KFPRI.Score >= DoshCost; +} + +/** Returns true if weapon can potentially be reloaded */ +simulated function bool CanReload(optional byte FireModeNum) +{ + return KFPRI.Score >= DoshCost && AmmoCount[FireModeNum] < MagazineCapacity[FireModeNum]; +} + +/** Performs actual ammo reloading */ +simulated function PerformReload(optional byte FireModeNum) +{ + local int ReloadAmount; + local int AmmoType; + + AmmoType = GetAmmoType(FireModeNum); + + if ( bInfiniteSpareAmmo ) + { + AmmoCount[AmmoType] = MagazineCapacity[AmmoType]; + ReloadAmountLeft = 0; + return; + } + + if ( (Role == ROLE_Authority && !bAllowClientAmmoTracking) || (Instigator.IsLocallyControlled() && bAllowClientAmmoTracking) ) + { + ReloadAmount = Min(MagazineCapacity[0] - AmmoCount[0], KFPRI.Score / DoshCost); + AmmoCount[AmmoType] = Min(AmmoCount[AmmoType] + ReloadAmount, MagazineCapacity[AmmoType]); + KFPRI.AddDosh(-ReloadAmount * DoshCost); + } + + ReloadAmountLeft = 0; + ShotsHit = 0; +} + +function int AddAmmo(int Amount) +{ + return 0; +} + +simulated function bool CanBuyAmmo() +{ + return false; +} + +static simulated event bool UsesAmmo() +{ + return true; +} + +// Overriden to deactivate low ammo dialogue +simulated state Reloading +{ + simulated function EndState(Name NextStateName) + { + local int ActualReloadAmount; + ClearZedTimeResist(); + ClearTimer(nameof(ReloadStatusTimer)); + ClearTimer(nameof(ReloadAmmoTimer)); + ClearPendingFire(RELOAD_FIREMODE); + + if ( bAllowClientAmmoTracking && Role < ROLE_Authority ) + { + // Get how much total ammo was reloaded on the client side over the entire course of the reload. + ActualReloadAmount = InitialReloadAmount - ReloadAmountLeft; + // Sync spare ammo counts using initial spare ammo, and how much ammo has been reloaded since reload began. + ServerSyncReload(InitialReloadSpareAmmo - ActualReloadAmount); + } + + CheckBoltLockPostReload(); + NotifyEndState(); + + CurrentFireMode = DEFAULT_FIREMODE; + + ReloadStatus = RS_None; + } +} + +defaultproperties +{ + // FOV + MeshFOV=65 + MeshIronSightFOV=45 //52 + PlayerIronSightFOV=70 + + // Depth of field + DOF_FG_FocalRadius=150 //85 + DOF_FG_MaxNearBlurSize=1 //2.5 + + // Content + PackageKey="Doshinegun" + FirstPersonMeshName="WEP_1P_Doshinegun_MESH.Wep_1stP_Doshinegun_Rig" + FirstPersonAnimSetNames(0)="WEP_1P_Doshinegun_ANIM.Wep_1st_Doshinegun_Anim" + PickupMeshName="WEP_3P_Doshinegun_MESH.Wep_Doshinegun_Pickup" + AttachmentArchetypeName="WEP_Doshinegun_ARCH.Wep_Doshinegun_3P" + MuzzleFlashTemplateName="WEP_Doshinegun_ARCH.Wep_Doshinegun_MuzzleFlash" + + // Zooming/Position + PlayerViewOffset=(X=1.0,Y=8.5,Z=-3) + IronSightPosition=(X=5.0,Y=-0.1,Z=-1.5) + + // Ammo + MagazineCapacity[0]=20 + SpareAmmoCapacity[0]=0 + InitialSpareMags[0]=0 + AmmoPickupScale[0]=0.0 + bCanBeReloaded=true + bReloadFromMagazine=true + + // Recoil + maxRecoilPitch=250 //150 + minRecoilPitch=200 //115 + maxRecoilYaw=115 + minRecoilYaw=-115 + RecoilRate=0.085 + RecoilMaxYawLimit=500 + RecoilMinYawLimit=65035 + RecoilMaxPitchLimit=900 + RecoilMinPitchLimit=65035 + RecoilISMaxYawLimit=75 + RecoilISMinYawLimit=65460 + RecoilISMaxPitchLimit=375 + RecoilISMinPitchLimit=65460 + RecoilViewRotationScale=0.25 + IronSightMeshFOVCompensationScale=1.5 + HippedRecoilModifier=1.5 + + // Inventory / Grouping + InventorySize=4 //6 + GroupPriority=50 + WeaponSelectTexture=Texture2D'WEP_UI_Doshinegun_TEX.UI_Weapon_Select_Doshinegun' + //AssociatedPerkClasses(0)=class'KFPerk_Survivalist' + AssociatedPerkClasses(0)=none + + // DEFAULT_FIREMODE + FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletAuto' + FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring + WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile + WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Dosh' + InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Bludgeon_Doshinegun_Shot' + FireInterval(DEFAULT_FIREMODE)=+0.2 + Spread(DEFAULT_FIREMODE)=0.015 + InstantHitDamage(DEFAULT_FIREMODE)=55.0 //60.0 + FireOffset=(X=30,Y=4.5,Z=-5) + + // ALT_FIREMODE + FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_BulletSingle' + FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring + WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile + WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Dosh' + InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Bludgeon_Doshinegun_Shot' + FireInterval(ALTFIRE_FIREMODE)=+0.2 + InstantHitDamage(ALTFIRE_FIREMODE)=55.0 //60.0 + Spread(ALTFIRE_FIREMODE)=0.015 + + // BASH_FIREMODE + InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_Doshinegun' + InstantHitDamage(BASH_FIREMODE)=26 + + // Fire Effects + WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Shoot_Fire_3P_Loop', FirstPersonCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Shoot_Fire_1P_Loop') + WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Fire_1P') + WeaponFireLoopEndSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Shoot_Fire_3P_EndLoop', FirstPersonCue=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Shoot_Fire_1P_EndLoop') + + WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Dry_Fire' + WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_Doshinegun.Play_WEP_Doshinegun_Dry_Fire' + + // Advanced (High RPM) Fire Effects + bLoopingFireAnim(DEFAULT_FIREMODE)=true + bLoopingFireSnd(DEFAULT_FIREMODE)=true + SingleFireSoundIndex=ALTFIRE_FIREMODE + + // Attachments + bHasIronSights=true + bHasFlashlight=false + + // Weapon Upgrade stat boosts + //WeaponUpgrades[1]=(IncrementDamage=1.3f,IncrementWeight=1) + //WeaponUpgrades[2]=(IncrementDamage=1.65f,IncrementWeight=2) + //WeaponUpgrades[3]=(IncrementDamage=1.85f,IncrementWeight=3) + + WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.2f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1))) + WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.4f), (Stat=EWUS_Damage1, Scale=1.3f), (Stat=EWUS_Weight, Add=2))) + WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.6f), (Stat=EWUS_Damage1, Scale=1.45f), (Stat=EWUS_Weight, Add=3))) + + DoshCost = 25; + bUsesSecondaryAmmoAltHUD=true + bAllowClientAmmoTracking=false +} + + + diff --git a/KFGameContent/Classes/KFWeap_Blunt_MedicBat.uc b/KFGameContent/Classes/KFWeap_Blunt_MedicBat.uc index 03ac3e6..4f48058 100644 --- a/KFGameContent/Classes/KFWeap_Blunt_MedicBat.uc +++ b/KFGameContent/Classes/KFWeap_Blunt_MedicBat.uc @@ -734,7 +734,7 @@ defaultproperties DamageFalloffExponent=0.f DamageDelay=0.f MyDamageType=class'KFDT_Toxic_MedicBatGas' - HealingAmount=20 //30 + HealingAmount=15 //20 //30 // Damage Effects KnockDownStrength=0 diff --git a/KFGameContent/Classes/KFWeap_HRG_Boomy.uc b/KFGameContent/Classes/KFWeap_HRG_Boomy.uc index 2792ffc..f318b18 100644 --- a/KFGameContent/Classes/KFWeap_HRG_Boomy.uc +++ b/KFGameContent/Classes/KFWeap_HRG_Boomy.uc @@ -115,7 +115,7 @@ defaultproperties // Ammo MagazineCapacity[0]=24 SpareAmmoCapacity[0]=192 - InitialSpareMags[0]=1 + InitialSpareMags[0]=2 //1 bCanBeReloaded=true bReloadFromMagazine=true @@ -152,7 +152,7 @@ defaultproperties InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Boomy' FireInterval(DEFAULT_FIREMODE)=+0.1667 // 360 RPM Spread(DEFAULT_FIREMODE)=0.01 //0.025 - InstantHitDamage(DEFAULT_FIREMODE)=25.0 + InstantHitDamage(DEFAULT_FIREMODE)=30.0 //25.0 FireOffset=(X=30,Y=4.5,Z=-5) // ALT_FIREMODE @@ -162,7 +162,7 @@ defaultproperties WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_HRG_Boomy' InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Boomy' FireInterval(ALTFIRE_FIREMODE)=+0.1667 // 360 RPM - InstantHitDamage(ALTFIRE_FIREMODE)=25.0 + InstantHitDamage(ALTFIRE_FIREMODE)=30.0 //25.0 Spread(ALTFIRE_FIREMODE)=0.01 //0.025 // BASH_FIREMODE @@ -186,7 +186,7 @@ defaultproperties bHasIronSights=true bHasFlashlight=false - WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1))) - WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.3f), (Stat=EWUS_Damage1, Scale=1.3f), (Stat=EWUS_Weight, Add=2))) - WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.45f), (Stat=EWUS_Damage1, Scale=1.45f), (Stat=EWUS_Weight, Add=3))) + WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.2f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1))) + WeaponUpgrades[2]=(Stats=((Stat=EWUS_Damage0, Scale=1.4f), (Stat=EWUS_Damage1, Scale=1.3f), (Stat=EWUS_Weight, Add=2))) + WeaponUpgrades[3]=(Stats=((Stat=EWUS_Damage0, Scale=1.6f), (Stat=EWUS_Damage1, Scale=1.45f), (Stat=EWUS_Weight, Add=3))) } diff --git a/KFGameContent/Classes/KFWeap_HRG_Energy.uc b/KFGameContent/Classes/KFWeap_HRG_Energy.uc index 9aa49a1..bd3d3ff 100644 --- a/KFGameContent/Classes/KFWeap_HRG_Energy.uc +++ b/KFGameContent/Classes/KFWeap_HRG_Energy.uc @@ -435,7 +435,7 @@ defaultproperties // Ammo MagazineCapacity[0]=15 - SpareAmmoCapacity[0]=135 + SpareAmmoCapacity[0]=120 //135 InitialSpareMags[0]=2 bCanBeReloaded=true bReloadFromMagazine=true @@ -466,7 +466,7 @@ defaultproperties WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_HRG_Energy' FireInterval(DEFAULT_FIREMODE)=+0.175 //342 RPM PenetrationPower(DEFAULT_FIREMODE)=1.0 - InstantHitDamage(DEFAULT_FIREMODE)=90.0 //125.0 + InstantHitDamage(DEFAULT_FIREMODE)=80 //90.0 //125.0 InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Energy_Primary' Spread(DEFAULT_FIREMODE)=0.015 FireOffset=(X=20,Y=4.0,Z=-3) @@ -480,7 +480,7 @@ defaultproperties InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Energy_Secondary' InstantHitMomentum(ALTFIRE_FIREMODE)=1.0 PenetrationPower(ALTFIRE_FIREMODE)=3.0 - InstantHitDamage(ALTFIRE_FIREMODE)=300.0 //475.0 + InstantHitDamage(ALTFIRE_FIREMODE)=120.0 // 300.0 //475.0 PenetrationDamageReductionCurve(ALTFIRE_FIREMODE)=(Points=((InVal=0.f,OutVal=0.f),(InVal=1.f, OutVal=1.f))) AmmoCost(ALTFIRE_FIREMODE)=3 diff --git a/KFGameContent/Classes/KFWeap_HRG_Stunner.uc b/KFGameContent/Classes/KFWeap_HRG_Stunner.uc new file mode 100644 index 0000000..bb5f9a4 --- /dev/null +++ b/KFGameContent/Classes/KFWeap_HRG_Stunner.uc @@ -0,0 +1,183 @@ +//============================================================================= +// KFWeap_HRG_Stunner +//============================================================================= +// HRG Stunner Weapon Class +//============================================================================= +// Killing Floor 2 +// Copyright (C) 2021 Tripwire Interactive LLC +//============================================================================= + +class KFWeap_HRG_Stunner extends KFWeap_ShotgunBase; + +const SecondaryFireAnim = 'Shoot_Secondary'; +const SecondaryFireIronAnim = 'Shoot_Secondary_Iron'; + +/** How much recoil the altfire should do */ +var protected const float AltFireRecoilScale; + +simulated function ModifyRecoil( out float CurrentRecoilModifier ) +{ + if( CurrentFireMode == ALTFIRE_FIREMODE ) + { + CurrentRecoilModifier *= AltFireRecoilScale; + } + + super.ModifyRecoil( CurrentRecoilModifier ); +} + +simulated function StartFire(byte FireModeNum) +{ + if (FireModeNum == DEFAULT_FIREMODE && bUseAltFireMode) + { + if (AmmoCount[FireModeNum] < AmmoCost[ALTFIRE_FIREMODE] && SpareAmmoCount[FireModeNum] > 0) + { + BeginFire(RELOAD_FIREMODE); + return; + } + } + + super.StartFire(FireModeNum); +} + +simulated function AltFireMode() +{ + StartFire(ALTFIRE_FIREMODE); +} + +simulated function NotifyAltFireUsage() +{ + local KFPawn_Human KFPH; + + // Notify 3P to change material. + KFPH = KFPawn_Human(Instigator); + if (KFPH != none) + { + KFPH.SetUsingAltFireMode(bUseAltFireMode, true); + KFPH.bNetDirty = true; + } +} + +simulated function name GetWeaponFireAnim(byte FireModeNum) +{ + if (FireModeNum == ALTFIRE_FIREMODE) + { + return bUsingSights ? SecondaryFireIronAnim : SecondaryFireAnim; + } + return super.GetWeaponFireAnim(FireModeNum); +} + +defaultproperties +{ + // Inventory + InventorySize=6 + GroupPriority=100 + WeaponSelectTexture=Texture2D'wep_ui_hrg_stunner_tex.UI_Weapon_Select_HRG_Stunner' + + // Shooting Animations + FireSightedAnims[0]=Shoot_Iron + FireSightedAnims[1]=Shoot_Iron2 + FireSightedAnims[2]=Shoot_Iron3 + + // FOV + MeshFOV=86 + MeshIronSightFOV=52 + PlayerIronSightFOV=70 + + // Depth of field + DOF_FG_FocalRadius=85 + DOF_FG_MaxNearBlurSize=3.5 + + // Zooming/Position + PlayerViewOffset=(X=15.0,Y=8.5,Z=0.0) + IronSightPosition=(X=8,Y=0,Z=0) + + // Content + PackageKey="HRG_Stunner" + FirstPersonMeshName="Wep_1P_HRG_Stunner_MESH.Wep_1stP_HRG_Stunner_Rig" + FirstPersonAnimSetNames(0)="Wep_1P_HRG_Stunner_ANIM.Wep_1stP_HRG_Stunner_Anim" + PickupMeshName="WEP_3P_HRG_Stunner_MESH.Wep_HRG_Stunner_Pickup" + AttachmentArchetypeName="WEP_HRG_Stunner_ARCH.Wep_AA12_3P" + MuzzleFlashTemplateName="WEP_HRG_Stunner_ARCH.Wep_AA12_MuzzleFlash" + + // DEFAULT_FIREMODE + FireModeIconPaths(DEFAULT_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunAuto' + FiringStatesArray(DEFAULT_FIREMODE)=WeaponFiring + WeaponFireTypes(DEFAULT_FIREMODE)=EWFT_Projectile + WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Bullet_Pellet' + InstantHitDamage(DEFAULT_FIREMODE)=60.0 //65.0 + InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_HRG_Stunner' + PenetrationPower(DEFAULT_FIREMODE)=2.0 + FireInterval(DEFAULT_FIREMODE)=0.15 + Spread(DEFAULT_FIREMODE)=0.005 + FireOffset=(X=30,Y=5,Z=-4) + // Shotgun + NumPellets(DEFAULT_FIREMODE)=1 + + // ALT_FIREMODE + FireModeIconPaths(ALTFIRE_FIREMODE)=Texture2D'ui_firemodes_tex.UI_FireModeSelect_ShotgunSingle' + FiringStatesArray(ALTFIRE_FIREMODE)=WeaponSingleFiring + WeaponFireTypes(ALTFIRE_FIREMODE)=EWFT_Projectile + WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Bullet_HRG_Stunner_Alt' + InstantHitDamage(ALTFIRE_FIREMODE)=20.0 //50.0 + InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_HRG_Stunner_Alt' + PenetrationPower(ALTFIRE_FIREMODE)=0 + FireInterval(ALTFIRE_FIREMODE)=0.5 + Spread(ALTFIRE_FIREMODE)=0.025 + AmmoCost(ALTFIRE_FIREMODE)=5 //3 + + // Shotgun + NumPellets(ALTFIRE_FIREMODE)=1 + + // BASH_FIREMODE + InstantHitDamageTypes(BASH_FIREMODE)=class'KFDT_Bludgeon_HRG_Stunner' + InstantHitDamage(BASH_FIREMODE)=26 + + // Fire Effects + WeaponFireSnd(DEFAULT_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Fire_1P') + WeaponFireSnd(ALTFIRE_FIREMODE)=(DefaultCue=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Alt_Fire_3P', FirstPersonCue=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Alt_Fire_1P') + + WeaponDryFireSnd(DEFAULT_FIREMODE)=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Dry_Fire' + WeaponDryFireSnd(ALTFIRE_FIREMODE)=AkEvent'WW_WEP_HRG_Stunner.Play_WEP_HRG_Stunner_Dry_Fire' + + // Attachments + bHasIronSights=true + bHasFlashlight=false + + // Ammo + MagazineCapacity[0]=25 + SpareAmmoCapacity[0]=225 //250 + InitialSpareMags[0]=1 + bCanBeReloaded=true + bReloadFromMagazine=true + bHasFireLastAnims=false + + // Recoil + maxRecoilPitch=150 + minRecoilPitch=125 + maxRecoilYaw=75 + minRecoilYaw=-75 + RecoilRate=0.075 + RecoilBlendOutRatio=0.25 + RecoilMaxYawLimit=500 + RecoilMinYawLimit=65035 + RecoilMaxPitchLimit=900 + RecoilMinPitchLimit=64785 + RecoilISMaxYawLimit=75 + RecoilISMinYawLimit=65460 + RecoilISMaxPitchLimit=375 + RecoilISMinPitchLimit=65460 + RecoilViewRotationScale=0.7 + FallingRecoilModifier=1.5 + HippedRecoilModifier=1.75 + + AssociatedPerkClasses(0)=class'KFPerk_SWAT' + + WeaponFireWaveForm=ForceFeedbackWaveform'FX_ForceFeedback_ARCH.Gunfire.Heavy_Recoil' + + // Weapon Upgrade stat boosts + //WeaponUpgrades[1]=(IncrementDamage=1.15f,IncrementWeight=1) + + WeaponUpgrades[1]=(Stats=((Stat=EWUS_Damage0, Scale=1.15f), (Stat=EWUS_Damage1, Scale=1.15f), (Stat=EWUS_Weight, Add=1))) + + AltFireRecoilScale=3.0f //2.0f +} \ No newline at end of file diff --git a/KFGameContent/Classes/KFWeap_Pistol_Bladed.uc b/KFGameContent/Classes/KFWeap_Pistol_Bladed.uc index f89d08e..f620a14 100644 --- a/KFGameContent/Classes/KFWeap_Pistol_Bladed.uc +++ b/KFGameContent/Classes/KFWeap_Pistol_Bladed.uc @@ -71,7 +71,7 @@ simulated function StartFire(byte FireModeNum) } } - super.StartFire(FireModeNum); + super(KFWeapon).StartFire(FireModeNum); } /********************************************************************************************* @@ -94,6 +94,13 @@ simulated function ProcessInstantHitEx(byte FiringMode, ImpactInfo Impact, optio 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); +} + defaultproperties { // MeleeBase @@ -109,7 +116,7 @@ defaultproperties // Zooming/Position PlayerViewOffset=(X=-15,Y=12,Z=-6) - IronSightPosition=(X=0,Y=0,Z=1.0) //(X=-3,Y=-0.38,Z=-0.2) + IronSightPosition=(X=0,Y=0.05,Z=-1.2) //(X=0,Y=0,Z=1.0) // Content PackageKey="BladedPistol" @@ -121,7 +128,7 @@ defaultproperties // Ammo MagazineCapacity[0]=6 - SpareAmmoCapacity[0]=72 //96 + SpareAmmoCapacity[0]=66 //72 InitialSpareMags[0]=2 AmmoPickupScale[0]=1.0 //2.0 bCanBeReloaded=true @@ -206,9 +213,9 @@ defaultproperties // default MIC param names BlockEffectsSocketName=BlockEffect // Defensive - BlockDamageMitigation=0.60f - ParryDamageMitigationPercent=0.5 - ParryStrength=4 + BlockDamageMitigation=0.70f //0.60f + ParryDamageMitigationPercent=0.6 //0.5 + ParryStrength=3 //4 BlockHitAnimCooldownTime=0.5f BlockTypes.Add((DmgType=class'KFDT_Bludgeon')) BlockTypes.Add((DmgType=class'KFDT_Slashing')) diff --git a/KFGameContent/Classes/KFWeap_Pistol_DualBladed.uc b/KFGameContent/Classes/KFWeap_Pistol_DualBladed.uc index 24b2a27..479dd0a 100644 --- a/KFGameContent/Classes/KFWeap_Pistol_DualBladed.uc +++ b/KFGameContent/Classes/KFWeap_Pistol_DualBladed.uc @@ -543,6 +543,17 @@ simulated function ANIMNOTIFY_UnLockBolt() BuildEmptyMagNodeWeightList( EmptyMagBlendNode, BonesToLockOnEmpty); } +/** + This weapon only supports akimbo anims. + Overriding bUseAltFireMode that comes from gameplay options by the user + */ +simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp) +{ + super.PostInitAnimTree(SkelComp); + + bUseAltFireMode = false; +} + defaultproperties { // Content @@ -579,7 +590,7 @@ defaultproperties // Ammo MagazineCapacity[0]=12 - SpareAmmoCapacity[0]=72 //96 + SpareAmmoCapacity[0]=66 //72 //96 InitialSpareMags[0]=1 AmmoPickupScale[0]=0.5 //1.0 bCanBeReloaded=true diff --git a/KFGameContent/Classes/KFWeap_Shotgun_Nailgun.uc b/KFGameContent/Classes/KFWeap_Shotgun_Nailgun.uc index 753e3b6..2b72c62 100644 --- a/KFGameContent/Classes/KFWeap_Shotgun_Nailgun.uc +++ b/KFGameContent/Classes/KFWeap_Shotgun_Nailgun.uc @@ -136,7 +136,7 @@ defaultproperties WeaponProjectiles(DEFAULT_FIREMODE)=class'KFProj_Nail_Nailgun' InstantHitDamage(DEFAULT_FIREMODE)=35 InstantHitDamageTypes(DEFAULT_FIREMODE)=class'KFDT_Ballistic_NailShotgun' - Spread(DEFAULT_FIREMODE)=0.16 + Spread(DEFAULT_FIREMODE)=0.13 //0.16 PenetrationPower(DEFAULT_FIREMODE)=3.0 FireInterval(DEFAULT_FIREMODE)=0.3 // 200 RPM FireOffset=(X=30,Y=5,Z=-4) @@ -150,7 +150,7 @@ defaultproperties WeaponProjectiles(ALTFIRE_FIREMODE)=class'KFProj_Nail_Nailgun' InstantHitDamage(ALTFIRE_FIREMODE)=35 InstantHitDamageTypes(ALTFIRE_FIREMODE)=class'KFDT_Ballistic_NailShotgun' - Spread(ALTFIRE_FIREMODE)=0.02 + Spread(ALTFIRE_FIREMODE)=0.01 //0.02 PenetrationPower(ALTFIRE_FIREMODE)=3.0 FireInterval(ALTFIRE_FIREMODE)=0.2 // 300 RPM AltFireRecoilModifier=0.5 @@ -174,7 +174,7 @@ defaultproperties // Ammo MagazineCapacity[0]=42 - SpareAmmoCapacity[0]=336 + SpareAmmoCapacity[0]=378 //336 InitialSpareMags[0]=3 bCanBeReloaded=true bReloadFromMagazine=true