From 3716813a7b4b7e1c841d109389dda0cf827b5143 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 26 Nov 2024 02:10:50 +0700 Subject: [PATCH 01/11] Change cooldowns to only decrease on kills --- sources/NiceGameType.uc | 6 +++- sources/NiceReplicationInfo.uc | 2 +- sources/Perks/Abilities/NiceAbilityManager.uc | 31 ++++++++++++------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/sources/NiceGameType.uc b/sources/NiceGameType.uc index ca0aaa7..7d1c2a8 100644 --- a/sources/NiceGameType.uc +++ b/sources/NiceGameType.uc @@ -74,6 +74,7 @@ State MatchInProgress{ function ScoreKill(Controller Killer, Controller Other) { + local NicePlayerController niceKiller; local PlayerReplicationInfo OtherPRI; local float KillScore; local Controller C; @@ -198,7 +199,10 @@ function ScoreKill(Controller Killer, Controller Other) } /* End Marco's Kill Messages */ - + niceKiller = NicePlayerController(killer); + if (niceKiller != none && niceKiller.abilityManager != none) { + niceKiller.abilityManager.AddToAllCooldowns(-1); + } } function DramaticEvent(float BaseZedTimePossibility, optional float DesiredZedTimeDuration){ diff --git a/sources/NiceReplicationInfo.uc b/sources/NiceReplicationInfo.uc index 5c0c9b7..2267304 100644 --- a/sources/NiceReplicationInfo.uc +++ b/sources/NiceReplicationInfo.uc @@ -334,7 +334,7 @@ simulated function UpdateMeleeInvincibility nicePawn.TryExtendingInv(niceZed, false, headshotLevel > 0.0); // Handle melee-cases if(mainTarget && class(damageType) != none) - nicePawn.TryExtendingInv(niceZed, true, headshotLevel > 0.0); + nicePawn.TryExtendingInv(niceZed, true, headshotLevel > 0.0); nicePawn.ApplyWeaponStats(nicePawn.weapon); } simulated function UpdateArdour(bool isKill, NicePlayerController nicePlayer){ diff --git a/sources/Perks/Abilities/NiceAbilityManager.uc b/sources/Perks/Abilities/NiceAbilityManager.uc index 96058e2..ad1cff5 100644 --- a/sources/Perks/Abilities/NiceAbilityManager.uc +++ b/sources/Perks/Abilities/NiceAbilityManager.uc @@ -29,19 +29,19 @@ struct NiceAbilityDescription{ // Image to be used as an ability's icon var Texture icon; // Default cooldown duration - var float cooldownLength; + var int cooldownLength; // Can ability be canceled once activated? - var bool canBeCancelled; + var bool canBeCancelled; }; // Complete description of current status of an ability, // including it's complete description. struct NiceAbilityStatus{ // Complete description of ability in question - var NiceAbilityDescription description; + var NiceAbilityDescription description; // Current cooldown value - var float cooldown; + var int cooldown; // Current state of an ability - var EAbilityState myState; + var EAbilityState myState; }; var NiceAbilityStatus currentAbilities[5]; var int currentAbilitiesAmount; @@ -65,7 +65,7 @@ function AddAbility(NiceAbilityDescription description){ if(currentAbilities[i].description.ID ~= description.ID) return; newRecord.description = description; - newRecord.cooldown = 0.0; + newRecord.cooldown = 0; newRecord.myState = ASTATE_READY; currentAbilities[currentAbilitiesAmount] = newRecord; currentAbilitiesAmount += 1; @@ -147,7 +147,7 @@ function SetAbilityState(int abilityIndex, EAbilityState newState){ // Changes ability's cooldown by a given amount. // If this brings cooldown to zero or below - // resets current ability to a 'ready' (ASTATE_READY) state. -function AddToCooldown(int abilityIndex, float delta){ +function AddToCooldown(int abilityIndex, int delta){ if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return; if(currentAbilities[abilityIndex].myState != ASTATE_COOLDOWN) return; currentAbilities[abilityIndex].cooldown += delta; @@ -155,12 +155,21 @@ function AddToCooldown(int abilityIndex, float delta){ SetAbilityState(abilityIndex, ASTATE_READY); hackCounter ++; } -function Tick(float deltaTime){ + +function AddToAllCooldowns(int delta){ local int i; - if(Role != Role_AUTHORITY) return; - for(i = 0;i < currentAbilitiesAmount;i ++) - AddToCooldown(i, -deltaTime); + + for (i = 0; i < currentAbilitiesAmount; i += 1) { + if (currentAbilities[i].myState == ASTATE_COOLDOWN) { + currentAbilities[i].cooldown += delta; + if(currentAbilities[i].cooldown <= 0) { + SetAbilityState(i, ASTATE_READY); + } + } + } + hackCounter ++; } + defaultproperties { maxAbilitiesAmount=5 From a3f4baabc6af17e59f6bb816da7b5e67cdd8decd Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 26 Nov 2024 03:33:21 +0700 Subject: [PATCH 02/11] Add limit to the damage from quad damage skill --- sources/GUI/NiceInteraction.uc | 15 ++++++++++ sources/NiceHumanPawn.uc | 3 +- sources/Perks/Abilities/NiceAbilityManager.uc | 28 +++++++++--------- .../Enforcer/NiceEnforcerAbilitiesAdapter.uc | 18 +++++++++++- sources/Perks/Enforcer/NiceVetEnforcer.uc | 29 +++++++++++-------- .../Skills/NiceSkillEnforcerBruteA.uc | 2 ++ 6 files changed, 67 insertions(+), 28 deletions(-) diff --git a/sources/GUI/NiceInteraction.uc b/sources/GUI/NiceInteraction.uc index 103d2cd..2afc1e1 100644 --- a/sources/GUI/NiceInteraction.uc +++ b/sources/GUI/NiceInteraction.uc @@ -260,6 +260,21 @@ function PostRender(Canvas C) } } + //// Draw quad damage bar + if (nicePawn != none && nicePawn.quadDamageRemaining > 0.0) + { + C.SetDrawColor(255, 255, 255); + barTexture = redBar; + center = C.ClipX * 0.5; + y = C.ClipY * 0.45; + barWidth = C.ClipX * 0.2; + barWidth *= nicePawn.quadDamageRemaining / class'NiceSkillEnforcerBruteA'.default.maximumDamageAdded; + x = center - (barWidth / 2); + C.SetPos(x, y); + Log("DRAWING" @ x @ y @ barWidth); + C.DrawTile(barTexture, barWidth, 32, 0, 0, barTexture.MaterialUSize(), barTexture.MaterialVSize()); + }//native(466) final function DrawTile( material Mat, float XL, float YL, float U, float V, float UL, float VL ); + team = C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team; //// Draw health still in regen timer healthToGive = ScrnHumanPawn(C.ViewPort.Actor.Pawn).clientHealthToGive; diff --git a/sources/NiceHumanPawn.uc b/sources/NiceHumanPawn.uc index 448e554..9b500a6 100644 --- a/sources/NiceHumanPawn.uc +++ b/sources/NiceHumanPawn.uc @@ -46,10 +46,11 @@ struct InvincExtentions{ var array zedInvExtList; var int headshotStack; var float bruteTimer; +var float quadDamageRemaining; replication{ reliable if(Role == ROLE_Authority) headshotStack, hmgShieldLevel, forcedZedTimeCountDown, maniacTimeout, invincibilityTimer, safeMeleeMisses, ffScale, - currentCalibrationState, calibrationScore, gunslingerTimer; + currentCalibrationState, calibrationScore, gunslingerTimer, quadDamageRemaining; reliable if(Role == ROLE_Authority) ClientChangeWeapon; reliable if(Role < ROLE_AUTHORITY) diff --git a/sources/Perks/Abilities/NiceAbilityManager.uc b/sources/Perks/Abilities/NiceAbilityManager.uc index ad1cff5..4e96c95 100644 --- a/sources/Perks/Abilities/NiceAbilityManager.uc +++ b/sources/Perks/Abilities/NiceAbilityManager.uc @@ -120,28 +120,28 @@ function SetAbilityState(int abilityIndex, EAbilityState newState){ if(abilityIndex < 0 || abilityIndex >= currentAbilitiesAmount) return; currentState = currentAbilities[abilityIndex].myState; if(currentState == newState) - return; + return; if( currentState == ASTATE_ACTIVE && newState == ASTATE_READY - && !currentAbilities[abilityIndex].description.canBeCancelled) - return; + && !currentAbilities[abilityIndex].description.canBeCancelled) + return; currentAbilities[abilityIndex].myState = newState; if(newState == ASTATE_COOLDOWN){ - cooldown = currentAbilities[abilityIndex].description.cooldownLength; - events.static.CallModAbilityCooldown( - currentAbilities[abilityIndex].description.ID, - relatedPlayer, - cooldown - ); - currentAbilities[abilityIndex].cooldown = cooldown; + cooldown = currentAbilities[abilityIndex].description.cooldownLength; + events.static.CallModAbilityCooldown( + currentAbilities[abilityIndex].description.ID, + relatedPlayer, + cooldown + ); + currentAbilities[abilityIndex].cooldown = cooldown; } hackCounter ++; netUpdateTime = level.timeSeconds - 1; // Fire off events if(newState == ASTATE_ACTIVE){ - events.static.CallAbilityActivated( - currentAbilities[abilityIndex].description.ID, - relatedPlayer - ); + events.static.CallAbilityActivated( + currentAbilities[abilityIndex].description.ID, + relatedPlayer + ); } } // Changes ability's cooldown by a given amount. diff --git a/sources/Perks/Enforcer/NiceEnforcerAbilitiesAdapter.uc b/sources/Perks/Enforcer/NiceEnforcerAbilitiesAdapter.uc index 0f5116f..11946da 100644 --- a/sources/Perks/Enforcer/NiceEnforcerAbilitiesAdapter.uc +++ b/sources/Perks/Enforcer/NiceEnforcerAbilitiesAdapter.uc @@ -15,7 +15,6 @@ static function AbilityActivated( NicePlayerController relatedPlayer) { local NiceHumanPawn nicePawn; - local NiceMonster victim; if (relatedPlayer == none) return; nicePawn = NiceHumanPawn(relatedPlayer.pawn); @@ -37,6 +36,23 @@ static function AbilityActivated( { nicePawn.bruteTimer = class'NiceSkillEnforcerBruteA'.default.abilityDuration; + nicePawn.quadDamageRemaining = class'NiceSkillEnforcerBruteA'.default.maximumDamageAdded; + } +} + +static function ModAbilityCooldown( string abilityID, + NicePlayerController relatedPlayer, + out float cooldown) +{ + local NiceHumanPawn nicePawn; + + if (relatedPlayer == none) return; + nicePawn = NiceHumanPawn(relatedPlayer.pawn); + if (nicePawn == none) return; + + if (abilityID == "brute") + { + nicePawn.quadDamageRemaining = 0; } } diff --git a/sources/Perks/Enforcer/NiceVetEnforcer.uc b/sources/Perks/Enforcer/NiceVetEnforcer.uc index 76d120d..c1b8182 100644 --- a/sources/Perks/Enforcer/NiceVetEnforcer.uc +++ b/sources/Perks/Enforcer/NiceVetEnforcer.uc @@ -16,12 +16,15 @@ static function array GetProgressArray(byte ReqNum, optional out int Double // Other bonuses static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class DmgType) { - local float fDamage; + local int bruteAbilityIndex; + local float fDamage, addedDamage; local NicePlayerController nicePlayer; + local NiceHumanPawn nicePawn; local NiceMonster niceTarget; fDamage = float(InDamage); nicePlayer = NicePlayerController(KFPRI.Owner); + nicePawn = NiceHumanPawn(nicePlayer.pawn); niceTarget = NiceMonster(injured); if ( niceTarget != none && niceTarget.bFrozenZed @@ -31,9 +34,20 @@ static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, (1 + class'NiceSkillEnforcerFinisherRounds'.default.damageBonus); } if( nicePlayer != none && nicePlayer.abilityManager != none + && nicePawn != none && nicePawn.quadDamageRemaining > 0 && nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillEnforcerBruteA'.default.abilityID)) { - fDamage *= class'NiceSkillEnforcerBruteA'.default.damageMult; + addedDamage = fDamage * class'NiceSkillEnforcerBruteA'.default.damageMult - fDamage; + if (addedDamage >= nicePawn.quadDamageRemaining) { + addedDamage = nicePawn.quadDamageRemaining; + nicePawn.quadDamageRemaining = 0.0; + bruteAbilityIndex = nicePlayer.abilityManager.GetAbilityIndex(class'NiceSkillEnforcerBruteA'.default.abilityID); + nicePlayer.abilityManager.SetAbilityState(bruteAbilityIndex, ASTATE_COOLDOWN); + } + else { + nicePawn.quadDamageRemaining -= addedDamage; + } + fDamage += addedDamage; } return int(fDamage); } @@ -45,7 +59,7 @@ static function float GetPenetrationDamageMulti(KFPlayerReplicationInfo KFPRI, f return DefaultPenDamageReduction; if(HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillSupportStubbornness')) bonusReduction = class'NiceSkillSupportStubbornness'.default.penLossRed; - PenDamageInverse = (1.0 - FMax(0, DefaultPenDamageReduction)); + PenDamageInverse = (1.0 - FMax(0, DefaultPenDamageReduction)); return DefaultPenDamageReduction + PenDamageInverse * (0.6 + 0.4 * bonusReduction); // 60% better penetrations + bonus } @@ -64,15 +78,6 @@ static function class GetNadeType(KFPlayerReplicationInfo KFPRI){ return class'NiceCryoNade'; } -static function float AddExtraAmmoFor(KFPlayerReplicationInfo KFPRI, Class AmmoType){ - local float bonusNades; - // Default bonus - bonusNades = 2; - if(AmmoType == class'FragAmmo') - return 1.0 + 0.2 * bonusNades; - return 1.0; -} - static function int ReduceDamage(KFPlayerReplicationInfo KFPRI, KFPawn Injured, Pawn Instigator, int InDamage, class DmgType){ local float fDamage; fDamage = float(inDamage); diff --git a/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBruteA.uc b/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBruteA.uc index 8bf9399..e7a87df 100644 --- a/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBruteA.uc +++ b/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBruteA.uc @@ -5,6 +5,7 @@ var string abilityID; var float coolDown; var float abilityDuration; var float damageMult; +var float maximumDamageAdded; function static SkillSelected(NicePlayerController nicePlayer) { @@ -29,6 +30,7 @@ function static SkillDeSelected(NicePlayerController nicePlayer) defaultproperties { + maximumDamageAdded=10000 abilityID="brute" cooldown=60.000000 abilityDuration=5.0 From b3b107c8eca7ee47f3210db391f69cd56b1814d8 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 02:17:05 +0700 Subject: [PATCH 03/11] Buff boomstick --- sources/NiceGameType.uc | 6 ++++++ .../Playable/Shotguns/Boomstick/NiceBoomStickAltFire.uc | 8 ++++---- .../Playable/Shotguns/Boomstick/NiceBoomStickFire.uc | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/sources/NiceGameType.uc b/sources/NiceGameType.uc index 7d1c2a8..5eb9578 100644 --- a/sources/NiceGameType.uc +++ b/sources/NiceGameType.uc @@ -75,6 +75,7 @@ State MatchInProgress{ function ScoreKill(Controller Killer, Controller Other) { local NicePlayerController niceKiller; + local NiceHumanPawn niceKillerPawn; local PlayerReplicationInfo OtherPRI; local float KillScore; local Controller C; @@ -201,8 +202,13 @@ function ScoreKill(Controller Killer, Controller Other) /* End Marco's Kill Messages */ niceKiller = NicePlayerController(killer); if (niceKiller != none && niceKiller.abilityManager != none) { + niceKillerPawn = NiceHumanPawn(niceKiller.pawn); niceKiller.abilityManager.AddToAllCooldowns(-1); } + if ( niceKillerPawn != none && NiceBoomStick(niceKillerPawn.weapon) != none + && other != none && other.pawn != none && other.pawn.default.health >= 1000) { + niceKillerPawn.invincibilityTimer += 1.0; + } } function DramaticEvent(float BaseZedTimePossibility, optional float DesiredZedTimeDuration){ diff --git a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickAltFire.uc b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickAltFire.uc index 4365656..82bcb3c 100644 --- a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickAltFire.uc +++ b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickAltFire.uc @@ -1,13 +1,13 @@ class NiceBoomStickAltFire extends NiceBoomStickFire; // Overload to force last shot to have a different animation with reload // NICETODO: uncomment this -function name GetCorrectAnim(bool bLoop, bool bAimed){ +function name GetCorrectAnim(bool bLoop, bool bAimed) { if(currentContext.sourceWeapon != none && currentContext.sourceWeapon.MagAmmoRemainingClient > 0) - return super.GetCorrectAnim(bLoop, bAimed); + return super.GetCorrectAnim(bLoop, bAimed); if(bAimed) - return 'Fire_Last_Iron'; + return 'Fire_Last_Iron'; else - return 'Fire_Last'; + return 'Fire_Last'; return FireAnim; } defaultproperties diff --git a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc index 070012c..837c195 100644 --- a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc +++ b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc @@ -58,6 +58,6 @@ defaultproperties ShakeOffsetTime=3.500000 BotRefireRate=2.500000 aimerror=2.000000 - Spread=3000.000000 + Spread=2000.000000 FireAnimRate=1.25 } From e1769e8048e7f80884a7880af09e66a5d874ced5 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:04:37 +0700 Subject: [PATCH 04/11] Change enforcer's heavy rifles' balance via burst fire parameters This patch dramatically reduces recoil on all guns and lets XMV850 accumulate way more damage that previously possible. --- .../BaseWeaponClasses/Heavy/NiceHeavyFire.uc | 3 ++- sources/Weapons/NiceFire.uc | 23 ++++++++++++++----- .../Playable/Heavy/M249/NiceM249Fire.uc | 4 ++-- .../Playable/Heavy/RPK47/NiceRPK47Fire.uc | 4 ++-- .../Playable/Heavy/SA80LSW/NiceSA80LSWFire.uc | 4 ++-- .../Playable/Heavy/XMV/NiceXMV850Fire.uc | 6 ++--- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/sources/Weapons/BaseWeaponClasses/Heavy/NiceHeavyFire.uc b/sources/Weapons/BaseWeaponClasses/Heavy/NiceHeavyFire.uc index 9077bf8..59b48a3 100644 --- a/sources/Weapons/BaseWeaponClasses/Heavy/NiceHeavyFire.uc +++ b/sources/Weapons/BaseWeaponClasses/Heavy/NiceHeavyFire.uc @@ -2,5 +2,6 @@ class NiceHeavyFire extends NiceFire; defaultproperties { - maxBonusContLenght=3 + maxBonusContLenght = 3 + aimingSpreadReductionCoefficient = 0.0 } diff --git a/sources/Weapons/NiceFire.uc b/sources/Weapons/NiceFire.uc index 82812b9..969d8ec 100644 --- a/sources/Weapons/NiceFire.uc +++ b/sources/Weapons/NiceFire.uc @@ -20,6 +20,7 @@ var() bool bSemiMustBurst; var() int MaxBurstLength; var() int burstShotsMade; var bool bResetRecoil; // Set this flag to 'true' to disable recoil for the next shot; flag will be automatically reset to 'false' after that +var float aimingSpreadReductionCoefficient; var bool zoomOutOnShot; var bool bShouldBounce; var bool bCausePain; @@ -487,7 +488,7 @@ simulated function HandleRecoil(float Rec) KFW= KFWeapon(Weapon); if (KFW.bAimingRifle) { - Rec *= 0.5; + Rec *= aimingSpreadReductionCoefficient; } if (nicePawn.stationaryTime > 0.0 && class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillHeavyStablePosition')) { @@ -697,7 +698,8 @@ simulated function UpdateFireSpeed(){ ReloadAnimRate = default.ReloadAnimRate * fireSpeedMod; } // This function is called when next fire time needs to be updated -simulated function float UpdateNextFireTime(float fireTimeVar){ +simulated function float UpdateNextFireTime(float fireTimeVar) { + local float usedFireRate; local float burstSlowDown; local NiceHumanPawn nicePawn; local class niceVet; @@ -705,11 +707,19 @@ simulated function float UpdateNextFireTime(float fireTimeVar){ if(nicePawn != none) niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePawn.PlayerReplicationInfo); fireTimeVar = FMax(fireTimeVar, Level.TimeSeconds); + usedFireRate = fireRate; + if (maxBonusContLenght > 1) { + if (currentContLenght <= maxBonusContLenght) { + usedFireRate *= 0.8 + 0.2 * (maxBonusContLenght - currentContLenght); + } else { + usedFireRate *= 0.8; + } + } if(bFireOnRelease){ if(bIsFiring) - fireTimeVar += MaxHoldTime + FireRate; + fireTimeVar += MaxHoldTime + usedFireRate; else - fireTimeVar = Level.TimeSeconds + FireRate; + fireTimeVar = Level.TimeSeconds + usedFireRate; } else{ if(currentContext.bIsBursting && GetBurstLength() > 1){ @@ -720,10 +730,10 @@ simulated function float UpdateNextFireTime(float fireTimeVar){ burstSlowDown = 1.0; else burstSlowDown = 1.3; - fireTimeVar += FireRate * burstSlowDown; + fireTimeVar += usedFireRate * burstSlowDown; } else - fireTimeVar += FireRate; + fireTimeVar += usedFireRate; fireTimeVar = FMax(fireTimeVar, Level.TimeSeconds); } return fireTimeVar; @@ -745,4 +755,5 @@ defaultproperties spreadGainedPerShot=0 spreadLostPerSecond=0 RecoilVelocityScale = 0 + aimingSpreadReductionCoefficient = 0.5 } diff --git a/sources/Weapons/Playable/Heavy/M249/NiceM249Fire.uc b/sources/Weapons/Playable/Heavy/M249/NiceM249Fire.uc index f531707..536e2ad 100644 --- a/sources/Weapons/Playable/Heavy/M249/NiceM249Fire.uc +++ b/sources/Weapons/Playable/Heavy/M249/NiceM249Fire.uc @@ -4,8 +4,8 @@ defaultproperties ProjectileSpeed=48250.000000 FireAimedAnim="Fire" RecoilRate=0.040000 - maxVerticalRecoilAngle=550 - maxHorizontalRecoilAngle=225 + maxVerticalRecoilAngle=115 + maxHorizontalRecoilAngle=0 ShellEjectClass=Class'ROEffects.KFShellEjectAK' ShellEjectBoneName="Shell_eject" bAccuracyBonusForSemiAuto=True diff --git a/sources/Weapons/Playable/Heavy/RPK47/NiceRPK47Fire.uc b/sources/Weapons/Playable/Heavy/RPK47/NiceRPK47Fire.uc index 79b5528..0bbd5bb 100644 --- a/sources/Weapons/Playable/Heavy/RPK47/NiceRPK47Fire.uc +++ b/sources/Weapons/Playable/Heavy/RPK47/NiceRPK47Fire.uc @@ -5,8 +5,8 @@ defaultproperties contBonus=1.400000 FireAimedAnim="Fire_Iron" RecoilRate=0.050000 - maxVerticalRecoilAngle=400 - maxHorizontalRecoilAngle=200 + maxVerticalRecoilAngle=100 + maxHorizontalRecoilAngle=0 ShellEjectClass=Class'ROEffects.KFShellEjectAK' ShellEjectBoneName="Shell_eject" bAccuracyBonusForSemiAuto=True diff --git a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWFire.uc b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWFire.uc index 5108bae..033030e 100644 --- a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWFire.uc +++ b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWFire.uc @@ -4,8 +4,8 @@ defaultproperties ProjectileSpeed=46500.000000 FireAimedAnim="Iron_Idle" RecoilRate=0.050000 - maxVerticalRecoilAngle=300 - maxHorizontalRecoilAngle=150 + maxVerticalRecoilAngle=75 + maxHorizontalRecoilAngle=0 ShellEjectClass=Class'ROEffects.KFShellEjectBullpup' ShellEjectBoneName="Shell_eject" bAccuracyBonusForSemiAuto=True diff --git a/sources/Weapons/Playable/Heavy/XMV/NiceXMV850Fire.uc b/sources/Weapons/Playable/Heavy/XMV/NiceXMV850Fire.uc index d266c98..1042ce3 100644 --- a/sources/Weapons/Playable/Heavy/XMV/NiceXMV850Fire.uc +++ b/sources/Weapons/Playable/Heavy/XMV/NiceXMV850Fire.uc @@ -12,12 +12,12 @@ simulated function HandleRecoil(float Rec) defaultproperties { ProjectileSpeed=42650.000000 - maxBonusContLenght=5 + maxBonusContLenght=10 contBonusReset=false FireAimedAnim="FireLoop" RecoilRate=0.040000 - maxVerticalRecoilAngle=450 - maxHorizontalRecoilAngle=225 + maxVerticalRecoilAngle=25 + maxHorizontalRecoilAngle=0 ShellEjectClass=Class'ROEffects.KFShellEjectSCAR' ShellEjectBoneName="ejector" FireSoundRef="HMG_S.XMV.XMV-Fire-1" From d44a1a3555edaa2c5b2981261747b08cd0868f5c Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:11:30 +0700 Subject: [PATCH 05/11] Change SA80LSW's magazine size to 60 --- sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSW.uc | 2 +- sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmo.uc | 2 +- .../Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmoPickup.uc | 2 +- sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWPickup.uc | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSW.uc b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSW.uc index a74b185..99f9056 100644 --- a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSW.uc +++ b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSW.uc @@ -17,7 +17,7 @@ defaultproperties MagazineBone="clip" bHasScope=True ZoomedDisplayFOVHigh=50.000000 - MagCapacity=30 + MagCapacity=60 ReloadRate=3.500000 ReloadAnim="Reload" ReloadAnimRate=1.000000 diff --git a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmo.uc b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmo.uc index f6abd5d..0fc562c 100644 --- a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmo.uc +++ b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmo.uc @@ -2,7 +2,7 @@ class NiceSA80LSWAmmo extends NiceAmmo; defaultproperties { WeaponPickupClass=class'NiceSA80LSWPickup' - AmmoPickupAmount=30 + AmmoPickupAmount=60 MaxAmmo=360 InitialAmount=90 PickupClass=class'NiceSA80LSWAmmoPickup' diff --git a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmoPickup.uc b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmoPickup.uc index 6c6ea5b..058a8e1 100644 --- a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmoPickup.uc +++ b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWAmmoPickup.uc @@ -1,7 +1,7 @@ class NiceSA80LSWAmmoPickup extends NiceAmmoPickup; defaultproperties { - AmmoAmount=30 + AmmoAmount=60 InventoryType=class'NiceSA80LSWAmmo' PickupMessage="5.56x45" StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo' diff --git a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWPickup.uc b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWPickup.uc index f57be35..0083a16 100644 --- a/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWPickup.uc +++ b/sources/Weapons/Playable/Heavy/SA80LSW/NiceSA80LSWPickup.uc @@ -3,8 +3,8 @@ defaultproperties { cost=200 Weight=5.000000 - AmmoCost=5 - BuyClipSize=30 + AmmoCost=10 + BuyClipSize=60 PowerValue=41 SpeedValue=60 RangeValue=60 From d9dce6a29d8bd4b4be25db565d9196429721d2e3 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:15:36 +0700 Subject: [PATCH 06/11] Change Enforcer's Bombard's description --- sources/Perks/Enforcer/Skills/NiceSkillEnforcerBombard.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBombard.uc b/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBombard.uc index e38133a..8bdedfa 100644 --- a/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBombard.uc +++ b/sources/Perks/Enforcer/Skills/NiceSkillEnforcerBombard.uc @@ -7,5 +7,5 @@ defaultproperties stunMult=3.000000 spreadMult=0.500000 SkillName="Bombard" - SkillEffects="Your perked weapons are 3 times as good at stunning." + SkillEffects="Your perked weapons are 3 times as good at stunning and have omly half as much spread." } From 64e40d58c96ffced33e1cb4d7c285f56f99e6ac1 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:28:32 +0700 Subject: [PATCH 07/11] Buff M41A's stun capabilities --- sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc | 2 ++ .../Weapons/Playable/Heavy/M41A/NiceDamTypeM41AAssaultRifle.uc | 2 ++ sources/Zeds/NiceMonster.uc | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc b/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc index 835503b..2afb911 100644 --- a/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc +++ b/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc @@ -14,6 +14,7 @@ var float prReqPrecise; // How precise must head-shot be var float lockonTime; var float flinchMultiplier; // How effective is weapon for flinching zeds var float stunMultiplier; // How effective is weapon for stunning zeds +var float stunLengthMultiplier; // For how long is weapon going to stun zeds var float heatPart; // How much of this damage should be a heat component? var float freezePower; // How good is weapon at freezing? var float bodyDestructionMult; // How much more damage do to body on a head-shot? @@ -84,6 +85,7 @@ defaultproperties prReqPrecise=0.750000 flinchMultiplier=1.000000 stunMultiplier=1.000000 + stunLengthMultiplier=1.000000 bodyDestructionMult=1.000000 headSizeModifier=1.000000 BigZedPenDmgReduction=0.500000 diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceDamTypeM41AAssaultRifle.uc b/sources/Weapons/Playable/Heavy/M41A/NiceDamTypeM41AAssaultRifle.uc index d7f796b..ea086e8 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceDamTypeM41AAssaultRifle.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceDamTypeM41AAssaultRifle.uc @@ -10,4 +10,6 @@ defaultproperties KDeathVel=1400.000000 KDeathUpKick=150.000000 VehicleDamageScaling=0.700000 + stunMultiplier=3.0 + stunLengthMultiplier=2.0 } diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 46b700a..7d902f1 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -1286,8 +1286,9 @@ function float GetstunDurationMult( Pawn instigatedBy, if(KFPRI == none) return stunDurationMultiplier; niceVet = class(KFPRI.ClientVeteranSkill); if(niceVet == none) return stunDurationMultiplier; + if(damageType == none) return stunDurationMultiplier; // Perk's bonuses out - return stunDurationMultiplier * + return stunDurationMultiplier * damageType.default.stunLengthMultiplier * niceVet.static.stunDurationMult( KFPRI, self, KFPawn(instigatedBy), damageType); } From ff720a6b7ebeb364cd78aaff26316a04cf512210 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:39:00 +0700 Subject: [PATCH 08/11] Nerf SPAS12 Alt fire now consists of 8 pellets instead of 12 --- sources/Weapons/Playable/Shotguns/Spas/NiceSpasAltFire.uc | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/Weapons/Playable/Shotguns/Spas/NiceSpasAltFire.uc b/sources/Weapons/Playable/Shotguns/Spas/NiceSpasAltFire.uc index 8b97ecb..a5af9ef 100644 --- a/sources/Weapons/Playable/Shotguns/Spas/NiceSpasAltFire.uc +++ b/sources/Weapons/Playable/Shotguns/Spas/NiceSpasAltFire.uc @@ -1,6 +1,7 @@ class NiceSpasAltFire extends NiceSpasFire; defaultproperties { + ProjPerFire=8 maxVerticalRecoilAngle=300 maxHorizontalRecoilAngle=180 FireAnimRate=0.650000 From f54f0d40db1713ac150920b39c9adb35194277d4 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 03:58:26 +0700 Subject: [PATCH 09/11] Change Enforcer's finisher rounds skill to safeguard skill --- sources/NiceHumanPawn.uc | 8 +++++++- sources/Perks/Enforcer/NiceVetEnforcer.uc | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/sources/NiceHumanPawn.uc b/sources/NiceHumanPawn.uc index 9b500a6..58a48f7 100644 --- a/sources/NiceHumanPawn.uc +++ b/sources/NiceHumanPawn.uc @@ -737,6 +737,7 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, local float healPotency; local bool bOldArmorStops; local float adrResistance; + local float oldHealthToGive; local NicePlayerController nicePlayer; ApplyWeaponStats(Weapon); if(invincibilityTimer > 0) @@ -767,7 +768,12 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, damageType.default.bArmorStops = true; } lastExplosionDistance = 0.0; // hack, but scrn fucks with usotherwise + oldHealthToGive = healthToGive; // remember this to restore this value, in case we are using safeguard skill super.TakeDamage(Damage, InstigatedBy, hitLocation, Momentum, damageType, HitIndex); + if (class'NiceVeterancyTypes'.static.HasSkill(nicePlayer, class'NiceSkillHeavySafeguard')) { + healthToGive = oldHealthToGive; + clientHealthToGive = healthToGive; + } // Commando's zed time if( forcedZedTimeCountDown <= 0.0 && health < class'NiceSkillCommandoCriticalFocus'.default.healthBoundary && KFGameType(Level.Game) != none @@ -790,7 +796,7 @@ simulated function TakeDamage(int Damage, Pawn InstigatedBy, Vector Hitlocation, if(ShieldStrength < 0) ShieldStrength = 0; health += HealAmount * 0.5; - TakeHealing(self, HealAmount * 0.5, HealPotency); + TakeHealing(self, HealAmount * 0.5 + 1, HealPotency); } if(ShieldStrength <= 0) getFreeJacket(); diff --git a/sources/Perks/Enforcer/NiceVetEnforcer.uc b/sources/Perks/Enforcer/NiceVetEnforcer.uc index c1b8182..141af22 100644 --- a/sources/Perks/Enforcer/NiceVetEnforcer.uc +++ b/sources/Perks/Enforcer/NiceVetEnforcer.uc @@ -185,7 +185,7 @@ defaultproperties SkillGroupA(4)=class'NiceSkillEnforcerZEDBarrage' SkillGroupB(0)=class'NiceSkillEnforcerUnkillable' SkillGroupB(1)=class'NiceSkillEnforcerMultitasker' - SkillGroupB(2)=class'NiceSkillEnforcerFinisherRounds' + SkillGroupB(2)=class'NiceSkillHeavySafeguard' SkillGroupB(3)=class'NiceSkillEnforcerBruteA' SkillGroupB(4)=class'NiceSkillEnforcerZEDIceGiant' progressArray0(0)=100 From 430debb99e92ec2f24e40b3baac5189194d30d48 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 04:03:56 +0700 Subject: [PATCH 10/11] Buff explosive damage by 50% against frozen targets --- sources/Zeds/NiceMonster.uc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 7d902f1..64b37f5 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -825,13 +825,16 @@ function int ModBodyDamage( out int damage, local NicePlayerController nicePlayer; painDamage = damage; bIsHeadShot = (headshotLevel > 0.0); - if(instigatedBy != none) + if (instigatedBy != none) nicePlayer = NicePlayerController(instigatedBy.Controller); + if (bFrozenZed && damageType != none && damageType.default.bIsExplosive) { + damage *= 1.5; + } // On damaging critical spot (so far only head) - do body destruction - if(bIsHeadShot && damageType != none) + if (bIsHeadShot && damageType != none) damage *= damageType.default.bodyDestructionMult; // Skill bonuses - if(nicePlayer == none) + if (nicePlayer == none) return painDamage; bHasMessy = class'NiceVeterancyTypes'.static. someoneHasSkill(nicePlayer, class'NiceSkillSharpshooterDieAlready'); From 0333cfc171c2f81f720df00011c8f8879a3ce48d Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 27 Nov 2024 23:01:43 +0700 Subject: [PATCH 11/11] Add first draft of new syringe --- .../BaseWeaponClasses/Melee/NiceMeleeFire.uc | 30 +-- sources/Weapons/Playable/Tools/NiceSyringe.uc | 108 +++++++++ .../Playable/Tools/NiceSyringeAltFire.uc | 90 ++++++++ .../Weapons/Playable/Tools/NiceSyringeAmmo.uc | 12 + .../Playable/Tools/NiceSyringeAmmoPickup.uc | 8 + .../Weapons/Playable/Tools/NiceSyringeFire.uc | 208 ++++++++++++++++++ .../Playable/Tools/NiceSyringePickup.uc | 19 ++ 7 files changed, 460 insertions(+), 15 deletions(-) create mode 100644 sources/Weapons/Playable/Tools/NiceSyringe.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringeAltFire.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringeAmmo.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringeAmmoPickup.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringeFire.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringePickup.uc diff --git a/sources/Weapons/BaseWeaponClasses/Melee/NiceMeleeFire.uc b/sources/Weapons/BaseWeaponClasses/Melee/NiceMeleeFire.uc index 23195ed..f4cfd8c 100644 --- a/sources/Weapons/BaseWeaponClasses/Melee/NiceMeleeFire.uc +++ b/sources/Weapons/BaseWeaponClasses/Melee/NiceMeleeFire.uc @@ -272,19 +272,19 @@ simulated function HandleRecoil(float Rec){} defaultproperties { - weaponRange=70.000000 - damageDelay=0.300000 - ImpactShakeRotMag=(X=50.000000,Y=50.000000,Z=50.000000) - ImpactShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000) - ImpactShakeRotTime=2.000000 - ImpactShakeOffsetMag=(X=10.000000,Y=10.000000,Z=10.000000) - ImpactShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000) - ImpactShakeOffsetTime=2.000000 - MeleeHitVolume=1.000000 - HitEffectClass=Class'KFMod.KFMeleeHitEffect' - WideDamageMinHitAngle=1.000000 - bFiringDoesntAffectMovement=True - FireEndAnim= - FireForce="ShockRifleFire" - aimerror=100.000000 + weaponRange=70.000000 + damageDelay=0.300000 + ImpactShakeRotMag=(X=50.000000,Y=50.000000,Z=50.000000) + ImpactShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000) + ImpactShakeRotTime=2.000000 + ImpactShakeOffsetMag=(X=10.000000,Y=10.000000,Z=10.000000) + ImpactShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000) + ImpactShakeOffsetTime=2.000000 + MeleeHitVolume=1.000000 + HitEffectClass=Class'KFMod.KFMeleeHitEffect' + WideDamageMinHitAngle=1.000000 + bFiringDoesntAffectMovement=True + FireEndAnim= + FireForce="ShockRifleFire" + aimerror=100.000000 } diff --git a/sources/Weapons/Playable/Tools/NiceSyringe.uc b/sources/Weapons/Playable/Tools/NiceSyringe.uc new file mode 100644 index 0000000..56ac0d6 --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringe.uc @@ -0,0 +1,108 @@ +class NiceSyringe extends NiceMeleeWeapon; + +var () int HealBoostAmount; +var float RegenTimer; +var localized string SuccessfulHealMessage; + +replication +{ + reliable if( Role == ROLE_Authority ) + ClientSuccessfulHeal; + +} + +simulated function PostBeginPlay() +{ + // Weapon will handle FireMode instantiation + Super.PostBeginPlay(); + + if( Role == ROLE_Authority ) { + HealBoostAmount = default.HealBoostAmount; + } +} + +// The server lets the client know they successfully healed someone +simulated function ClientSuccessfulHeal(String HealedName) +{ + if( PlayerController(Instigator.Controller) != none ) + { + PlayerController(Instigator.controller).ClientMessage(SuccessfulHealMessage$HealedName, 'CriticalEvent'); + } +} + +simulated function Timer() +{ + Super.Timer(); + if( KFPawn(Instigator)!=None && KFPawn(Instigator).bIsQuickHealing>0 && ClientState==WS_ReadyToFire ) + { + if( KFPawn(Instigator).bIsQuickHealing==1 ) + { + if( !HackClientStartFire() ) + { + if( Instigator.Health>=Instigator.HealthMax || ChargeBar()<0.75 ) + KFPawn(Instigator).bIsQuickHealing = 2; // Was healed by someone else or some other error occurred. + SetTimer(0.2,False); + return; + } + KFPawn(Instigator).bIsQuickHealing = 2; + SetTimer(FireMode[1].FireRate+0.5,False); + } + else + { + Instigator.SwitchToLastWeapon(); + KFPawn(Instigator).bIsQuickHealing = 0; + } + } + else if( ClientState==WS_Hidden && KFPawn(Instigator)!=None ) + KFPawn(Instigator).bIsQuickHealing = 0; // Weapon was changed, ensure to reset this. +} + +simulated function bool HackClientStartFire() +{ + if( StartFire(1) ) + { + if( Role 1 && KFPlayerController(Instigator.Controller) != none && + KFSteamStatsAndAchievements(KFPlayerController(Instigator.Controller).SteamStatsAndAchievements) != none ) + { + KFSteamStatsAndAchievements(KFPlayerController(Instigator.Controller).SteamStatsAndAchievements).AddSelfHeal(); + } +} + +function Timer() +{ + local float HealSum, HealPotency; + local KFPlayerReplicationInfo KFPRI; + + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + + HealSum = NiceSyringe(Weapon).HealBoostAmount; + + HealPotency = 1.0; + + if ( KFPRI != none && KFPRI.ClientVeteranSkill != none ) + HealPotency = KFPRI.ClientVeteranSkill.Static.GetHealPotency(KFPRI); + HealSum *= HealPotency; + + Load = 1; + ReduceAmmoClient(); + if ( NiceHumanPawn(Instigator) != none ) + NiceHumanPawn(Instigator).TakeHealing(NiceHumanPawn(Instigator), HealSum, HealPotency, KFWeapon(Instigator.Weapon)); + else + KFPawn(Instigator).GiveHealth(HealSum, Instigator.HealthMax); +} + +function bool AllowFire() +{ + if (Instigator.Health >= Instigator.HealthMax) + return false; + + return Weapon.AmmoAmount(ThisModeNum) >= AmmoPerFire; +} + +event ModeDoFire() +{ + Load = 1; + Super.ModeDoFire(); +} + +function PlayFiring() +{ + if ( Weapon.Mesh != None ) + { + if ( FireCount > 0 ) + { + if ( Weapon.HasAnim(FireLoopAnim) ) + { + Weapon.PlayAnim(FireLoopAnim, FireLoopAnimRate, 0.0); + } + else + { + Weapon.PlayAnim(FireAnim, FireAnimRate, 0.0); + } + } + else + { + Weapon.PlayAnim(FireAnim, FireAnimRate, 0.0); + } + } + Weapon.PlayOwnedSound(FireSound,SLOT_Interact,TransientSoundVolume,,TransientSoundRadius,Default.FireAnimRate/FireAnimRate,false); + ClientPlayForceFeedback(FireForce); // jdf + + FireCount++; +} + +defaultproperties { + AmmoClass=class'NiceSyringeAmmo' + AmmoPerFire=1 + TweenTime=0.1 + TransientSoundVolume=1.8 + FireAnim="AltFire" + FireRate=3.60000 + bModeExclusive=true + InjectDelay=0.1 + HealeeRange=70.000000 +} diff --git a/sources/Weapons/Playable/Tools/NiceSyringeAmmo.uc b/sources/Weapons/Playable/Tools/NiceSyringeAmmo.uc new file mode 100644 index 0000000..dc7731f --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringeAmmo.uc @@ -0,0 +1,12 @@ +class NiceSyringeAmmo extends NiceAmmo; + +defaultproperties { + WeaponPickupClass=class'NiceSyringePickup' + AmmoPickupAmount=0 + MaxAmmo=4 + InitialAmount=1 + PickupClass=class'NiceSyringeAmmoPickup' + IconMaterial=Texture'KillingFloorHUD.Generic.HUD' + IconCoords=(X1=336,Y1=82,X2=382,Y2=125) + ItemName="Healing juice" +} diff --git a/sources/Weapons/Playable/Tools/NiceSyringeAmmoPickup.uc b/sources/Weapons/Playable/Tools/NiceSyringeAmmoPickup.uc new file mode 100644 index 0000000..600369e --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringeAmmoPickup.uc @@ -0,0 +1,8 @@ +class NiceSyringeAmmoPickup extends NiceAmmoPickup; + +defaultproperties { + AmmoAmount=1 + InventoryType=class'NiceSyringe' + PickupMessage="Healing juice" + StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo' +} diff --git a/sources/Weapons/Playable/Tools/NiceSyringeFire.uc b/sources/Weapons/Playable/Tools/NiceSyringeFire.uc new file mode 100644 index 0000000..287a10a --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringeFire.uc @@ -0,0 +1,208 @@ +class NiceSyringeFire extends NiceMeleeFire; + +var float LastHealAttempt; +var float HealAttemptDelay; +var float LastHealMessageTime; +var float HealMessageDelay; +var localized string NoHealTargetMessage; +var KFHumanPawn CachedHealee; +var transient float PendingHealTime; + +simulated function DestroyEffects() +{ + super.DestroyEffects(); + + if (CachedHealee != None) + CachedHealee = none; +} + +simulated function bool AllowFire() { + local KFHumanPawn Healtarget; + local string healeeName; + if (!super.AllowFire()) { + return false; + } + if (CanFindHealee()) { + if( CachedHealee.PlayerReplicationInfo != none && + CachedHealee.PlayerReplicationInfo.PlayerName != "") + { + HealeeName = CachedHealee.PlayerReplicationInfo.PlayerName; + } + else { + HealeeName = CachedHealee.MenuName; + } + NiceSyringe(Weapon).ClientSuccessfulHeal(HealeeName); + // Give the messages if we missed our heal, can't find a target, etc + if ( KFPlayerController(Instigator.Controller) != none ) + { + if ( LastHealAttempt + HealAttemptDelay < Level.TimeSeconds) + { + PlayerController(Instigator.controller).ClientMessage(NoHealTargetMessage, 'CriticalEvent'); + LastHealAttempt = Level.TimeSeconds; + } + + if ( Level.TimeSeconds - LastHealMessageTime > HealMessageDelay ) + { + // if there's a Player within 2 meters who needs healing, say that we're trying to heal them + foreach Instigator.VisibleCollidingActors(class'KFHumanPawn', Healtarget, 100) + { + if ( Healtarget != Instigator && Healtarget.Health < Healtarget.HealthMax ) + { + PlayerController(Instigator.Controller).Speech('AUTO', 5, ""); + LastHealMessageTime = Level.TimeSeconds; + + break; + } + } + } + } + return true; + } + return false; +} + +function Timer() +{ + local KFPlayerReplicationInfo PRI; + local int MedicReward; + local KFHumanPawn Healed; + local float HealSum, HealPotency; // for modifying based on perks + + PRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + Healed = CachedHealee; + HealPotency = 1.0; + CachedHealee = none; + if ( Healed != none && Healed.Health > 0 && Healed != Instigator ) + { + Load = 1; + ReduceAmmoClient(); + + if ( PRI != none && PRI.ClientVeteranSkill != none ) + HealPotency = PRI.ClientVeteranSkill.Static.GetHealPotency(PRI); + + HealSum = NiceSyringe(Weapon).HealBoostAmount; + + HealSum *= HealPotency; + MedicReward = HealSum; + + if ( (Healed.Health + Healed.healthToGive + MedicReward) > Healed.HealthMax ) + { + MedicReward = Healed.HealthMax - (Healed.Health + Healed.healthToGive); + if ( MedicReward < 0 ) + { + MedicReward = 0; + } + } + + if ( NiceHumanPawn(Healed) != none ) + NiceHumanPawn(Healed).TakeHealing(NiceHumanPawn(Instigator), HealSum, HealPotency, KFWeapon(Instigator.Weapon)); + else + Healed.GiveHealth(HealSum, Healed.HealthMax); + + // Tell them we're healing them + PlayerController(Instigator.Controller).Speech('AUTO', 5, ""); + LastHealMessageTime = Level.TimeSeconds; + + if ( PRI != None ) + { + if ( MedicReward > 0 && KFSteamStatsAndAchievements(PRI.SteamStatsAndAchievements) != none ) + { + KFSteamStatsAndAchievements(PRI.SteamStatsAndAchievements).AddDamageHealed(MedicReward); + } + + // Give the medic reward money as a percentage of how much of the person's health they healed + MedicReward = int((FMin(float(MedicReward),Healed.HealthMax)/Healed.HealthMax) * 60); // Increased to 80 in Balance Round 6, reduced to 60 in Round 7 + + if ( class'ScrnBalance'.default.Mut.bMedicRewardFromTeam && Healed.PlayerReplicationInfo != none && Healed.PlayerReplicationInfo.Team != none ) { + // give money from team wallet + if ( Healed.PlayerReplicationInfo.Team.Score >= MedicReward ) { + Healed.PlayerReplicationInfo.Team.Score -= MedicReward; + PRI.Score += MedicReward; + } + } + else + PRI.Score += MedicReward; + + if ( KFHumanPawn(Instigator) != none ) + { + KFHumanPawn(Instigator).AlphaAmount = 255; + } + } + } +} + +function KFHumanPawn GetHealee() +{ + local KFHumanPawn KFHP, BestKFHP; + local vector Dir; + local float TempDot, BestDot; + + Dir = vector(Instigator.GetViewRotation()); + + foreach Instigator.VisibleCollidingActors(class'KFHumanPawn', KFHP, 80.0) + { + if ( KFHP.Health < KFHP.HealthMax && KFHP.Health > 0 ) + { + TempDot = Dir dot (KFHP.Location - Instigator.Location); + if ( TempDot > 0.7 && TempDot > BestDot ) + { + BestKFHP = KFHP; + BestDot = TempDot; + } + } + } + + return BestKFHP; +} + +// Can we find someone to heal +function bool CanFindHealee() +{ + local KFHumanPawn Healtarget; + + Healtarget = GetHealee(); + CachedHealee = Healtarget; + + // Can't use syringe if we can't find a target + if ( Healtarget == none ) + { + if ( KFPlayerController(Instigator.Controller) != none ) + { + KFPlayerController(Instigator.Controller).CheckForHint(53); + } + + return false; + } + + // Can't use syringe if our target is already being healed to full health. + if ( (Healtarget.Health == Healtarget.Healthmax) || ((Healtarget.healthToGive + Healtarget.Health) >= Healtarget.Healthmax) ) + { + return false; + } + + return true; +} + +function float GetFireSpeed() +{ + if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none ) + { + return KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetFireSpeedMod(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), Weapon); + } + + return 1; +} + +defaultproperties { + AmmoClass=class'NiceSyringeAmmo' + ammoPerFire=1 + + FireAnims(0)="Fire" + FireRate=2.800000 + damageDelay=0.36 + + HealAttemptDelay=0.5 + HealMessageDelay=10.0 + NoHealTargetMessage="You must be near another player to heal them!" + bWaitForRelease=true +} diff --git a/sources/Weapons/Playable/Tools/NiceSyringePickup.uc b/sources/Weapons/Playable/Tools/NiceSyringePickup.uc new file mode 100644 index 0000000..424c4e4 --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringePickup.uc @@ -0,0 +1,19 @@ +class NiceSyringePickup extends NiceWeaponPickup; + +defaultproperties { + ItemName="Med-Syringe" + InventoryType=Class'NicePack.NiceSyringe' + Weight=0.000000 + cost=100 + AmmoCost=40 + BuyClipSize=1 + PickupMessage="You got the Med-Syringe." + PickupSound=Sound'Inf_Weapons_Foley.AmmoPickup' + PickupForce="AssaultRiflePickup" + StaticMesh=StaticMesh'KF_pickups_Trip.Syringe_pickup' + CollisionHeight=5.000000 + EquipmentCategoryID=0 + ItemShortName="Syringe" + AmmoItemName="Healing juice" + Description="Basic equipment, necessary for survival." +}