From d6662b1bc60e4c64a2a3793cdfccad75403afef1 Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Sat, 8 Apr 2023 22:21:30 +0400 Subject: [PATCH 01/46] Add NiceSyringe And make heal distance 80 -> 120 --- sources/NiceHumanPawn.uc | 22 +++++++++--------- sources/Weapons/Playable/Tools/NiceSyringe.uc | 8 +++++++ .../Playable/Tools/NiceSyringeAltFire.uc | 1 + .../Weapons/Playable/Tools/NiceSyringeFire.uc | 23 +++++++++++++++++++ .../Playable/Tools/NiceSyringePickup.uc | 6 +++++ 5 files changed, 49 insertions(+), 11 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/NiceSyringeFire.uc create mode 100644 sources/Weapons/Playable/Tools/NiceSyringePickup.uc diff --git a/sources/NiceHumanPawn.uc b/sources/NiceHumanPawn.uc index b6f1ece..18205da 100644 --- a/sources/NiceHumanPawn.uc +++ b/sources/NiceHumanPawn.uc @@ -69,7 +69,7 @@ function ReplaceRequiredEquipment() RequiredEquipment[0] = string(class'NiceMachete'); RequiredEquipment[1] = string(class'Nice9mmPlus'); RequiredEquipment[2] = string(class'ScrnFrag'); - RequiredEquipment[3] = string(class'ScrnSyringe'); + RequiredEquipment[3] = string(class'NiceSyringe'); RequiredEquipment[4] = string(class'KFMod.Welder'); } @@ -420,10 +420,10 @@ function ServerBuyWeapon(class WClass, float ItemWeight){ Price = WP.Default.Cost; if(KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none){ Price *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), WP); - if(class'ScrnBalance'.default.Mut.bBuyPerkedWeaponsOnly - && WP.default.CorrespondingPerkIndex != 7 + if(class'ScrnBalance'.default.Mut.bBuyPerkedWeaponsOnly + && WP.default.CorrespondingPerkIndex != 7 && WP.default.CorrespondingPerkIndex != KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.default.PerkIndex ) - return; + return; } SellValue = Price * 0.75; Price = int(Price); @@ -507,11 +507,11 @@ function bool AddInventory(inventory NewItem){ if(weap != none){ if(Dualies(weap) != none){ if((DualDeagle(weap) != none || Dual44Magnum(weap) != none || DualMK23Pistol(weap) != none) - && weap.InventoryGroup != 4 ) { + && weap.InventoryGroup != 4 ) { if(KFPRI != none && ClassIsChildOf(KFPRI.ClientVeteranSkill, class'ScrnVetGunslinger')) weap.InventoryGroup = 3; - else + else weap.InventoryGroup = 2; GroupChanged = true; } @@ -521,7 +521,7 @@ function bool AddInventory(inventory NewItem){ } weap.bIsTier3Weapon = true; } - if(GroupChanged) + if(GroupChanged) ClientSetInventoryGroup(NewItem.class, NewItem.InventoryGroup); if(super(SRHumanPawn).AddInventory(NewItem)){ if(weap != none && weap.bTorchEnabled) @@ -568,7 +568,7 @@ simulated function ThrowGrenade() super.ThrowGrenade(); return; } - + if(playerGrenade == none) playerGrenade = FindPlayerGrenade(); if(playerGrenade != none && playerGrenade.HasAmmo()){ @@ -650,7 +650,7 @@ simulated function ApplyWeaponStats(Weapon NewWeapon){ InventorySpeedModifier += default.GroundSpeed * (8 - weaponWeight) * 0.025; // ScrN Armor can slow down players (or even boost) -- PooSH InventorySpeedModifier -= default.GroundSpeed * GetCurrentVestClass().default.SpeedModifier; - } + } } simulated function ModifyVelocity(float DeltaTime, vector OldVelocity){ local NicePack NicePackMutator; @@ -699,7 +699,7 @@ simulated function ModifyVelocity(float DeltaTime, vector OldVelocity){ GroundSpeed = StoryInv.ForcedGroundSpeed; return; } - } + } if(bTraderSpeedBoost && !KFGameReplicationInfo(Level.GRI).bWaveInProgress) MovementMod *= TraderSpeedBoost; if(Health < HealthMax && medicAdrenaliteTime > 0){ @@ -846,7 +846,7 @@ function VeterancyChanged(){ nicePlayer.TriggerSelectEventOnPerkChange(nicePrevPerkClass, class(KFPRI.ClientVeteranSkill)); } - + super.VeterancyChanged(); } simulated function AltFire(optional float F){ diff --git a/sources/Weapons/Playable/Tools/NiceSyringe.uc b/sources/Weapons/Playable/Tools/NiceSyringe.uc new file mode 100644 index 0000000..48116c4 --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringe.uc @@ -0,0 +1,8 @@ +class NiceSyringe extends ScrnSyringe; + +defaultproperties { + ItemName="Nice Med-Syringe" + FireModeClass(0)=class'NiceSyringeFire' + FireModeClass(1)=class'NiceSyringeAltFire' + PickupClass=class'NiceSyringePickup' +} \ No newline at end of file diff --git a/sources/Weapons/Playable/Tools/NiceSyringeAltFire.uc b/sources/Weapons/Playable/Tools/NiceSyringeAltFire.uc new file mode 100644 index 0000000..c6b2f4a --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringeAltFire.uc @@ -0,0 +1 @@ +class NiceSyringeAltFire extends ScrnSyringeAltFire; \ No newline at end of file diff --git a/sources/Weapons/Playable/Tools/NiceSyringeFire.uc b/sources/Weapons/Playable/Tools/NiceSyringeFire.uc new file mode 100644 index 0000000..a632d12 --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringeFire.uc @@ -0,0 +1,23 @@ +class NiceSyringeFire extends ScrnSyringeFire; + +// default == 80 +const SEARCH_RADIUS=120.0; + +function KFHumanPawn GetHealee() { + local KFHumanPawn KFHP, BestKFHP; + local vector Dir; + local float TempDot, BestDot; + + Dir = vector(Instigator.GetViewRotation()); + + foreach Instigator.VisibleCollidingActors(class'KFHumanPawn', KFHP, SEARCH_RADIUS) { + 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; +} \ No newline at end of file diff --git a/sources/Weapons/Playable/Tools/NiceSyringePickup.uc b/sources/Weapons/Playable/Tools/NiceSyringePickup.uc new file mode 100644 index 0000000..a9673b6 --- /dev/null +++ b/sources/Weapons/Playable/Tools/NiceSyringePickup.uc @@ -0,0 +1,6 @@ +class NiceSyringePickup extends ScrnSyringePickup; + +defaultproperties { + ItemName="Nice Med-Syringe" + InventoryType=class'NiceSyringe' +} \ No newline at end of file From 2f3385583cd92a9f2d81846f35c73a4e65d167ab Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Sun, 9 Apr 2023 01:35:25 +0400 Subject: [PATCH 02/46] Apply new formatting for NiceBullet --- sources/Weapons/NiceBullet.uc | 1563 ++++++++++++++++++--------------- 1 file changed, 877 insertions(+), 686 deletions(-) diff --git a/sources/Weapons/NiceBullet.uc b/sources/Weapons/NiceBullet.uc index 6a60342..d402fd7 100644 --- a/sources/Weapons/NiceBullet.uc +++ b/sources/Weapons/NiceBullet.uc @@ -1,202 +1,209 @@ //====================================================================================================================== -// NicePack / NiceBullet +// NicePack / NiceBullet //====================================================================================================================== -// Bullet class that's supposed to take care of all damage-dealing projectile needs. -// Functionality: -// - Simulation of both linear and piece-wise motion -// - Collision detection that can be handled through the adapter class +// Bullet class that's supposed to take care of all damage-dealing projectile needs. +// Functionality: +// - Simulation of both linear and piece-wise motion +// - Collision detection that can be handled through the adapter class //====================================================================================================================== -// 'Nice pack' source -// Do whatever the fuck you want with it -// Author: dkanus -// E-mail: dkanus@gmail.com +// 'Nice pack' source +// Do whatever the fuck you want with it +// Author: dkanus +// E-mail: dkanus@gmail.com //====================================================================================================================== class NiceBullet extends Actor; -// Link to interaction with the server -var NiceReplicationInfo niceRI; -// Controller of our instigator -var NicePlayerController nicePlayer; -// Controller of local player -var NicePlayerController localPlayer; -// Link to our mutator -var NicePack niceMutator; +// Link to interaction with the server +var NiceReplicationInfo niceRI; +// Controller of our instigator +var NicePlayerController nicePlayer; +// Controller of local player +var NicePlayerController localPlayer; +// Link to our mutator +var NicePack niceMutator; //====================================================================================================================== -// Battle bullet characteristic -var float charOrigDamage; -var float charDamage; -var float decapMod; -var float incapMod; -var int charPenetrationCount; -var float charMomentumTransfer; +// Battle bullet characteristic +var float charOrigDamage; +var float charDamage; +var float decapMod; +var float incapMod; +var int charPenetrationCount; +var float charMomentumTransfer; var class charDamageType; var class charExplosionDamageType; -var float charExplosionDamage; -var float charExplosionRadius; -var float charExplosionExponent; -var float charExplosionMomentum; -var bool charIsDud; -var float charFuseTime; -var bool charExplodeOnFuse; -var bool charExplodeOnPawnHit; -var bool charExplodeOnWallHit; -var bool charAffectedByScream; -var float charMinExplosionDist; -var bool charWasHipFired; -var bool charCausePain; -var bool charIsSticky; -var float charContiniousBonus; -var bool bAlreadyHitZed; -var NiceWeapon sourceWeapon; -var NiceMonster lockonZed; -var float lockonTime; -var float bounceHeadMod; -var int insideBouncesLeft; -var bool bGrazing; +var float charExplosionDamage; +var float charExplosionRadius; +var float charExplosionExponent; +var float charExplosionMomentum; +var bool charIsDud; +var float charFuseTime; +var bool charExplodeOnFuse; +var bool charExplodeOnPawnHit; +var bool charExplodeOnWallHit; +var bool charAffectedByScream; +var float charMinExplosionDist; +var bool charWasHipFired; +var bool charCausePain; +var bool charIsSticky; +var float charContiniousBonus; +var bool bAlreadyHitZed; +var NiceWeapon sourceWeapon; +var NiceMonster lockonZed; +var float lockonTime; +var float bounceHeadMod; +var int insideBouncesLeft; +var bool bGrazing; //====================================================================================================================== -// Sticky projectile-related variables -var bool bStuck, bUseBone, bStuckToHead; -var name stuckBone; -var int stuckID; -// Data about explosive characteristics that must be transfered after projectile sticks on something +// Sticky projectile-related variables +var bool bStuck, bUseBone, bStuckToHead; +var name stuckBone; +var int stuckID; +// Data about explosive characteristics that must be transfered after projectile sticks on something struct ExplosionData{ - var Pawn instigator; - var NiceWeapon sourceWeapon; - var class bulletClass; + var Pawn instigator; + var NiceWeapon sourceWeapon; + var class bulletClass; var class explosionDamageType; - var float explosionDamage; - var float explosionRadius; - var float explosionExponent; - var float explosionMomentum; - var float fuseTime; - var bool explodeOnFuse; - var bool affectedByScream; - var bool stuckToHead; + var float explosionDamage; + var float explosionRadius; + var float explosionExponent; + var float explosionMomentum; + var float fuseTime; + var bool explodeOnFuse; + var bool affectedByScream; + var bool stuckToHead; }; //====================================================================================================================== -// Temporary variables that either need to be moved into config or generalized later -// How often trajectory is allowed to change direction? +// Temporary variables that either need to be moved into config or generalized later +// How often trajectory is allowed to change direction? var const float trajUpdFreq; -// How much tracing cycles to endure before declaring an infinite cycle? -var const int maxTraceCycles; -var bool bCanAngleDamage; +// How much tracing cycles to endure before declaring an infinite cycle? +var const int maxTraceCycles; +var bool bCanAngleDamage; //====================================================================================================================== -// State variables -// Indicates that all necessary values were recorded and we can process this bullet normally -var bool bInitFinished; -var bool bInitFinishDetected; -// Disables all the interaction of this bullet with the world and removes it / marks it for removal -var bool bBulletDead; -var bool bGhost; +// State variables +// Indicates that all necessary values were recorded and we can process this bullet normally +var bool bInitFinished; +var bool bInitFinishDetected; +// Disables all the interaction of this bullet with the world and removes it / marks it for removal +var bool bBulletDead; +var bool bGhost; //====================================================================================================================== -// Collision management -// Describes an actor that we don't wish to collide with +// Collision management +// Describes an actor that we don't wish to collide with struct IgnoreEntry{ - var Actor ignored; - // Set to true when 3rd party already disabled this actor before we had the chance - // Used to avoid re-enabling it later - var bool bExtDisabled; + var Actor ignored; + // Set to true when 3rd party already disabled this actor before we had the chance + // Used to avoid re-enabling it later + var bool bExtDisabled; }; -var array ignoredActors; -// 'true' if we're enforcing our collision rules on actors to ignore them -var bool bIgnoreIsActive; +var array ignoredActors; +// 'true' if we're enforcing our collision rules on actors to ignore them +var bool bIgnoreIsActive; //====================================================================================================================== -// Movement -// If 'true' disables any modifications to the bullet's movement, making it travel in a simple, linear path -var bool bDisableComplexMovement; -// Linear motion -var float movementSpeed; -var Vector movementDirection; -// Added vector acceleration -var Vector movementAcceleration; -var bool bShouldBounce; -// Amount of time our bullet should fall down after hitting a wall -var float movementFallTime; +// Movement +// If 'true' disables any modifications to the bullet's movement, making it travel in a simple, linear path +var bool bDisableComplexMovement; +// Linear motion +var float movementSpeed; +var Vector movementDirection; +// Added vector acceleration +var Vector movementAcceleration; +var bool bShouldBounce; +// Amount of time our bullet should fall down after hitting a wall +var float movementFallTime; //====================================================================================================================== -// Path building -// We will be building a piecewise linear path for projectiles, where each linear segment should be passable by -// projectile in time 'trajUpdFreq'. -// By changing trajectory in only preset point allow client to emulate non-linear paths, -// while keeping them more or less independent from the frame rate. -// Start and End point of the current linear segment +// Path building +// We will be building a piecewise linear path for projectiles, where each linear segment should be passable by +// projectile in time 'trajUpdFreq'. +// By changing trajectory in only preset point allow client to emulate non-linear paths, +// while keeping them more or less independent from the frame rate. +// Start and End point of the current linear segment var Vector pathSegmentS, pathSegmentE; -// Point in the segment, at which we've stopped after last movement +// Point in the segment, at which we've stopped after last movement var Vector shiftPoint; -// The part of current segment that we've already covered, changes from 0.0 to 1.0. -// Values above 1.0 indicate that segment was finished and we need to build another one. -// Values below 0.0 indicate that no segment has yet been built. +// The part of current segment that we've already covered, changes from 0.0 to 1.0. +// Values above 1.0 indicate that segment was finished and we need to build another one. +// Values below 0.0 indicate that no segment has yet been built. var float finishedSegmentPart; //====================================================================================================================== -// Visual effects -var class trailClass; +// Visual effects +var class trailClass; var class trailXClass; -var Emitter bulletTrail; -var xEmitter bulletXTrail; -// Describes effect that projectile should produce on hit -struct ImpactEffect{ - // Is this effect too important to cut it due to effect limit? - var bool bImportanEffect; - // Should we play classic KF's hit effect ('ROBulletHitEffect')? - var bool bPlayROEffect; - // Decal to spawn; null to skip - var class decalClass; - // Emitter to spawn; null to skip - var class emitterClass; - // How much back (against direction of the shot) should we spawn emitter? Can be used to avoid clipping with walls - var float emitterShiftWall; // Shift for wall-hits - var float emitterShiftPawn; // Shift for pawn-hits - // Impact noise parameters - var Sound noise; - var string noiseRef; // Reference to 'Sound' to allow dynamic resource allocation - var float noiseVolume; +var Emitter bulletTrail; +var xEmitter bulletXTrail; +// Describes effect that projectile should produce on hit +struct ImpactEffect { + // Is this effect too important to cut it due to effect limit? + var bool bImportanEffect; + // Should we play classic KF's hit effect ('ROBulletHitEffect')? + var bool bPlayROEffect; + // Decal to spawn; null to skip + var class decalClass; + // Emitter to spawn; null to skip + var class emitterClass; + // How much back (against direction of the shot) should we spawn emitter? Can be used to avoid clipping with walls + var float emitterShiftWall; // Shift for wall-hits + var float emitterShiftPawn; // Shift for pawn-hits + // Impact noise parameters + var Sound noise; + var string noiseRef; // Reference to 'Sound' to allow dynamic resource allocation + var float noiseVolume; }; -var ImpactEffect regularImpact; -var ImpactEffect explosionImpact; -var ImpactEffect disintegrationImpact; -var bool bGenRegEffectOnPawn; -var bool bShakeViewOnExplosion; -var Vector shakeRotMag; // how far to rot view -var Vector shakeRotRate; // how fast to rot view -var float shakeRotTime; // how much time to rot the instigator's view -var Vector shakeOffsetMag; // max view offset vertically -var Vector shakeOffsetRate; // how fast to offset view vertically -var float shakeOffsetTime; // how much time to offset view -var float shakeRadiusMult; +var ImpactEffect regularImpact; +var ImpactEffect explosionImpact; +var ImpactEffect disintegrationImpact; +var bool bGenRegEffectOnPawn; +var bool bShakeViewOnExplosion; +var Vector shakeRotMag; // how far to rot view +var Vector shakeRotRate; // how fast to rot view +var float shakeRotTime; // how much time to rot the instigator's view +var Vector shakeOffsetMag; // max view offset vertically +var Vector shakeOffsetRate; // how fast to offset view vertically +var float shakeOffsetTime; // how much time to offset view +var float shakeRadiusMult; //====================================================================================================================== -// References -// References to allow pre-loading of some resource objects, declared in parent classes +// References +// References to allow pre-loading of some resource objects, declared in parent classes var string meshRef; var string staticMeshRef; var string ambientSoundRef; //====================================================================================================================== -// Functions -static function PreloadAssets(){ - if(default.ambientSound == none && default.ambientSoundRef != "") - default.ambientSound = sound(DynamicLoadObject(default.ambientSoundRef, class'Sound', true)); - if(default.staticMesh == none && default.staticMeshRef != "") - UpdateDefaultStaticMesh(StaticMesh(DynamicLoadObject(default.staticMeshRef, class'StaticMesh', true))); - if(default.mesh == none && default.meshRef != "") - UpdateDefaultMesh(Mesh(DynamicLoadObject(default.meshRef, class'Mesh', true))); - if(default.regularImpact.noise == none && default.regularImpact.noiseRef != "") - default.regularImpact.noise = - sound(DynamicLoadObject(default.regularImpact.noiseRef, class'Sound', true)); - if(default.explosionImpact.noise == none && default.explosionImpact.noiseRef != "") - default.explosionImpact.noise = - sound(DynamicLoadObject(default.explosionImpact.noiseRef, class'Sound', true)); - if(default.disintegrationImpact.noise == none && default.disintegrationImpact.noiseRef != "") - default.disintegrationImpact.noise = - sound(DynamicLoadObject(default.disintegrationImpact.noiseRef, class'Sound', true)); +// Functions +static function PreloadAssets() { + if (default.ambientSound == none && default.ambientSoundRef != "") { + default.ambientSound = sound(DynamicLoadObject(default.ambientSoundRef, class'Sound', true)); + } + if (default.staticMesh == none && default.staticMeshRef != "") { + UpdateDefaultStaticMesh(StaticMesh(DynamicLoadObject(default.staticMeshRef, class'StaticMesh', true))); + } + if (default.mesh == none && default.meshRef != "") { + UpdateDefaultMesh(Mesh(DynamicLoadObject(default.meshRef, class'Mesh', true))); + } + if (default.regularImpact.noise == none && default.regularImpact.noiseRef != "") { + default.regularImpact.noise = + sound(DynamicLoadObject(default.regularImpact.noiseRef, class'Sound', true)); + } + if (default.explosionImpact.noise == none && default.explosionImpact.noiseRef != "") { + default.explosionImpact.noise = + sound(DynamicLoadObject(default.explosionImpact.noiseRef, class'Sound', true)); + } + if (default.disintegrationImpact.noise == none && default.disintegrationImpact.noiseRef != "") { + default.disintegrationImpact.noise = + sound(DynamicLoadObject(default.disintegrationImpact.noiseRef, class'Sound', true)); + } } -static function bool UnloadAssets(){ + +static function bool UnloadAssets() { default.AmbientSound = none; UpdateDefaultStaticMesh(none); UpdateDefaultMesh(none); @@ -205,400 +212,498 @@ static function bool UnloadAssets(){ default.disintegrationImpact.noise = none; return true; } -function PostBeginPlay(){ + +function PostBeginPlay() { super.PostBeginPlay(); - bounceHeadMod = 1.0; + bounceHeadMod = 1.0; } -function UpdateTrails(){ + +function UpdateTrails() { local Actor trailBase; + // Do nothing on dedicated server - if(Level.NetMode == NM_DedicatedServer) - return; + if (Level.NetMode == NM_DedicatedServer) { + return; + } // Spawn necessary trails first - if(trailClass != none && bulletTrail == none) - bulletTrail = Spawn(trailClass, self); - if(trailXClass != none && bulletXTrail == none) - bulletXTrail = Spawn(trailXClass, self); + if (trailClass != none && bulletTrail == none) { + bulletTrail = Spawn(trailClass, self); + } + if (trailXClass != none && bulletXTrail == none) { + bulletXTrail = Spawn(trailXClass, self); + } // Handle positioning differently for stuck and regular projectiles - if(bStuck && base != none){ - if(bUseBone){ - if(bulletTrail != none){ - bulletTrail.SetBase(base); - base.AttachToBone(bulletTrail, stuckBone); - bulletTrail.SetRelativeLocation(relativeLocation); - bulletTrail.SetRelativeRotation(relativeRotation); - } - if(bulletXTrail != none){ - bulletXTrail.SetBase(base); - base.AttachToBone(bulletTrail, stuckBone); - bulletXTrail.SetRelativeLocation(relativeLocation); - bulletXTrail.SetRelativeRotation(relativeRotation); - } - } + if (bStuck && base != none) { + if (bUseBone) { + if (bulletTrail != none) { + bulletTrail.SetBase(base); + base.AttachToBone(bulletTrail, stuckBone); + bulletTrail.SetRelativeLocation(relativeLocation); + bulletTrail.SetRelativeRotation(relativeRotation); + } + if (bulletXTrail != none) { + bulletXTrail.SetBase(base); + base.AttachToBone(bulletTrail, stuckBone); + bulletXTrail.SetRelativeLocation(relativeLocation); + bulletXTrail.SetRelativeRotation(relativeRotation); + } + } + } else { + trailBase = self; } - else - trailBase = self; + // Update lifetime and base (latter is for non-bone attachments only) - if(bulletTrail != none){ - if(trailBase != none) - bulletTrail.SetBase(trailBase); - bulletTrail.lifespan = lifeSpan; + if (bulletTrail != none) { + if (trailBase != none) { + bulletTrail.SetBase(trailBase); + } + bulletTrail.lifespan = lifeSpan; } - if(bulletXTrail != none){ - if(trailBase != none) - bulletXTrail.SetBase(trailBase); - bulletXTrail.lifespan = lifeSpan; + if (bulletXTrail != none) { + if (trailBase != none) { + bulletXTrail.SetBase(trailBase); + } + bulletXTrail.lifespan = lifeSpan; } } -function ResetPathBuilding(){ + +function ResetPathBuilding() { finishedSegmentPart = -1.0; shiftPoint = location; } -// Resets default values for this bullet. -// Must be called before each new use of a bullet. -function Renew(){ - bInitFinished = false; - bBulletDead = false; - bCanAngleDamage = true; - SoundVolume = default.SoundVolume; + +// Resets default values for this bullet. +// Must be called before each new use of a bullet. +function Renew() { + bInitFinished = false; + bBulletDead = false; + bCanAngleDamage = true; + SoundVolume = default.SoundVolume; decapMod = 1.0f; incapMod = 1.0f; ResetIgnoreList(); ResetPathBuilding(); } -simulated function Tick(float delta){ + +simulated function Tick(float delta) { super.Tick(delta); - if(localPlayer == none) - localPlayer = NicePlayerController(Level.GetLocalPlayerController()); - if(charFuseTime > 0){ - charFuseTime -= delta; - if(charFuseTime < 0){ - if(charExplodeOnFuse && !charIsDud){ - GenerateImpactEffects(explosionImpact, location, movementDirection); - if(bStuck) - class'NiceBulletAdapter'.static.Explode(self, niceRI, location, base); - else - class'NiceBulletAdapter'.static.Explode(self, niceRI, location); - } - if(!charExplodeOnFuse) - GenerateImpactEffects(disintegrationImpact, location, movementDirection); - KillBullet(); - } + + if (localPlayer == none) { + localPlayer = NicePlayerController(Level.GetLocalPlayerController()); } - if(bInitFinished && !bInitFinishDetected){ - bInitFinishDetected = true; - UpdateTrails(); + + if (charFuseTime > 0) { + charFuseTime -= delta; + if (charFuseTime < 0) { + if (charExplodeOnFuse && !charIsDud) { + GenerateImpactEffects(explosionImpact, location, movementDirection); + if (bStuck) { + class'NiceBulletAdapter'.static.Explode(self, niceRI, location, base); + } else { + class'NiceBulletAdapter'.static.Explode(self, niceRI, location); + } + } + if (!charExplodeOnFuse) { + GenerateImpactEffects(disintegrationImpact, location, movementDirection); + } + KillBullet(); + } } - if(bInitFinished && !bBulletDead && !bStuck) - DoProcessMovement(delta); - if(bInitFinished && bStuck){ - if(base == none || (KFMonster(base) != none && KFMonster(base).health <= 0)) - nicePlayer.ExplodeStuckBullet(stuckID); + + if (bInitFinished && !bInitFinishDetected) { + bInitFinishDetected = true; + UpdateTrails(); + } + if (bInitFinished && !bBulletDead && !bStuck) { + DoProcessMovement(delta); + } + if (bInitFinished && bStuck) { + if (base == none || (KFMonster(base) != none && KFMonster(base).health <= 0)) { + nicePlayer.ExplodeStuckBullet(stuckID); + } } } -// Extracts pawn actor from it's auxiliary collision -// @param other Actor we collided with -// @return Pawn we're interested in -function Actor GetMainActor(Actor other){ - if(other == none) - return none; + +// Extracts pawn actor from it's auxiliary collision +// @param other Actor we collided with +// @return Pawn we're interested in +function Actor GetMainActor(Actor other) { + if (other == none) { + return none; + } + // Try owner - if( KFPawn(other) == none && KFMonster(other) == none - && (KFPawn(other.owner) != none || KFMonster(other.owner) != none) ) - other = other.owner; + if ( + KFPawn(other) == none && + KFMonster(other) == none && + (KFPawn(other.owner) != none || KFMonster(other.owner) != none) + ) { + other = other.owner; + } + // Try base - if( KFPawn(other) == none && KFMonster(other) == none - && (KFPawn(other.base) != none || KFMonster(other.base) != none) ) - other = other.base; + if ( + KFPawn(other) == none && + KFMonster(other) == none && + (KFPawn(other.base) != none || KFMonster(other.base) != none) + ) { + other = other.base; + } + return other; } -// Returns 'true' if passed actor is either world geometry, 'Level' itself or nothing ('none') -// Neither of these related to pawn damage dealing -function bool IsLevelActor(Actor other){ - if(other == none) - return true; + +// Returns 'true' if passed actor is either world geometry, 'Level' itself or nothing ('none') +// Neither of these related to pawn damage dealing +function bool IsLevelActor(Actor other) { + if (other == none) { + return true; + } return (other.bWorldGeometry || other == Level); } -// Adds given actor and every colliding object connected to it to ignore list -// Removes their collision in case ignore is active (see 'bIgnoreIsActive') -function TotalIgnore(Actor other){ + +// Adds given actor and every colliding object connected to it to ignore list +// Removes their collision in case ignore is active (see 'bIgnoreIsActive') +function TotalIgnore(Actor other) { // These mark what objects, associated with 'other' we also need to ignore - local KFPawn pawnOther; + local KFPawn pawnOther; local KFMonster zedOther; - if(other == none) - return; + + if (other == none) { + return; + } // Try to find main actor as KFPawn pawnOther = KFPawn(other); - if(pawnOther == none) - pawnOther = KFPawn(other.base); - if(pawnOther == none) - pawnOther = KFPawn(other.owner); + if (pawnOther == none) { + pawnOther = KFPawn(other.base); + } + if (pawnOther == none) { + pawnOther = KFPawn(other.owner); + } // Try to find main actor as KFMonster zedOther = KFMonster(other); - if(zedOther == none) - zedOther = KFMonster(other.base); - if(zedOther == none) - zedOther = KFMonster(other.owner); + if (zedOther == none) { + zedOther = KFMonster(other.base); + } + if (zedOther == none) { + zedOther = KFMonster(other.owner); + } // Ignore everything that's associated with this actor and can have collision IgnoreActor(other); IgnoreActor(other.base); IgnoreActor(other.owner); - if(pawnOther != none) - IgnoreActor(pawnOther.AuxCollisionCylinder); - if(zedOther != none) - IgnoreActor(zedOther.MyExtCollision); -} -// Adds a given actor to ignore list and removes it's collision in case ignore is active (see 'bIgnoreIsActive') -function IgnoreActor(Actor other){ - local int i; - local IgnoreEntry newIgnoredEntry; - // Check if that's a non-level actor and not already on the list - if(IsLevelActor(other)) - return; - for(i = 0;i < ignoredActors.Length;i ++) - if(ignoredActors[i].ignored == other) - return; - // Add actor to the ignore list & disable collision if needed - if(other != none){ - // Make entry - newIgnoredEntry.ignored = other; - newIgnoredEntry.bExtDisabled = !other.bCollideActors; - // Add and activate it - ignoredActors[ignoredActors.Length] = newIgnoredEntry; - if(bIgnoreIsActive) - other.SetCollision(false); + if (pawnOther != none) { + IgnoreActor(pawnOther.AuxCollisionCylinder); + } + if (zedOther != none) { + IgnoreActor(zedOther.MyExtCollision); } } -// Restores ignored state of the actors and zeroes our ignored arrays -function ResetIgnoreList(){ + +// Adds a given actor to ignore list and removes it's collision in case ignore is active (see 'bIgnoreIsActive') +function IgnoreActor(Actor other) { + local int i; + local IgnoreEntry newIgnoredEntry; + + // Check if that's a non-level actor and not already on the list + if (IsLevelActor(other)) { + return; + } + for (i = 0; i < ignoredActors.Length; i ++) { + if (ignoredActors[i].ignored == other) { + return; + } + } + // Add actor to the ignore list & disable collision if needed + if (other != none) { + // Make entry + newIgnoredEntry.ignored = other; + newIgnoredEntry.bExtDisabled = !other.bCollideActors; + // Add and activate it + ignoredActors[ignoredActors.Length] = newIgnoredEntry; + if (bIgnoreIsActive) { + other.SetCollision(false); + } + } +} + +// Restores ignored state of the actors and zeroes our ignored arrays +function ResetIgnoreList() { SetIgnoreActive(false); ignoredActors.Length = 0; } -// Activates/deactivates ignore for actors on the ignore list. -// Ignore deactivation doesn't restore collision if actor was set to not collide prior most recent ignore activation. -// Activating ignore when it's already active does nothing; same with deactivation. -// Ignore deactivation is supposed to be used in the same function call in which activation took place before. -function SetIgnoreActive(bool bActive){ + +// Activates/deactivates ignore for actors on the ignore list. +// Ignore deactivation doesn't restore collision if actor was set to not collide prior most recent ignore activation. +// Activating ignore when it's already active does nothing; same with deactivation. +// Ignore deactivation is supposed to be used in the same function call in which activation took place before. +function SetIgnoreActive(bool bActive) { local int i; + // Do nothing if we're already in a correct state - if(bActive == bIgnoreIsActive) - return; + if (bActive == bIgnoreIsActive) { + return; + } // Change ignore state & disable collision for ignored actors bIgnoreIsActive = bActive; - for(i = 0;i < ignoredActors.Length;i ++) - if(ignoredActors[i].ignored != none){ - // Mark actors that were set to not collide before activation - if(bActive && !ignoredActors[i].ignored.bCollideActors) - ignoredActors[i].bExtDisabled = true; - // Change collision for actors that weren't externally modified - if(!ignoredActors[i].bExtDisabled) - ignoredActors[i].ignored.SetCollision(!bActive); - // After we deactivated our rules - forget about external modifications - if(!bActive) - ignoredActors[i].bExtDisabled = false; - } + for (i = 0; i < ignoredActors.Length; i ++) { + if (ignoredActors[i].ignored != none) { + // Mark actors that were set to not collide before activation + if (bActive && !ignoredActors[i].ignored.bCollideActors) { + ignoredActors[i].bExtDisabled = true; + } + // Change collision for actors that weren't externally modified + if (!ignoredActors[i].bExtDisabled) { + ignoredActors[i].ignored.SetCollision(!bActive); + } + // After we deactivated our rules - forget about external modifications + if (!bActive) { + ignoredActors[i].bExtDisabled = false; + } + } + } } -function SetHumanPawnCollision(bool bEnable){ + +function SetHumanPawnCollision(bool bEnable) { local int i; - if(niceMutator == none) - niceMutator = class'NicePack'.static.Myself(Level); - for(i = 0;i < niceMutator.recordedHumanPawns.Length;i ++) - if(niceMutator.recordedHumanPawns[i] != none) - niceMutator.recordedHumanPawns[i].bBlockHitPointTraces = bEnable; + + if (niceMutator == none) { + niceMutator = class'NicePack'.static.Myself(Level); + } + + for (i = 0; i < niceMutator.recordedHumanPawns.Length; i ++) { + if (niceMutator.recordedHumanPawns[i] != none) { + niceMutator.recordedHumanPawns[i].bBlockHitPointTraces = bEnable; + } + } } -function float CheckHeadshot(KFMonster kfZed, Vector hitLocation, Vector hitDirection){ - local float hsMod; - local float precision; - local bool bIsShotgunBullet; - local NiceMonster niceZed; - local KFPlayerReplicationInfo KFPRI; + +function float CheckHeadshot(KFMonster kfZed, Vector hitLocation, Vector hitDirection) { + local float hsMod; + local float precision; + local bool bIsShotgunBullet; + local NiceMonster niceZed; + local KFPlayerReplicationInfo KFPRI; local class niceVet; + niceZed = NiceMonster(kfZed); hitDirection = Normal(hitDirection); bIsShotgunBullet = ClassIsChildOf(charDamageType, class'NiceDamageTypeVetEnforcer'); - if(niceZed != none){ - hsMod = bounceHeadMod; // NICETODO: Add bounce and perk and damage type head-shot zones bonuses - hsMod *= charDamageType.default.headSizeModifier; - hsMod *= bounceHeadMod; - if(nicePlayer != none) - KFPRI = KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo); - if(KFPRI != none) - niceVet = class(KFPRI.ClientVeteranSkill); - if(niceVet != none) - hsMod *= niceVet.static.GetHeadshotCheckMultiplier(KFPRI, charDamageType); - precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod); - if(precision <= 0.0 && bIsShotgunBullet && nicePlayer != none && class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillSupportGraze')){ - bGrazing = true; - hsMod *= class'NiceSkillSupportGraze'.default.hsBonusZoneMult; - precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod); - } - return precision; - } - else{ - if(kfZed.IsHeadShot(hitLocation, hitDirection, 1.0)) - return 1.0; - else - return 0.0; + if (niceZed != none) { + hsMod = bounceHeadMod; // NICETODO: Add bounce and perk and damage type head-shot zones bonuses + hsMod *= charDamageType.default.headSizeModifier; + hsMod *= bounceHeadMod; + if (nicePlayer != none) { + KFPRI = KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo); + } + if (KFPRI != none) { + niceVet = class(KFPRI.ClientVeteranSkill); + } + if (niceVet != none) { + hsMod *= niceVet.static.GetHeadshotCheckMultiplier(KFPRI, charDamageType); + } + precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod); + if ( + precision <= 0.0 && + bIsShotgunBullet && + nicePlayer != none && + class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillSupportGraze') + ) { + bGrazing = true; + hsMod *= class'NiceSkillSupportGraze'.default.hsBonusZoneMult; + precision = niceZed.IsHeadshotClient(hitLocation, hitDirection, niceZed.clientHeadshotScale * hsMod); + } + return precision; + } else { + if (kfZed.IsHeadShot(hitLocation, hitDirection, 1.0)) { + return 1.0; + } else { + return 0.0; + } } } -// Makes bullet trace a directed line segment given by start and end points. -// All traced actors and geometry are then properly affected by corresponding 'HandleHitPawn', 'HandleHitZed' and -// 'HandleHitWall' functions. -// Might have to do several traces in case it either hits a (several) target(s) -function DoTraceLine(Vector lineStart, Vector lineEnd){ - local float headshotLevel; + +// Makes bullet trace a directed line segment given by start and end points. +// All traced actors and geometry are then properly affected by corresponding 'HandleHitPawn', 'HandleHitZed' and +// 'HandleHitWall' functions. +// Might have to do several traces in case it either hits a (several) target(s) +function DoTraceLine(Vector lineStart, Vector lineEnd) { + local float headshotLevel; // Amount of tracing iterations we had to do - local int iterationCount; + local int iterationCount; // Direction and length of traced line - local Vector lineDirection; + local Vector lineDirection; // Auxiliary variables for retrieving results of tracing - local Vector hitLocation, hitNormal; - local Actor tracedActor; - local array hitPoints; - local KFMonster tracedZed; - local KFPawn tracedPawn; + local Vector hitLocation, hitNormal; + local Actor tracedActor; + local array hitPoints; + local KFMonster tracedZed; + local KFPawn tracedPawn; + lineDirection = (lineEnd - lineStart); lineDirection = (lineDirection) / VSize(lineDirection); // Do not trace for disabled bullets and prevent infinite loops - while(!bBulletDead && iterationCount < maxTraceCycles){ - iterationCount ++; - // Trace next object - if(!bGhost || localPlayer == none || localPlayer.tracesThisTick <= localPlayer.tracesPerTickLimit){ - if(Instigator != none) - tracedActor = Instigator.Trace(hitLocation, hitNormal, lineEnd, lineStart, true); - else - tracedActor = none; - localPlayer.tracesThisTick ++; - } - else - tracedActor = none; - if(charAffectedByScream && !charIsDud && localPlayer != none && localPlayer.localCollisionManager != none && localPlayer.localCollisionManager.IsCollidingWithAnything(lineStart, lineEnd)) - HandleScream(lineStart, lineDirection); - if(tracedActor != none && IsLevelActor(tracedActor)){ - HandleHitWall(tracedActor, hitLocation, hitNormal); - break; - } - else{ - TotalIgnore(tracedActor); - tracedActor = GetMainActor(tracedActor); - } + while (!bBulletDead && iterationCount < maxTraceCycles) { + iterationCount++; + // Trace next object + if (!bGhost || localPlayer == none || localPlayer.tracesThisTick <= localPlayer.tracesPerTickLimit) { + if (Instigator != none) { + tracedActor = Instigator.Trace(hitLocation, hitNormal, lineEnd, lineStart, true); + } else { + tracedActor = none; + } + localPlayer.tracesThisTick++; + } else { + tracedActor = none; + } + if ( + charAffectedByScream && + !charIsDud && + localPlayer != none && + localPlayer.localCollisionManager != none && + localPlayer.localCollisionManager.IsCollidingWithAnything(lineStart, lineEnd) + ) { + HandleScream(lineStart, lineDirection); + } + if (tracedActor != none && IsLevelActor(tracedActor)) { + HandleHitWall(tracedActor, hitLocation, hitNormal); + break; + } else { + TotalIgnore(tracedActor); + tracedActor = GetMainActor(tracedActor); + } - // If tracing between current trace points haven't found anything and tracing step is less than segment's length - // -- shift tracing bounds - if(tracedActor == none) - return; + // If tracing between current trace points haven't found anything and tracing step is less than segment's length + // -- shift tracing bounds + if (tracedActor == none) { + return; + } - // First, try to handle pawn like a zed; if fails, - try to handle it like 'KFPawn' - tracedZed = KFMonster(tracedActor); - tracedPawn = KFPawn(tracedActor); - if(tracedPawn != none && NiceHumanPawn(instigator) != none && - (NiceHumanPawn(instigator).ffScale <= 0 && NiceMedicProjectile(self) == none) ) - continue; - if(tracedZed != none){ - if(tracedZed.Health > 0){ - headshotLevel = CheckHeadshot(tracedZed, hitLocation, lineDirection); - HandleHitZed(tracedZed, hitLocation, lineDirection, headshotLevel); - } - } - else if(tracedPawn != none && tracedPawn.Health > 0){ - if(tracedPawn.Health > 0) - HandleHitPawn(tracedPawn, hitLocation, lineDirection, hitPoints); - } - else - HandleHitWall(tracedActor, hitLocation, hitNormal); + // First, try to handle pawn like a zed; if fails, - try to handle it like 'KFPawn' + tracedZed = KFMonster(tracedActor); + tracedPawn = KFPawn(tracedActor); + if ( + tracedPawn != none && + NiceHumanPawn(instigator) != none && + (NiceHumanPawn(instigator).ffScale <= 0 && NiceMedicProjectile(self) == none) + ) { + continue; + } + if (tracedZed != none) { + if (tracedZed.Health > 0) { + headshotLevel = CheckHeadshot(tracedZed, hitLocation, lineDirection); + HandleHitZed(tracedZed, hitLocation, lineDirection, headshotLevel); + } + } else if (tracedPawn != none && tracedPawn.Health > 0) { + if (tracedPawn.Health > 0) { + HandleHitPawn(tracedPawn, hitLocation, lineDirection, hitPoints); + } + } else { + HandleHitWall(tracedActor, hitLocation, hitNormal); + } } } -// Replaces current path segment with the next one. -// Doesn't check whether or not we've finished with the current segment. -function BuildNextPathSegment(){ + +// Replaces current path segment with the next one. +// Doesn't check whether or not we've finished with the current segment. +function BuildNextPathSegment() { // Only set start point to our location when we build path segment for the first time // After that we can't even assume that bullet is exactly in the 'pathSegmentE' point - if(finishedSegmentPart < 0.0) - pathSegmentS = Location; - else - pathSegmentS = pathSegmentE; + if (finishedSegmentPart < 0.0) { + pathSegmentS = Location; + } else { + pathSegmentS = pathSegmentE; + } movementDirection += (movementAcceleration * trajUpdFreq) / movementSpeed; pathSegmentE = pathSegmentS + movementDirection * movementSpeed * trajUpdFreq; finishedSegmentPart = 0.0; shiftPoint = pathSegmentS; } -// Updates 'shiftPoint' to the next bullet position in current segment. -// Does nothing if current segment is finished or no segment was built at all. -// @param delta Amount of time bullet has to move through the segment. -// @return Amount of time left for bullet to move after this segment -function float ShiftInSegment(float delta){ + +// Updates 'shiftPoint' to the next bullet position in current segment. +// Does nothing if current segment is finished or no segment was built at all. +// @param delta Amount of time bullet has to move through the segment. +// @return Amount of time left for bullet to move after this segment +function float ShiftInSegment(float delta) { // Time that bullet still has available to move after this segment local float remainingTime; // Part of segment we can pass in a given time local float segmentPartWeCanPass; + // Exit if there's no segment in progress - if(finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) - return delta; + if (finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) { + return delta; + } // [movementSpeed * delta] / [movementSpeed * trajUpdFreq] = [delta / trajUpdFreq] segmentPartWeCanPass = delta / trajUpdFreq; // If we can move through the rest of the segment - move to end point and mark it finished - if(segmentPartWeCanPass >= (1.0 - finishedSegmentPart)){ - remainingTime = delta - (1.0 - finishedSegmentPart) * trajUpdFreq; - finishedSegmentPart = 1.1; - shiftPoint = pathSegmentE; - } - // Otherwise compute new 'shiftPoint' normally - else{ - remainingTime = 0.0; - finishedSegmentPart += (delta / trajUpdFreq); - shiftPoint = pathSegmentS + movementDirection * movementSpeed * trajUpdFreq * finishedSegmentPart; + if (segmentPartWeCanPass >= (1.0 - finishedSegmentPart)) { + remainingTime = delta - (1.0 - finishedSegmentPart) * trajUpdFreq; + finishedSegmentPart = 1.1; + shiftPoint = pathSegmentE; + } else { + // Otherwise compute new 'shiftPoint' normally + remainingTime = 0.0; + finishedSegmentPart += (delta / trajUpdFreq); + shiftPoint = pathSegmentS + movementDirection * movementSpeed * trajUpdFreq * finishedSegmentPart; } return remainingTime; } -// Moves bullet according to settings and decides when and how much tracing should it do. -// @param delta Amount of time passed after previous bullet movement -function DoProcessMovement(float delta){ - local Vector tempVect; + +// Moves bullet according to settings and decides when and how much tracing should it do. +// @param delta Amount of time passed after previous bullet movement +function DoProcessMovement(float delta) { + local Vector tempVect; + SetIgnoreActive(true); //SetHumanPawnCollision(true); - // Simple linear movement - if(bDisableComplexMovement){ - // Use 'traceStart' as a shift variable here - // Naming is bad in this case, but it avoids - tempVect = movementDirection * movementSpeed * delta; - DoTraceLine(location, location + tempVect); - Move(tempVect); - // Reset path building - // If in future complex movement would be re-enabled, - we want to set first point of the path to - // the location of bullet at a time and not use outdated information. - finishedSegmentPart = -1.0; - } - // Non-linear movement support - else{ - while(delta > 0.0){ - if(finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) - BuildNextPathSegment(); - // Remember current 'shiftPoint'. That's where we stopped tracing last time and where we must resume. - tempVect = shiftPoint; - // Update 'shiftPoint' (bullet position) - // and update how much time we've got left after we wasted some to move. - delta = ShiftInSegment(delta); - // Trace between end point of previous tracing and end point of the new one. - DoTraceLine(tempVect, shiftPoint); - } - tempVect = shiftPoint - location; - Move(shiftPoint - location); + // Simple linear movement + if (bDisableComplexMovement) { + // Use 'traceStart' as a shift variable here + // Naming is bad in this case, but it avoids + tempVect = movementDirection * movementSpeed * delta; + DoTraceLine(location, location + tempVect); + Move(tempVect); + // Reset path building + // If in future complex movement would be re-enabled, - we want to set first point of the path to + // the location of bullet at a time and not use outdated information. + finishedSegmentPart = -1.0; + } else { + // Non-linear movement support + while(delta > 0.0) { + if (finishedSegmentPart < 0.0 || finishedSegmentPart > 1.0) { + BuildNextPathSegment(); + } + // Remember current 'shiftPoint'. That's where we stopped tracing last time and where we must resume. + tempVect = shiftPoint; + // Update 'shiftPoint' (bullet position) + // and update how much time we've got left after we wasted some to move. + delta = ShiftInSegment(delta); + // Trace between end point of previous tracing and end point of the new one. + DoTraceLine(tempVect, shiftPoint); + } + tempVect = shiftPoint - location; + Move(shiftPoint - location); } SetRotation(Rotator(movementDirection)); - if(charMinExplosionDist > 0) - charMinExplosionDist -= VSize(tempVect); + if (charMinExplosionDist > 0) { + charMinExplosionDist -= VSize(tempVect); + } SetIgnoreActive(false); - //SetHumanPawnCollision(false); + // SetHumanPawnCollision(false); } -function Stick(Actor target, Vector hitLocation){ - local NiceMonster targetZed; - local name boneStick; - local float distToBone; - local float t; - local Vector boneStrickOrig; + +function Stick(Actor target, Vector hitLocation) { + local NiceMonster targetZed; + local name boneStick; + local float distToBone; + local float t; + local Vector boneStrickOrig; local ExplosionData expData; - if(bGhost) - return; + + if (bGhost) { + return; + } expData.explosionDamageType = charExplosionDamageType; expData.explosionDamage = charExplosionDamage; expData.explosionRadius = charExplosionRadius; @@ -609,236 +714,322 @@ function Stick(Actor target, Vector hitLocation){ expData.affectedByScream = charAffectedByScream; expData.sourceWeapon = sourceWeapon; targetZed = NiceMonster(target); - if(targetZed == none){ - expData.bulletClass = class; - expData.instigator = instigator; - niceRI.ServerStickProjectile(KFHumanPawn(instigator), target, 'None', hitLocation - target.location, - Rotator(movementDirection), expData); - class'NiceProjectileSpawner'.static.StickProjectile(KFHumanPawn(instigator), target, 'None', - hitLocation - target.location, Rotator(movementDirection), expData); + + if (targetZed == none) { + expData.bulletClass = class; + expData.instigator = instigator; + niceRI.ServerStickProjectile( + KFHumanPawn(instigator), + target, + 'None', + hitLocation - target.location, + Rotator(movementDirection), + expData + ); + class'NiceProjectileSpawner'.static.StickProjectile( + KFHumanPawn(instigator), + target, + 'None', + hitLocation - target.location, + Rotator(movementDirection), + expData + ); + } else { + expData.bulletClass = class; + expData.instigator = instigator; + boneStick = targetZed.GetClosestBone(hitLocation, movementDirection, distToBone); + if (CheckHeadshot(targetZed, hitLocation, movementDirection) > 0.0) { + boneStick = targetZed.HeadBone; + } + if (boneStick == targetZed.HeadBone) { + expData.stuckToHead = true; + } + boneStrickOrig = targetZed.GetBoneCoords(boneStick).origin; + t = movementDirection.x * (boneStrickOrig.x - hitLocation.x) + + movementDirection.y * (boneStrickOrig.y - hitLocation.y) + + movementDirection.z * (boneStrickOrig.z - hitLocation.z); + t /= VSizeSquared(movementDirection); + t *= 0.5; + hitLocation = hitLocation + t * movementDirection; + niceRI.ServerStickProjectile( + KFHumanPawn(instigator), + targetZed, + boneStick, + hitLocation - boneStrickOrig, + Rotator(movementDirection), + expData + ); + class'NiceProjectileSpawner'.static.StickProjectile( + KFHumanPawn(instigator), + targetZed, + boneStick, + hitLocation - boneStrickOrig, + Rotator(movementDirection), + expData + ); } - else{ - expData.bulletClass = class; - expData.instigator = instigator; - boneStick = targetZed.GetClosestBone(hitLocation, movementDirection, distToBone); - if(CheckHeadshot(targetZed, hitLocation, movementDirection) > 0.0) - boneStick = targetZed.HeadBone; - if(boneStick == targetZed.HeadBone) - expData.stuckToHead = true; - boneStrickOrig = targetZed.GetBoneCoords(boneStick).origin; - t = movementDirection.x * (boneStrickOrig.x - hitLocation.x) + - movementDirection.y * (boneStrickOrig.y - hitLocation.y) + - movementDirection.z * (boneStrickOrig.z - hitLocation.z); - t /= VSizeSquared(movementDirection); - t *= 0.5; - hitLocation = hitLocation + t * movementDirection; - niceRI.ServerStickProjectile(KFHumanPawn(instigator), targetZed, boneStick, - hitLocation - boneStrickOrig, Rotator(movementDirection), expData); - class'NiceProjectileSpawner'.static.StickProjectile(KFHumanPawn(instigator), targetZed, boneStick, - hitLocation - boneStrickOrig, Rotator(movementDirection), expData); - } - KillBullet(); -} -function DoExplode(Vector explLocation, Vector impactNormal){ - if(charIsDud) - return; - if(bStuck) - class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation, base); - else - class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation); - GenerateImpactEffects(explosionImpact, explLocation, impactNormal, true, true); - if(bShakeViewOnExplosion) - ShakeView(explLocation); - KillBullet(); -} -function HandleHitWall(Actor wall, Vector hitLocation, Vector hitNormal){ - local bool bBulletTooWeak; - if(charExplodeOnWallHit && !charIsDud && charMinExplosionDist <= 0.0){ - DoExplode(hitLocation, hitNormal); - return; - } - else{ - class'NiceBulletAdapter'.static.HitWall(self, niceRI, wall, hitLocation, hitNormal); - GenerateImpactEffects(regularImpact, hitLocation, hitNormal, true, true); - if(charIsSticky) - Stick(wall, hitLocation); - } - if(bShouldBounce && !bDisableComplexMovement){ - movementDirection = (movementDirection - 2.0 * hitNormal * (movementDirection dot hitNormal)); - bBulletTooWeak = !class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false); - charPenetrationCount += 1; - ResetPathBuilding(); - ResetIgnoreList(); - bounceHeadMod *= 2; - } - else if(movementFallTime > 0.0){ - charIsDud = true; - lifeSpan = movementFallTime; - movementFallTime = 0.0; - movementDirection = vect(0,0,0); - ResetPathBuilding(); - ResetIgnoreList(); - } - else - bBulletTooWeak = true; - if(bBulletTooWeak) - KillBullet(); -} -function HandleHitPawn(KFPawn hitPawn, Vector hitLocation, Vector hitDirection, array hitPoints){ - if(charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0){ - DoExplode(hitLocation, hitDirection); - GenerateImpactEffects(explosionImpact, hitLocation, hitDirection); - return; - } - else{ - class'NiceBulletAdapter'.static.HitPawn(self, niceRI, hitPawn, hitLocation, hitDirection, hitPoints); - if(bGenRegEffectOnPawn) - GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); - } - if(!class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false)){ - charPenetrationCount += 1; - KillBullet(); - } -} -function HandleHitZed(KFMonster targetZed, Vector hitLocation, Vector hitDirection, float headshotLevel){ - local bool bHitZedCalled; - if(class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillDemoDirectApproach')){ - class'NiceBulletAdapter'.static.HitZed(self, niceRI, targetZed, hitLocation, hitDirection, headshotLevel); - if(bGenRegEffectOnPawn) - GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); - bHitZedCalled = true; - } - if(charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0){ - class'NiceBulletAdapter'.static.Explode(self, niceRI, hitLocation, targetZed); - GenerateImpactEffects(explosionImpact, hitLocation, hitDirection); - if(bShakeViewOnExplosion) - ShakeView(hitLocation); - KillBullet(); - return; - } - else{ - if(!bHitZedCalled){ - class'NiceBulletAdapter'.static.HitZed(self, niceRI, targetZed, hitLocation, hitDirection, headshotLevel); - if(bGenRegEffectOnPawn) - GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); - } - bHitZedCalled = true; - if(!bGhost && !bAlreadyHitZed){ - bAlreadyHitZed = true; - if(nicePlayer != none && niceRI != none) - niceRI.ServerJunkieExtension(nicePlayer, headshotLevel > 0.0); - } - if(charIsSticky) - Stick(targetZed, hitLocation); - } - if(!class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, targetZed, (headshotLevel > 0.0), (headshotLevel > charDamageType.default.prReqPrecise))){ - charPenetrationCount += 1; - KillBullet(); - } -} -function HandleScream(Vector disintegrationLocation, Vector entryDirection){ - if(!charIsDud) - GenerateImpactEffects(disintegrationImpact, disintegrationLocation, entryDirection); - class'NiceBulletAdapter'.static.HandleScream(self, niceRI, disintegrationLocation, entryDirection); -} -function GenerateImpactEffects(ImpactEffect effect, Vector hitLocation, Vector hitNormal, - optional bool bWallImpact, optional bool bGenerateDecal){ - local float actualCullDistance; - local float actualImpactShift; - local bool generatedEffect; - // No need to play visuals on a server, for a dead bullets or in case there's no local player at all - if(Level.NetMode == NM_DedicatedServer || bBulletDead || localPlayer == none) - return; - if(!localPlayer.CanSpawnEffect(bGhost) && !effect.bImportanEffect) - return; - // -- Classic effect - if(effect.bPlayROEffect && !bBulletDead) - Spawn(class'ROBulletHitEffect',,, hitLocation, rotator(-hitNormal)); - // -- Generate decal - if(bGenerateDecal && effect.decalClass != none){ - // Find appropriate cull distance for this decal - actualCullDistance = effect.decalClass.default.cullDistance; - // Double cull distance if local player is an instigator - if(instigator != none && localPlayer == instigator.Controller) - actualCullDistance *= 2; // NICETODO: magic number - // Spawn decal - if(!localPlayer.BeyondViewDistance(hitLocation, actualCullDistance)){ - Spawn(effect.decalClass, self,, hitLocation, rotator(- hitNormal)); - generatedEffect = true; - } - } - // -- Generate custom effect - if(effect.emitterClass != none && EffectIsRelevant(hitLocation, false)){ - if(bWallImpact) - actualImpactShift = effect.emitterShiftWall; - else - actualImpactShift = effect.emitterShiftPawn; - Spawn(effect.emitterClass,,, hitLocation - movementDirection * actualImpactShift, rotator(movementDirection)); - generatedEffect = true; - } - // -- Generate custom sound - if(effect.noise != none){ - class'NiceSoundCls'.default.effectSound = effect.noise; - class'NiceSoundCls'.default.effectVolume = effect.noiseVolume; - Spawn(class'NiceSoundCls',,, hitLocation); - generatedEffect = true; - } - if(generatedEffect) - localPlayer.AddEffect(); -} -function ShakeView(Vector hitLocation){ - local float distance, scale; - if(nicePlayer == none || shakeRadiusMult < 0.0) - return; - distance = VSize(hitLocation - nicePlayer.ViewTarget.Location); - if(distance < charExplosionRadius * shakeRadiusMult){ - if(distance < charExplosionRadius) - scale = 1.0; - else - scale = (charExplosionRadius * ShakeRadiusMult - distance) / (charExplosionRadius); - nicePlayer.ShakeView(shakeRotMag*scale, shakeRotRate, shakeRotTime, shakeOffsetMag * scale, shakeOffsetRate, shakeOffsetTime); - } -} -function KillBullet(){ - local int i; - if(bulletTrail != none){ - for(i = 0;i < bulletTrail.Emitters.Length;i ++){ - if(bulletTrail.Emitters[i] == none) - continue; - bulletTrail.Emitters[i].ParticlesPerSecond = 0; - bulletTrail.Emitters[i].InitialParticlesPerSecond = 0; - bulletTrail.Emitters[i].RespawnDeadParticles = false; - } - bulletTrail.SetBase(none); - bulletTrail.AutoDestroy = true; - } - if(bulletXTrail != none){ - bulletXTrail.mRegen = false; - bulletXTrail.LifeSpan = LifeSpan; - } - bBulletDead = true; - bHidden = true; - SoundVolume = 0; - LifeSpan = FMin(LifeSpan, 0.1); -} -event Destroyed(){ KillBullet(); } -defaultproperties -{ - insideBouncesLeft=2 - trajUpdFreq=0.100000 - maxTraceCycles=128 - bDisableComplexMovement=True - trailXClass=Class'KFMod.KFTracer' - regularImpact=(bPlayROEffect=True) - StaticMeshRef="kf_generic_sm.Shotgun_Pellet" - DrawType=DT_StaticMesh - bAcceptsProjectors=False - LifeSpan=15.000000 - Texture=Texture'Engine.S_Camera' - bGameRelevant=True - bCanBeDamaged=True - SoundVolume=255 +function DoExplode(Vector explLocation, Vector impactNormal) { + if (charIsDud) { + return; + } + if (bStuck) { + class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation, base); + } else { + class'NiceBulletAdapter'.static.Explode(self, niceRI, explLocation); + } + GenerateImpactEffects(explosionImpact, explLocation, impactNormal, true, true); + if (bShakeViewOnExplosion) { + ShakeView(explLocation); + } + KillBullet(); } + +function HandleHitWall(Actor wall, Vector hitLocation, Vector hitNormal) { + local bool bBulletTooWeak; + + if (charExplodeOnWallHit && !charIsDud && charMinExplosionDist <= 0.0) { + DoExplode(hitLocation, hitNormal); + return; + } else { + class'NiceBulletAdapter'.static.HitWall(self, niceRI, wall, hitLocation, hitNormal); + GenerateImpactEffects(regularImpact, hitLocation, hitNormal, true, true); + if (charIsSticky) { + Stick(wall, hitLocation); + } + } + + if (bShouldBounce && !bDisableComplexMovement) { + movementDirection = (movementDirection - 2.0 * hitNormal * (movementDirection dot hitNormal)); + bBulletTooWeak = !class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false); + charPenetrationCount += 1; + ResetPathBuilding(); + ResetIgnoreList(); + bounceHeadMod *= 2; + } else if (movementFallTime > 0.0) { + charIsDud = true; + lifeSpan = movementFallTime; + movementFallTime = 0.0; + movementDirection = vect(0, 0, 0); + ResetPathBuilding(); + ResetIgnoreList(); + } else { + bBulletTooWeak = true; + } + + if (bBulletTooWeak) { + KillBullet(); + } +} + +function HandleHitPawn(KFPawn hitPawn, Vector hitLocation, Vector hitDirection, array hitPoints) { + if (charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0) { + DoExplode(hitLocation, hitDirection); + GenerateImpactEffects(explosionImpact, hitLocation, hitDirection); + return; + } else { + class'NiceBulletAdapter'.static.HitPawn(self, niceRI, hitPawn, hitLocation, hitDirection, hitPoints); + if (bGenRegEffectOnPawn) { + GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); + } + } + if (!class'NiceBulletAdapter'.static.ZedPenetration(charDamage, self, none, false, false)) { + charPenetrationCount += 1; + KillBullet(); + } +} + +function HandleHitZed(KFMonster targetZed, Vector hitLocation, Vector hitDirection, float headshotLevel) { + local bool bHitZedCalled; + + if (class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillDemoDirectApproach')) { + class'NiceBulletAdapter'.static.HitZed(self, niceRI, targetZed, hitLocation, hitDirection, headshotLevel); + if (bGenRegEffectOnPawn) { + GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); + } + bHitZedCalled = true; + } + + if (charExplodeOnPawnHit && !charIsDud && charMinExplosionDist <= 0.0) { + class'NiceBulletAdapter'.static.Explode(self, niceRI, hitLocation, targetZed); + GenerateImpactEffects(explosionImpact, hitLocation, hitDirection); + if (bShakeViewOnExplosion) { + ShakeView(hitLocation); + } + KillBullet(); + return; + } else { + if (!bHitZedCalled) { + class'NiceBulletAdapter'.static.HitZed( + self, + niceRI, + targetZed, + hitLocation, + hitDirection, + headshotLevel + ); + if (bGenRegEffectOnPawn) { + GenerateImpactEffects(regularImpact, hitLocation, hitDirection, false, false); + } + } + bHitZedCalled = true; + if (!bGhost && !bAlreadyHitZed) { + bAlreadyHitZed = true; + if (nicePlayer != none && niceRI != none) { + niceRI.ServerJunkieExtension(nicePlayer, headshotLevel > 0.0); + } + } + if (charIsSticky) { + Stick(targetZed, hitLocation); + } + } + if (!class'NiceBulletAdapter'.static.ZedPenetration( + charDamage, + self, + targetZed, + (headshotLevel > 0.0), + (headshotLevel > charDamageType.default.prReqPrecise) + ) + ) { + charPenetrationCount += 1; + KillBullet(); + } +} + +function HandleScream(Vector disintegrationLocation, Vector entryDirection) { + if (!charIsDud) { + GenerateImpactEffects(disintegrationImpact, disintegrationLocation, entryDirection); + } + class'NiceBulletAdapter'.static.HandleScream(self, niceRI, disintegrationLocation, entryDirection); +} + +function GenerateImpactEffects( + ImpactEffect effect, + Vector hitLocation, + Vector hitNormal, + optional bool bWallImpact, + optional bool bGenerateDecal +) { + local float actualCullDistance; + local float actualImpactShift; + local bool generatedEffect; + + // No need to play visuals on a server, for a dead bullets or in case there's no local player at all + if (Level.NetMode == NM_DedicatedServer || bBulletDead || localPlayer == none) { + return; + } + if (!localPlayer.CanSpawnEffect(bGhost) && !effect.bImportanEffect) { + return; + } + // -- Classic effect + if (effect.bPlayROEffect && !bBulletDead) { + Spawn(class'ROBulletHitEffect',,, hitLocation, rotator(-hitNormal)); + } + // -- Generate decal + if (bGenerateDecal && effect.decalClass != none) { + // Find appropriate cull distance for this decal + actualCullDistance = effect.decalClass.default.cullDistance; + // Double cull distance if local player is an instigator + if (instigator != none && localPlayer == instigator.Controller) { + actualCullDistance *= 2; // NICETODO: magic number + } + // Spawn decal + if (!localPlayer.BeyondViewDistance(hitLocation, actualCullDistance)) { + Spawn(effect.decalClass, self,, hitLocation, rotator(- hitNormal)); + generatedEffect = true; + } + } + // -- Generate custom effect + if (effect.emitterClass != none && EffectIsRelevant(hitLocation, false)) { + if (bWallImpact) { + actualImpactShift = effect.emitterShiftWall; + } else { + actualImpactShift = effect.emitterShiftPawn; + } + Spawn(effect.emitterClass,,, hitLocation - movementDirection * actualImpactShift, rotator(movementDirection)); + generatedEffect = true; + } + // -- Generate custom sound + if (effect.noise != none) { + class'NiceSoundCls'.default.effectSound = effect.noise; + class'NiceSoundCls'.default.effectVolume = effect.noiseVolume; + Spawn(class'NiceSoundCls',,, hitLocation); + generatedEffect = true; + } + if (generatedEffect) { + localPlayer.AddEffect(); + } +} + +function ShakeView(Vector hitLocation) { + local float distance, scale; + + if (nicePlayer == none || shakeRadiusMult < 0.0) { + return; + } + distance = VSize(hitLocation - nicePlayer.ViewTarget.Location); + if (distance < charExplosionRadius * shakeRadiusMult) { + if (distance < charExplosionRadius) { + scale = 1.0; + } else { + scale = (charExplosionRadius * ShakeRadiusMult - distance) / (charExplosionRadius); + } + nicePlayer.ShakeView( + shakeRotMag * scale, + shakeRotRate, + shakeRotTime, + shakeOffsetMag * scale, + shakeOffsetRate, + shakeOffsetTime + ); + } +} + +function KillBullet() { + local int i; + + if (bulletTrail != none) { + for (i = 0; i < bulletTrail.Emitters.Length; i ++) { + if (bulletTrail.Emitters[i] == none) { + continue; + } + bulletTrail.Emitters[i].ParticlesPerSecond = 0; + bulletTrail.Emitters[i].InitialParticlesPerSecond = 0; + bulletTrail.Emitters[i].RespawnDeadParticles = false; + } + bulletTrail.SetBase(none); + bulletTrail.AutoDestroy = true; + } + + if (bulletXTrail != none) { + bulletXTrail.mRegen = false; + bulletXTrail.LifeSpan = LifeSpan; + } + bBulletDead = true; + bHidden = true; + SoundVolume = 0; + LifeSpan = FMin(LifeSpan, 0.1); +} + +event Destroyed() { + KillBullet(); +} + +defaultproperties { + insideBouncesLeft=2 + trajUpdFreq=0.100000 + maxTraceCycles=128 + bDisableComplexMovement=True + trailXClass=Class'KFMod.KFTracer' + regularImpact=(bPlayROEffect=True) + StaticMeshRef="kf_generic_sm.Shotgun_Pellet" + DrawType=DT_StaticMesh + bAcceptsProjectors=False + LifeSpan=15.000000 + Texture=Texture'Engine.S_Camera' + bGameRelevant=True + bCanBeDamaged=True + SoundVolume=255 +} \ No newline at end of file From 3b5f46c2b5b5be568468f2ab1fa410baba7fa31a Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Sun, 9 Apr 2023 14:30:28 +0400 Subject: [PATCH 03/46] Optimize code flow --- sources/Weapons/NiceBullet.uc | 100 ++++++++++++++-------------------- 1 file changed, 41 insertions(+), 59 deletions(-) diff --git a/sources/Weapons/NiceBullet.uc b/sources/Weapons/NiceBullet.uc index d402fd7..8e03861 100644 --- a/sources/Weapons/NiceBullet.uc +++ b/sources/Weapons/NiceBullet.uc @@ -332,22 +332,15 @@ function Actor GetMainActor(Actor other) { return none; } - // Try owner - if ( - KFPawn(other) == none && - KFMonster(other) == none && - (KFPawn(other.owner) != none || KFMonster(other.owner) != none) - ) { - other = other.owner; - } - - // Try base - if ( - KFPawn(other) == none && - KFMonster(other) == none && - (KFPawn(other.base) != none || KFMonster(other.base) != none) - ) { - other = other.base; + if (!other.IsA('KFPawn') && !other.IsA('KFMonster')) { + // Try owner + if (other.owner.IsA('KFPawn') || other.owner.IsA('KFMonster')) { + return other.owner; + } + // Try base + if (other.base.IsA('KFPawn') || other.base.IsA('KFMonster')) { + return other.base; + } } return other; @@ -694,16 +687,19 @@ function DoProcessMovement(float delta) { } function Stick(Actor target, Vector hitLocation) { - local NiceMonster targetZed; - local name boneStick; - local float distToBone; - local float t; local Vector boneStrickOrig; local ExplosionData expData; + local Actor resultTarget; + local NiceMonster targetZed; + local name boneStick; + local float distToBone, t; if (bGhost) { return; } + expData.instigator = instigator; + expData.sourceWeapon = sourceWeapon; + expData.bulletClass = class; expData.explosionDamageType = charExplosionDamageType; expData.explosionDamage = charExplosionDamage; expData.explosionRadius = charExplosionRadius; @@ -712,31 +708,13 @@ function Stick(Actor target, Vector hitLocation) { expData.fuseTime = charFuseTime; expData.explodeOnFuse = charExplodeOnFuse; expData.affectedByScream = charAffectedByScream; - expData.sourceWeapon = sourceWeapon; - targetZed = NiceMonster(target); - if (targetZed == none) { - expData.bulletClass = class; - expData.instigator = instigator; - niceRI.ServerStickProjectile( - KFHumanPawn(instigator), - target, - 'None', - hitLocation - target.location, - Rotator(movementDirection), - expData - ); - class'NiceProjectileSpawner'.static.StickProjectile( - KFHumanPawn(instigator), - target, - 'None', - hitLocation - target.location, - Rotator(movementDirection), - expData - ); + if (!target.IsA('NiceMonster')) { + hitLocation -= target.location; + boneStick = 'None'; + resultTarget = target; } else { - expData.bulletClass = class; - expData.instigator = instigator; + targetZed = NiceMonster(target); boneStick = targetZed.GetClosestBone(hitLocation, movementDirection, distToBone); if (CheckHeadshot(targetZed, hitLocation, movementDirection) > 0.0) { boneStick = targetZed.HeadBone; @@ -751,23 +729,27 @@ function Stick(Actor target, Vector hitLocation) { t /= VSizeSquared(movementDirection); t *= 0.5; hitLocation = hitLocation + t * movementDirection; - niceRI.ServerStickProjectile( - KFHumanPawn(instigator), - targetZed, - boneStick, - hitLocation - boneStrickOrig, - Rotator(movementDirection), - expData - ); - class'NiceProjectileSpawner'.static.StickProjectile( - KFHumanPawn(instigator), - targetZed, - boneStick, - hitLocation - boneStrickOrig, - Rotator(movementDirection), - expData - ); + hitLocation -= boneStrickOrig; + resultTarget = targetZed; } + + niceRI.ServerStickProjectile( + KFHumanPawn(instigator), + resultTarget, + boneStick, + hitLocation, + Rotator(movementDirection), + expData + ); + class'NiceProjectileSpawner'.static.StickProjectile( + KFHumanPawn(instigator), + resultTarget, + boneStick, + hitLocation, + Rotator(movementDirection), + expData + ); + KillBullet(); } From 78ca66acddc10d64f32808bf2e39de1e3f70590b Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Sun, 9 Apr 2023 14:52:39 +0400 Subject: [PATCH 04/46] Apply new formatting for NiceBulletAdapter --- sources/Weapons/NiceBulletAdapter.uc | 386 ++++++++++++++++++--------- 1 file changed, 261 insertions(+), 125 deletions(-) diff --git a/sources/Weapons/NiceBulletAdapter.uc b/sources/Weapons/NiceBulletAdapter.uc index 1ab2f91..4234c72 100644 --- a/sources/Weapons/NiceBulletAdapter.uc +++ b/sources/Weapons/NiceBulletAdapter.uc @@ -9,57 +9,132 @@ // E-mail: dkanus@gmail.com //====================================================================================================================== class NiceBulletAdapter extends Object; -var const int BigZedMinHealth; // If zed's base Health >= this value, zed counts as Big -var const int MediumZedMinHealth; // If zed's base Health >= this value, zed counts as Medium-size -static function Explode(NiceBullet bullet, NiceReplicationInfo niceRI, Vector hitLocation, optional Actor explosionTarget){ - if(!bullet.bGhost){ - niceRI.ServerExplode(bullet.charExplosionDamage, bullet.charExplosionRadius, bullet.charExplosionExponent, - bullet.charExplosionDamageType, bullet.charExplosionMomentum, hitLocation, bullet.instigator, true, - explosionTarget, Vector(bullet.Rotation)); - if(KFMonster(bullet.base) != none && bullet.bStuck && bullet.bStuckToHead) - niceRI.ServerDealDamage(KFMonster(bullet.base), bullet.charExplosionDamage, bullet.instigator, hitLocation, - bullet.charExplosionMomentum * vect(0,0,-1), bullet.charExplosionDamageType, 1.0); + +var const int BigZedMinHealth; // If zed's base Health >= this value, zed counts as Big +var const int MediumZedMinHealth; // If zed's base Health >= this value, zed counts as Medium-size + +static function Explode( + NiceBullet bullet, + NiceReplicationInfo niceRI, + Vector hitLocation, + optional Actor explosionTarget +) { + if (!bullet.bGhost) { + niceRI.ServerExplode( + bullet.charExplosionDamage, + bullet.charExplosionRadius, + bullet.charExplosionExponent, + bullet.charExplosionDamageType, + bullet.charExplosionMomentum, + hitLocation, + bullet.instigator, + true, + explosionTarget, + Vector(bullet.Rotation) + ); + + if (KFMonster(bullet.base) != none && bullet.bStuck && bullet.bStuckToHead) { + niceRI.ServerDealDamage( + KFMonster(bullet.base), + bullet.charExplosionDamage, + bullet.instigator, + hitLocation, + bullet.charExplosionMomentum * vect(0, 0, -1), + bullet.charExplosionDamageType, + 1.0 + ); + } } } -static function HandleCalibration - ( - bool isHeadshot, - NiceHumanPawn nicePawn, - NiceMonster targetZed - ){ - if(nicePawn == none) return; - if(nicePawn.currentCalibrationState != CALSTATE_ACTIVE) return; + +static function HandleCalibration ( + bool isHeadshot, + NiceHumanPawn nicePawn, + NiceMonster targetZed +) { + if (nicePawn == none || nicePawn.currentCalibrationState != CALSTATE_ACTIVE) { + return; + } + nicePawn.ServerUpdateCalibration(isHeadshot, targetZed); } -static function HitWall(NiceBullet bullet, NiceReplicationInfo niceRI, Actor targetWall, - Vector hitLocation, Vector hitNormal){ + +static function HitWall( + NiceBullet bullet, + NiceReplicationInfo niceRI, + Actor targetWall, + Vector hitLocation, + Vector hitNormal +) { local NicePlayerController nicePlayer; + nicePlayer = NicePlayerController(bullet.Instigator.Controller); - if(nicePlayer == none) - return; - if(!bullet.bAlreadyHitZed) - HandleCalibration(false, NiceHumanPawn(bullet.Instigator), none); - if(!targetWall.bStatic && !targetWall.bWorldGeometry && nicePlayer != none && (nicePlayer.wallHitsLeft > 0 || Projectile(targetWall) != none)){ - niceRI.ServerDealDamage(targetWall, bullet.charOrigDamage, bullet.Instigator, hitLocation, - bullet.charMomentumTransfer * hitNormal, bullet.charDamageType); - nicePlayer.wallHitsLeft --; + if (nicePlayer == none) { + return; + } + if (!bullet.bAlreadyHitZed) { + HandleCalibration(false, NiceHumanPawn(bullet.Instigator), none); + } + if ( + !targetWall.bStatic && + !targetWall.bWorldGeometry && + nicePlayer != none && + (nicePlayer.wallHitsLeft > 0 || Projectile(targetWall) != none) + ) { + niceRI.ServerDealDamage( + targetWall, + bullet.charOrigDamage, + bullet.Instigator, + hitLocation, + bullet.charMomentumTransfer * hitNormal, + bullet.charDamageType + ); + nicePlayer.wallHitsLeft --; } } -static function HandleScream(NiceBullet bullet, NiceReplicationInfo niceRI, Vector location, Vector entryDirection){ + +static function HandleScream( + NiceBullet bullet, + NiceReplicationInfo niceRI, + Vector location, + Vector entryDirection +) { bullet.charIsDud = true; } -static function HitPawn(NiceBullet bullet, NiceReplicationInfo niceRI, KFPawn targetPawn, Vector hitLocation, - Vector hitNormal, array hitPoints){ + +static function HitPawn( + NiceBullet bullet, + NiceReplicationInfo niceRI, + KFPawn targetPawn, + Vector hitLocation, + Vector hitNormal, + array hitPoints +) { local NiceMedicProjectile niceDart; + niceDart = NiceMedicProjectile(bullet); - if(niceDart == none) - niceRI.ServerDealDamage(targetPawn, bullet.charDamage, bullet.instigator, HitLocation, - hitNormal * bullet.charMomentumTransfer, bullet.charDamageType); - else - niceRI.ServerHealTarget(NiceHumanPawn(targetPawn), bullet.charDamage, bullet.instigator); + if (niceDart == none) { + niceRI.ServerDealDamage( + targetPawn, + bullet.charDamage, + bullet.instigator, + HitLocation, + hitNormal * bullet.charMomentumTransfer, + bullet.charDamageType + ); + } else { + niceRI.ServerHealTarget(NiceHumanPawn(targetPawn), bullet.charDamage, bullet.instigator); + } } -static function HitZed(NiceBullet bullet, NiceReplicationInfo niceRI, KFMonster kfZed, Vector hitLocation, - Vector hitNormal, float headshotLevel){ + +static function HitZed( + NiceBullet bullet, + NiceReplicationInfo niceRI, + KFMonster kfZed, + Vector hitLocation, + Vector hitNormal, + float headshotLevel +) { local bool bIsHeadshot, bIsPreciseHeadshot; local float actualDamage; local int lockonTicks; @@ -68,74 +143,113 @@ static function HitZed(NiceBullet bullet, NiceReplicationInfo niceRI, KFMonster local NiceHumanPawn nicePawn; local NicePlayerController nicePlayer; local class niceVet; + nicePlayer = NicePlayerController(bullet.Instigator.Controller); - if ( nicePlayer != none && nicePlayer.abilityManager != none - && nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillEnforcerBruteA'.default.abilityID)) { + if ( + nicePlayer != none && + nicePlayer.abilityManager != none && + nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillEnforcerBruteA'.default.abilityID) + ) { headshotLevel = 0.0; } bIsHeadshot = (headshotLevel > 0.0); bIsPreciseHeadshot = (headshotLevel > bullet.charDamageType.default.prReqPrecise); - if(!bullet.bAlreadyHitZed || bIsHeadshot) - HandleCalibration(bIsHeadshot, NiceHumanPawn(bullet.Instigator), NiceMonster(kfZed)); - if(bIsHeadshot && bullet.sourceWeapon != none) - bullet.sourceWeapon.lastHeadshotTime = bullet.Level.TimeSeconds; - if(nicePlayer == none) - return; - nicePawn = NiceHumanPawn(bullet.instigator); - if( !bIsHeadshot - && nicePawn != none - && nicePlayer.abilityManager != none - && nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillSharpshooterReaperA'.default.abilityID)) - nicePawn.ServerCooldownAbility(class'NiceSkillSharpshooterReaperA'.default.abilityID); - niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); - if(bullet.charCausePain) - actualDamage = bullet.charOrigDamage; - else - actualDamage = bullet.charDamage; - if(headshotLevel > 0) - actualDamage *= bullet.charContiniousBonus; - if(bullet.bGrazing) - actualDamage *= class'NiceSkillSupportGraze'.default.grazeDamageMult; - bullet.bGrazing = false; - if(kfZed == bullet.lockonZed && bullet.lockonTime > bullet.sourceWeapon.stdFireRate - && niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterKillConfirmed')){ - lockOnTickRate =class'NiceSkillSharpshooterKillConfirmed'.default.stackDelay; - lockonTicks = Ceil(bullet.lockonTime / lockOnTickRate) - 1; - lockonTicks = Min(class'NiceSkillSharpshooterKillConfirmed'.default.maxStacks, lockonTicks); - //actualDamage *= 1.0 + - // 0.5 * lockonTicks * (lockonTicks + 1) * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; - //damageMod *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; - actualDamage *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; + if (!bullet.bAlreadyHitZed || bIsHeadshot) { + HandleCalibration(bIsHeadshot, NiceHumanPawn(bullet.Instigator), NiceMonster(kfZed)); + } + if (bIsHeadshot && bullet.sourceWeapon != none) { + bullet.sourceWeapon.lastHeadshotTime = bullet.Level.TimeSeconds; + } + if (nicePlayer == none) { + return; + } + nicePawn = NiceHumanPawn(bullet.instigator); + if ( + !bIsHeadshot && + nicePawn != none && + nicePlayer.abilityManager != none && + nicePlayer.abilityManager.IsAbilityActive(class'NiceSkillSharpshooterReaperA'.default.abilityID) + ) { + nicePawn.ServerCooldownAbility(class'NiceSkillSharpshooterReaperA'.default.abilityID); + } + niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); + if (bullet.charCausePain) { + actualDamage = bullet.charOrigDamage; + } else { + actualDamage = bullet.charDamage; + } + if (headshotLevel > 0) { + actualDamage *= bullet.charContiniousBonus; + } + if (bullet.bGrazing) { + actualDamage *= class'NiceSkillSupportGraze'.default.grazeDamageMult; + } + bullet.bGrazing = false; + if ( + kfZed == bullet.lockonZed && + bullet.lockonTime > bullet.sourceWeapon.stdFireRate && + niceVet != none && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterKillConfirmed') + ) { + lockOnTickRate =class'NiceSkillSharpshooterKillConfirmed'.default.stackDelay; + lockonTicks = Ceil(bullet.lockonTime / lockOnTickRate) - 1; + lockonTicks = Min(class'NiceSkillSharpshooterKillConfirmed'.default.maxStacks, lockonTicks); + // actualDamage *= 1.0 + + // 0.5 * lockonTicks * (lockonTicks + 1) * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; + // damageMod *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; + actualDamage *= 1.0 + lockonTicks * class'NiceSkillSharpshooterKillConfirmed'.default.damageBonus; + } + if (!bullet.bGhost) { + niceRI.ServerDealDamage( + kfZed, + actualDamage, + bullet.instigator, + hitLocation, + bullet.charMomentumTransfer * hitNormal, + bullet.charDamageType, + headshotLevel, + bullet.lockonTime + ); } - if(!bullet.bGhost) - niceRI.ServerDealDamage(kfZed, actualDamage, bullet.instigator, hitLocation, - bullet.charMomentumTransfer * hitNormal, bullet.charDamageType, headshotLevel, bullet.lockonTime); //// Handle angled shots angle = asin(hitNormal.Z); // Apply angled shots - if((angle > 0.8 || angle < -0.45) && bullet.bCanAngleDamage && kfZed != none){ - bullet.bCanAngleDamage = false; - bullet.bAlreadyHitZed = true; - if(ZedPenetration(bullet.charDamage, bullet, kfZed, bIsHeadshot, bIsPreciseHeadshot)) - HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel); + if ((angle > 0.8 || angle < -0.45) && bullet.bCanAngleDamage && kfZed != none) { + bullet.bCanAngleDamage = false; + bullet.bAlreadyHitZed = true; + if (ZedPenetration(bullet.charDamage, bullet, kfZed, bIsHeadshot, bIsPreciseHeadshot)) { + HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel); + } } //// 'Bore' support skill - if( niceVet != none && nicePlayer.IsZedTimeActive() && bullet.insideBouncesLeft > 0 - && niceVet.static.hasSkill(nicePlayer, class'NiceSkillSupportZEDBore')){ - // Count one bounce - bullet.insideBouncesLeft --; - // Swap head-shot level - if(headshotLevel <= 0.0) - headshotLevel = class'NiceSkillSupportZEDBore'.default.minHeadshotPrecision; - else - headshotLevel = -headshotLevel; - // Deal next batch of damage - ZedPenetration(bullet.charDamage, bullet, kfZed, false, false); - HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel); + if ( + niceVet != none && + nicePlayer.IsZedTimeActive() && + bullet.insideBouncesLeft > 0 && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillSupportZEDBore') + ) { + // Count one bounce + bullet.insideBouncesLeft --; + // Swap head-shot level + if (headshotLevel <= 0.0) { + headshotLevel = class'NiceSkillSupportZEDBore'.default.minHeadshotPrecision; + } else { + headshotLevel = -headshotLevel; + } + // Deal next batch of damage + ZedPenetration(bullet.charDamage, bullet, kfZed, false, false); + HitZed(bullet, niceRI, kfZed, hitLocation, hitNormal, headshotLevel); } bullet.insideBouncesLeft = 2; } -static function bool ZedPenetration(out float Damage, NiceBullet bullet, KFMonster targetZed, bool bIsHeadshot, bool bIsPreciseHeadshot){ + +static function bool ZedPenetration( + out float Damage, + NiceBullet bullet, + KFMonster targetZed, + bool bIsHeadshot, + bool bIsPreciseHeadshot +) { local float reductionMod; local NiceMonster niceZed; local NicePlayerController nicePlayer; @@ -144,52 +258,74 @@ static function bool ZedPenetration(out float Damage, NiceBullet bullet, KFMonst local class niceDmgType; // True if we can penetrate even body, but now penetrating a head and shouldn't reduce damage too much local bool bEasyHeadPenetration; + // Init variables niceZed = NiceMonster(targetZed); nicePlayer = NicePlayerController(bullet.Instigator.Controller); niceVet = none; - if(nicePlayer != none) - niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); + if (nicePlayer != none) { + niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); + } niceDmgType = bullet.charDamageType; bEasyHeadPenetration = bIsHeadshot && !niceDmgType.default.bPenetrationHSOnly; reductionMod = 1.0f; // Apply zed reduction and perk reduction of reduction` - if(niceZed != none){ - // Railgun skill exception - if(niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterZEDRailgun') && nicePlayer.IsZedTimeActive()) - return true; - if(niceZed.default.Health >= default.BigZedMinHealth && !bEasyHeadPenetration) - reductionMod *= niceDmgType.default.BigZedPenDmgReduction; - else if(niceZed.default.Health >= default.MediumZedMinHealth && !bEasyHeadPenetration) - reductionMod *= niceDmgType.default.MediumZedPenDmgReduction; - } - else + if (niceZed != none) { + // Railgun skill exception + if ( + niceVet != none && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterZEDRailgun') && + nicePlayer.IsZedTimeActive() + ) { + return true; + } + if (niceZed.default.Health >= default.BigZedMinHealth && !bEasyHeadPenetration) { + reductionMod *= niceDmgType.default.BigZedPenDmgReduction; + } else if (niceZed.default.Health >= default.MediumZedMinHealth && !bEasyHeadPenetration) { + reductionMod *= niceDmgType.default.MediumZedPenDmgReduction; + } + } else { reductionMod *= niceDmgType.default.BigZedPenDmgReduction; - if(niceVet != none) - reductionMod = niceVet.static.GetPenetrationDamageMulti(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo), reductionMod, niceDmgType); - actualMaxPenetrations = niceDmgType.default.maxPenetrations; - if(niceVet != none && !bullet.charWasHipFired && niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterSurgical') && bIsHeadshot){ - actualMaxPenetrations += 1; - reductionMod = FMax(reductionMod, class'NiceSkillSharpshooterSurgical'.default.penDmgReduction); - } + } + if (niceVet != none) { + reductionMod = niceVet.static.GetPenetrationDamageMulti( + KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo), + reductionMod, + niceDmgType + ); + } + actualMaxPenetrations = niceDmgType.default.maxPenetrations; + if ( + niceVet != none && + !bullet.charWasHipFired && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillSharpshooterSurgical') && + bIsHeadshot + ) { + actualMaxPenetrations += 1; + reductionMod = FMax(reductionMod, class'NiceSkillSharpshooterSurgical'.default.penDmgReduction); + } // Assign new damage value and tell us if we should stop with penetration Damage *= reductionMod * niceDmgType.default.PenDmgReduction; bullet.decapMod *= reductionMod * niceDmgType.default.PenDecapReduction; bullet.incapMod *= reductionMod * niceDmgType.default.PenIncapReduction; - if(niceVet != none && actualMaxPenetrations >= 0) - actualMaxPenetrations += - niceVet.static.GetAdditionalPenetrationAmount(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); - if(!bIsHeadshot && niceDmgType.default.bPenetrationHSOnly) - return false; - if(actualMaxPenetrations < 0) - return true; - if(Damage / bullet.charOrigDamage < (niceDmgType.default.PenDmgReduction ** (actualMaxPenetrations + 1)) + 0.0001 || Damage < 1) - return false; + if (niceVet != none && actualMaxPenetrations >= 0) { + actualMaxPenetrations += + niceVet.static.GetAdditionalPenetrationAmount(KFPlayerReplicationInfo(nicePlayer.PlayerReplicationInfo)); + } + if (!bIsHeadshot && niceDmgType.default.bPenetrationHSOnly) { + return false; + } + if (actualMaxPenetrations < 0) { + return true; + } + if (Damage / bullet.charOrigDamage < (niceDmgType.default.PenDmgReduction ** (actualMaxPenetrations + 1)) + 0.0001 || Damage < 1) { + return false; + } + return true; } -defaultproperties -{ - BigZedMinHealth=1000 - MediumZedMinHealth=500 -} +defaultproperties { + BigZedMinHealth=1000 + MediumZedMinHealth=500 +} \ No newline at end of file From bf53b53b31fd906893306cd96633ba94a938fb74 Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Sun, 9 Apr 2023 15:15:00 +0400 Subject: [PATCH 05/46] Apply new formatting for NiceProjectileSpawner --- sources/Weapons/NiceProjectileSpawner.uc | 282 +++++++++++++++-------- 1 file changed, 192 insertions(+), 90 deletions(-) diff --git a/sources/Weapons/NiceProjectileSpawner.uc b/sources/Weapons/NiceProjectileSpawner.uc index 05dd281..5334af4 100644 --- a/sources/Weapons/NiceProjectileSpawner.uc +++ b/sources/Weapons/NiceProjectileSpawner.uc @@ -1,76 +1,160 @@ class NiceProjectileSpawner extends Actor dependson(NiceBullet); + // NICETODO: use flags correctly -static function MakeProjectile(Vector start, Rotator dir, NiceFire.ShotType shotParams, NiceFire.FireModeContext fireContext, optional bool bForceComplexTraj, - optional bool bDuplReal, optional bool bSkipGhosts){ +static function MakeProjectile( + Vector start, + Rotator dir, + NiceFire.ShotType shotParams, + NiceFire.FireModeContext fireContext, + optional bool bForceComplexTraj, + optional bool bDuplReal, + optional bool bSkipGhosts +) { local int i; local NicePack niceMut; + niceMut = class'NicePack'.static.Myself(fireContext.Instigator.Level); - if(niceMut == none) - return; - if(fireContext.Instigator.Role < ROLE_Authority || bDuplReal) - SpawnProjectile(Start, Dir, shotParams, fireContext, false, bForceComplexTraj); - if(fireContext.Instigator.Role == ROLE_Authority && niceMut != none && !bSkipGhosts){ - for(i = 0;i < niceMut.playersList.Length;i ++){ - if(niceMut.playersList[i] != fireContext.Instigator.Controller) - niceMut.playersList[i].ClientSpawnGhostProjectile(start, dir.pitch, dir.yaw, dir.roll, shotParams, fireContext, bForceComplexTraj); - } + if (niceMut == none) { + return; + } + if (fireContext.Instigator.Role < ROLE_Authority || bDuplReal) { + SpawnProjectile(Start, Dir, shotParams, fireContext, false, bForceComplexTraj); + } + if (fireContext.Instigator.Role == ROLE_Authority && niceMut != none && !bSkipGhosts) { + for (i = 0; i < niceMut.playersList.Length; i++) { + if (niceMut.playersList[i] != fireContext.Instigator.Controller) { + niceMut.playersList[i].ClientSpawnGhostProjectile( + start, + dir.pitch, + dir.yaw, + dir.roll, + shotParams, + fireContext, + bForceComplexTraj + ); + } + } } } -static function StickProjectile(KFHumanPawn instigator, Actor base, name bone, Vector shift, Rotator direction, - NiceBullet.ExplosionData expData, optional bool bDuplReal, optional bool bSkipGhosts){ + +static function StickProjectile( + KFHumanPawn instigator, + Actor base, + name bone, + Vector shift, + Rotator direction, + NiceBullet.ExplosionData expData, + optional bool bDuplReal, + optional bool bSkipGhosts +) { local int i; local NicePack niceMut; + niceMut = class'NicePack'.static.Myself(expData.Instigator.Level); - if(niceMut == none) - return; + if (niceMut == none) { + return; + } niceMut.stuckCounter ++; - if(expData.Instigator.Role < ROLE_Authority) - SpawnStuckProjectile(instigator, base, bone, shift, direction, expData, false, niceMut.stuckCounter); - if(expData.Instigator.Role == ROLE_Authority && niceMut != none){ - for(i = 0;i < niceMut.playersList.Length;i ++){ - if( (niceMut.playersList[i] != expData.Instigator.Controller && !bSkipGhosts) - || (niceMut.playersList[i] == expData.Instigator.Controller && bDuplReal) ) - niceMut.playersList[i].ClientStickGhostProjectile(instigator, base, bone, shift, direction, expData, - niceMut.stuckCounter); - } + if (expData.Instigator.Role < ROLE_Authority) { + SpawnStuckProjectile( + instigator, + base, + bone, + shift, + direction, + expData, + false, + niceMut.stuckCounter + ); + } + if (expData.Instigator.Role == ROLE_Authority && niceMut != none) { + for (i = 0; i < niceMut.playersList.Length; i++) { + if ( + (niceMut.playersList[i] != expData.Instigator.Controller && !bSkipGhosts) || + (niceMut.playersList[i] == expData.Instigator.Controller && bDuplReal) + ) { + niceMut.playersList[i].ClientStickGhostProjectile( + instigator, + base, + bone, + shift, + direction, + expData, + niceMut.stuckCounter + ); + } + } } } -static function NiceBullet SpawnProjectile(Vector Start, Rotator Dir, NiceFire.ShotType shotParams, NiceFire.FireModeContext fireContext, optional bool bIsGhost, optional bool bForceComplexTraj){ + +static function NiceBullet SpawnProjectile( + Vector Start, + Rotator Dir, + NiceFire.ShotType shotParams, + NiceFire.FireModeContext fireContext, + optional bool bIsGhost, + optional bool bForceComplexTraj +) { local Actor other; local NiceBullet niceProj; local Vector HitLocation, HitNormal; local NicePlayerController nicePlayer; local class niceVet; + // No class - no projectile - if(shotParams.bulletClass == none) - return none; + if (shotParams.bulletClass == none) { + return none; + } // Try to spawn - if(fireContext.Instigator != none) - niceProj = fireContext.Instigator.Spawn(shotParams.bulletClass,,, Start, Dir); + if (fireContext.Instigator != none) { + niceProj = fireContext.Instigator.Spawn(shotParams.bulletClass,,, Start, Dir); + } // Try harder - if(niceProj == none && fireContext.Instigator != none){ - other = fireContext.Instigator.Trace(HitLocation, HitNormal, Start, fireContext.Instigator.Location + fireContext.Instigator.EyePosition(), false, Vect(0,0,1)); - if(other != none) - Start = HitLocation; - niceProj = fireContext.Instigator.Spawn(shotParams.bulletClass,,, Start, Dir); + if (niceProj == none && fireContext.Instigator != none) { + other = fireContext.Instigator.Trace( + HitLocation, + HitNormal, + Start, + fireContext.Instigator.Location + fireContext.Instigator.EyePosition(), + false, + Vect(0, 0, 1) + ); + if (other != none) { + Start = HitLocation; + } + niceProj = fireContext.Instigator.Spawn(shotParams.bulletClass,,, Start, Dir); } // Give up if failed after these two attempts - if(niceProj == none) - return none; + if (niceProj == none) { + return none; + } niceProj.Renew(); // Initialize projectile - if(fireContext.Instigator != none) - nicePlayer = NicePlayerController(fireContext.Instigator.Controller); - if(nicePlayer != none) - niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePlayer.PlayerReplicationInfo); + if (fireContext.Instigator != none) { + nicePlayer = NicePlayerController(fireContext.Instigator.Controller); + } + if (nicePlayer != none) { + niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(nicePlayer.PlayerReplicationInfo); + } niceProj.bGhost = bIsGhost; // Fill-up data about what damage should projectile deal niceProj.charDamage = shotParams.damage; - if(niceVet != none && fireContext.bIsBursting && niceVet.static.hasSkill(nicePlayer, class'NiceSkillCommandoExplosivePower')) + if ( + niceVet != none && + fireContext.bIsBursting && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillCommandoExplosivePower') + ) { niceProj.charDamage *= class'NiceSkillCommandoExplosivePower'.default.dmgMod; - if(niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillSupportZEDBulletStorm') && nicePlayer.IsZedTimeActive()) + } + if ( + niceVet != none && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillSupportZEDBulletStorm') && + nicePlayer.IsZedTimeActive() + ) { niceProj.charDamage = shotParams.damage * class'NiceSkillSupportZEDBulletStorm'.default.damageCut; + } + niceProj.charOrigDamage = niceProj.charDamage; niceProj.charDamageType = shotParams.shotDamageType; niceProj.charExplosionDamageType = shotParams.explosionDamageType; @@ -92,76 +176,94 @@ static function NiceBullet SpawnProjectile(Vector Start, Rotator Dir, NiceFire.S niceProj.charContiniousBonus = fireContext.continiousBonus; // Fill-up data about at what speed should projectile travel niceProj.movementSpeed = shotParams.projSpeed; - if(niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoOnperk')) + if (niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoOnperk')) { niceProj.movementSpeed *= class'NiceSkillDemoOnperk'.default.speedBonus; + } niceProj.movementDirection = Vector(niceProj.rotation); niceProj.charAffectedByScream = shotParams.projAffectedByScream; niceProj.charIsSticky = shotParams.bShouldStick; niceProj.nicePlayer = nicePlayer; - if(niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoVolatile')){ + if (niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoVolatile')) { niceProj.charExplosionRadius *= class'NiceSkillDemoVolatile'.default.explRangeMult; niceProj.charExplosionExponent *= class'NiceSkillDemoVolatile'.default.falloffMult; niceProj.charMinExplosionDist *= class'NiceSkillDemoVolatile'.default.safeDistanceMult; } - if(niceVet != none && niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoZEDFullBlast') && nicePlayer.IsZedTimeActive()){ - niceProj.charExplosionRadius *= class'NiceSkillDemoZEDFullBlast'.default.explRadiusMult; - niceProj.charExplosionExponent = 0.0; + if ( + niceVet != none && + niceVet.static.hasSkill(nicePlayer, class'NiceSkillDemoZEDFullBlast') && + nicePlayer.IsZedTimeActive() + ) { + niceProj.charExplosionRadius *= class'NiceSkillDemoZEDFullBlast'.default.explRadiusMult; + niceProj.charExplosionExponent = 0.0; + } + if (bForceComplexTraj) { + niceProj.bDisableComplexMovement = false; + } + if (niceProj.Instigator != none && NicePlayerController(niceProj.Instigator.Controller) != none) { + niceProj.niceRI = NicePlayerController(niceProj.Instigator.Controller).NiceRI; } - if(bForceComplexTraj) - niceProj.bDisableComplexMovement = false; - if(niceProj.Instigator != none && NicePlayerController(niceProj.Instigator.Controller) != none) - niceProj.niceRI = NicePlayerController(niceProj.Instigator.Controller).NiceRI; // And some leftovers //niceProj.bShouldBounce = shotParams.bShouldBounce; niceProj.bInitFinished = true; + return niceProj; } -static function SpawnStuckProjectile(KFHumanPawn instigator, Actor base, name bone, Vector shift, Rotator direction, - NiceBullet.ExplosionData expData, bool bIsGhost, int stuckID){ - local Pawn justPawn; - local NiceFire.ShotType shotParams; - local NiceFire.FireModeContext fireContext; - local NiceBullet spawnedBullet; - local NicePlayerController nicePlayer; + +static function SpawnStuckProjectile( + KFHumanPawn instigator, + Actor base, + name bone, + Vector shift, + Rotator direction, + NiceBullet.ExplosionData expData, + bool bIsGhost, + int stuckID +) { + local Pawn justPawn; + local NiceFire.ShotType shotParams; + local NiceFire.FireModeContext fireContext; + local NiceBullet spawnedBullet; + local NicePlayerController nicePlayer; + nicePlayer = NicePlayerController(instigator.Controller); - if(base == none || nicePlayer == none) - return; + if (base == none || nicePlayer == none) { + return; + } justPawn = Pawn(base); - fireContext.instigator = NiceHumanPawn(instigator); - fireContext.sourceWeapon = expData.sourceWeapon; - shotParams.bulletClass = expData.bulletClass; - shotParams.explosionDamageType = expData.explosionDamageType; - shotParams.explosionDamage = expData.explosionDamage; - shotParams.explosionRadius = expData.explosionRadius; - shotParams.explosionExponent = expData.explosionExponent; - shotParams.explosionMomentum = expData.explosionMomentum; - shotParams.fuseTime = expData.fuseTime; - shotParams.explodeOnFuse = expData.explodeOnFuse; + fireContext.instigator = NiceHumanPawn(instigator); + fireContext.sourceWeapon = expData.sourceWeapon; + shotParams.bulletClass = expData.bulletClass; + shotParams.explosionDamageType = expData.explosionDamageType; + shotParams.explosionDamage = expData.explosionDamage; + shotParams.explosionRadius = expData.explosionRadius; + shotParams.explosionExponent = expData.explosionExponent; + shotParams.explosionMomentum = expData.explosionMomentum; + shotParams.fuseTime = expData.fuseTime; + shotParams.explodeOnFuse = expData.explodeOnFuse; shotParams.projAffectedByScream = expData.affectedByScream; spawnedBullet = SpawnProjectile(base.location, direction, shotParams, fireContext, bIsGhost); - if(spawnedBullet == none) - return; + if (spawnedBullet == none) { + return; + } spawnedBullet.stuckID = stuckID; spawnedBullet.bStuck = true; nicePlayer.RegisterStuckBullet(spawnedBullet); - if(justPawn != none){ - spawnedBullet.bStuckToHead = expData.stuckToHead; - spawnedBullet.SetBase(base); - justPawn.AttachToBone(spawnedBullet, bone); - spawnedBullet.SetRelativeLocation(shift); - spawnedBullet.SetRelativeRotation(Rotator(Vector(direction) << justPawn.GetBoneRotation(bone, 0))); - spawnedBullet.bUseBone = true; - spawnedBullet.stuckBone = bone; - } - else{ - spawnedBullet.SetBase(base); - spawnedBullet.SetRelativeLocation(shift); + if (justPawn != none) { + spawnedBullet.bStuckToHead = expData.stuckToHead; + spawnedBullet.SetBase(base); + justPawn.AttachToBone(spawnedBullet, bone); + spawnedBullet.SetRelativeLocation(shift); + spawnedBullet.SetRelativeRotation(Rotator(Vector(direction) << justPawn.GetBoneRotation(bone, 0))); + spawnedBullet.bUseBone = true; + spawnedBullet.stuckBone = bone; + } else { + spawnedBullet.SetBase(base); + spawnedBullet.SetRelativeLocation(shift); } } -defaultproperties -{ - bHidden=True - RemoteRole=ROLE_SimulatedProxy - LifeSpan=1.000000 -} +defaultproperties { + bHidden=True + RemoteRole=ROLE_SimulatedProxy + LifeSpan=1.000000 +} \ No newline at end of file From f331df23c523ae47ae1affed1a14bd4332745097 Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Mon, 22 May 2023 01:14:18 +0400 Subject: [PATCH 06/46] Add missing variables for playercontroller reset --- sources/NicePlayerController.uc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sources/NicePlayerController.uc b/sources/NicePlayerController.uc index dabd3d0..ccd38a9 100644 --- a/sources/NicePlayerController.uc +++ b/sources/NicePlayerController.uc @@ -212,6 +212,20 @@ simulated function ClientPostLogin(){ // Change HUD parameters class'ScrnHUD'.default.EnemyHealthBarHeight = 4.0; } + +// fix crooked camera after you die with active `ViewShake` +function StopViewShaking() { + ShakeRotMax = vect(0, 0, 0); + ShakeRotRate = vect(0, 0, 0); + ShakeRotTime = vect(0, 0, 0); + ShakeOffsetMax = vect(0, 0, 0); + ShakeOffsetRate = vect(0, 0, 0); + ShakeOffsetTime = vect(0, 0, 0); + // add missing variables + ShakeOffset = vect(0, 0, 0); + ShakeRot = Rot(0, 0, 0); +} + function ShowLobbyMenu(){ Super.ShowLobbyMenu(); } @@ -1225,7 +1239,7 @@ function LoadDualWieldables(){ local class WP; local class W; local int i; - + CPRL = class'ClientPerkRepLink'.Static.FindStats(self); if(CPRL == none || CPRL.ShopInventory.Length == 0) return; From 989bfc779274321c6b85109cecc5555303816ea6 Mon Sep 17 00:00:00 2001 From: Shtoyan Date: Mon, 22 May 2023 02:00:56 +0400 Subject: [PATCH 07/46] New NiceBloatVomit Limit how many times single projectile can damage zeds --- sources/Zeds/Nice/NiceBloatVomit.uc | 30 ++++++++++++++++++++++++++++ sources/Zeds/Nice/NiceZombieBloat.uc | 9 +++++---- 2 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 sources/Zeds/Nice/NiceBloatVomit.uc diff --git a/sources/Zeds/Nice/NiceBloatVomit.uc b/sources/Zeds/Nice/NiceBloatVomit.uc new file mode 100644 index 0000000..7f3d37c --- /dev/null +++ b/sources/Zeds/Nice/NiceBloatVomit.uc @@ -0,0 +1,30 @@ +class NiceBloatVomit extends KFBloatVomit; + +// limit how much you can damage zeds +const DAMAGECOUNT=10; +var private transient int DamageTicked; + +auto state Flying { + simulated function ProcessTouch(Actor Other, Vector HitLocation) { + // add damage limit + if (DamageTicked >= DAMAGECOUNT) { + BlowUp(HitLocation); + return; + } + if (ExtendedZCollision(Other) != none) { + return; + } + if ( + Other != Instigator && + (Other.IsA('Pawn') || Other.IsA('DestroyableObjective') || Other.bProjTarget) + ) { + DamageTicked += 1; + // warn("DamageTicked: " $ DamageTicked); + // use server DelayedHurtRadius() instead? + HurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation); + } + else if (Other != Instigator && Other.bBlockActors) { + HitWall(Normal(HitLocation - Location), Other); + } + } +} \ No newline at end of file diff --git a/sources/Zeds/Nice/NiceZombieBloat.uc b/sources/Zeds/Nice/NiceZombieBloat.uc index c3ab99b..459e04e 100644 --- a/sources/Zeds/Nice/NiceZombieBloat.uc +++ b/sources/Zeds/Nice/NiceZombieBloat.uc @@ -173,7 +173,8 @@ function SpawnTwoShots() if ( !SavedFireProperties.bInitialized ) { SavedFireProperties.AmmoClass = Class'SkaarjAmmo'; - SavedFireProperties.ProjectileClass = Class'KFBloatVomit'; + // use fixed bile class, to prevent super high damage to zeds + SavedFireProperties.ProjectileClass = Class'NiceBloatVomit'; SavedFireProperties.WarnTargetPct = 1; SavedFireProperties.MaxRange = 500; SavedFireProperties.bTossed = False; @@ -185,13 +186,13 @@ function SpawnTwoShots() // Turn off extra collision before spawning vomit, otherwise spawn fails ToggleAuxCollision(false); FireRotation = Controller.AdjustAim(SavedFireProperties,FireStart,600); - Spawn(Class'KFBloatVomit',,,FireStart,FireRotation); + Spawn(SavedFireProperties.ProjectileClass,,,FireStart,FireRotation); FireStart-=(0.5*CollisionRadius*Y); FireRotation.Yaw -= 1200; - spawn(Class'KFBloatVomit',,,FireStart, FireRotation); + spawn(SavedFireProperties.ProjectileClass,,,FireStart, FireRotation); FireStart+=(CollisionRadius*Y); FireRotation.Yaw += 2400; - spawn(Class'KFBloatVomit',,,FireStart, FireRotation); + spawn(SavedFireProperties.ProjectileClass,,,FireStart, FireRotation); // Turn extra collision back on ToggleAuxCollision(true); } From 796b69982532f1f10d02b91358433d7d209ac38a Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:07:57 +0700 Subject: [PATCH 08/46] Add dynamic spread mechanic --- sources/Weapons/NiceFire.uc | 43 ++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/sources/Weapons/NiceFire.uc b/sources/Weapons/NiceFire.uc index a752d16..bc253e4 100644 --- a/sources/Weapons/NiceFire.uc +++ b/sources/Weapons/NiceFire.uc @@ -38,6 +38,10 @@ var bool projAffectedByScream; var bool bShouldStick; var int resetTicks; var float niceNextFireTime; +var float minimalSpreadScale; +var float activeSpreadScale; +var float spreadGainedPerShot; +var float spreadLostPerSecond; struct FireModeContext{ var bool bHipfire; var NiceWeapon sourceWeapon; @@ -152,9 +156,15 @@ simulated function int GetBurstLength(){ } return currentContext.burstLength; } + simulated function ModeTick(float delta){ local float headLevel; local NiceMonster currTarget; + if (spreadLostPerSecond > 0 && activeSpreadScale > minimalSpreadScale + && niceNextFireTime + fireRate <= Level.TimeSeconds) { + activeSpreadScale -= spreadLostPerSecond * delta; + activeSpreadScale = FMax(minimalSpreadScale, activeSpreadScale); + } if(currentContext.Instigator == none) currentContext.Instigator = NiceHumanPawn(Instigator); if(currentContext.sourceWeapon == none) @@ -548,7 +558,7 @@ function DoFireEffect(){ if(!Weapon.WeaponCentered() && !KFWeap.bAimingRifle) StartProj = StartProj + Weapon.Hand * Y * ProjSpawnOffset.Y + Z * ProjSpawnOffset.Z; other = Weapon.Trace(HitLocation, HitNormal, StartProj, StartTrace, false); - activeSpread = fireShots[currentShot].spread; + activeSpread = fireShots[currentShot].spread * activeSpreadScale; if(class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, class'NiceSkillEnforcerBombard')){ bPinpoint = true; activeSpread *= class'NiceSkillEnforcerBombard'.default.spreadMult; @@ -607,6 +617,15 @@ function DoFireEffect(){ else if(Instigator.Physics == PHYS_Falling && Instigator.PhysicsVolume.Gravity.Z > class'PhysicsVolume'.default.Gravity.Z) Instigator.AddVelocity((KickMomentum * LowGravKickMomentumScale) >> Instigator.GetViewRotation()); } + if (activeSpreadScale < 1.0) { + if (KFWeap.bAimingRifle) { + activeSpreadScale += spreadGainedPerShot * 0.5; + } + else { + activeSpreadScale += spreadGainedPerShot; + } + activeSpreadScale = FMin(1.0, activeSpreadScale); + } } simulated function float TraceZed(out NiceMonster tracedZed, optional out Vector hitLoc, optional out Vector hitNorm, optional float hsMultiplier){ @@ -712,13 +731,17 @@ simulated function float UpdateNextFireTime(float fireTimeVar){ defaultproperties { - zedTimeFireSpeedUp=1.000000 - ProjPerFire=1 - ProjectileSpeed=1524.000000 - MaxBurstLength=3 - bulletClass=class'NiceBullet' - contBonus=1.200000 - contBonusReset=True - maxBonusContLenght=1 - AmmoPerFire=1 + zedTimeFireSpeedUp=1.000000 + ProjPerFire=1 + ProjectileSpeed=1524.000000 + MaxBurstLength=3 + bulletClass=class'NiceBullet' + contBonus=1.200000 + contBonusReset=True + maxBonusContLenght=1 + AmmoPerFire=1 + minimalSpreadScale=1 + activeSpreadScale=1 + spreadGainedPerShot=0 + spreadLostPerSecond=0 } From ed4d67dc1c2b0011968450aaf1c6a3112f56d4a3 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:10:59 +0700 Subject: [PATCH 09/46] Move medic SMGs to demolitionist perk --- sources/Perks/Commando/NiceDamTypeMedicDart.uc | 2 +- sources/Perks/Demolitions/NiceVetDemolitions.uc | 5 +++-- sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc | 2 +- sources/Weapons/Playable/SMG/Kriss/NiceKrissMPickup.uc | 2 +- sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc | 2 +- sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc | 2 +- sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc | 2 +- sources/Weapons/Playable/SMG/MP5M/NiceMP5MPickup.uc | 2 +- sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc | 2 +- sources/Weapons/Playable/SMG/MP7M/NiceMP7MPickup.uc | 2 +- 10 files changed, 12 insertions(+), 11 deletions(-) diff --git a/sources/Perks/Commando/NiceDamTypeMedicDart.uc b/sources/Perks/Commando/NiceDamTypeMedicDart.uc index 260ac7a..c64ead0 100644 --- a/sources/Perks/Commando/NiceDamTypeMedicDart.uc +++ b/sources/Perks/Commando/NiceDamTypeMedicDart.uc @@ -1,4 +1,4 @@ -class NiceDamTypeMedicDart extends NiceDamageTypeVetCommando +class NiceDamTypeMedicDart extends NiceDamageTypeVetDemolitions abstract; defaultproperties { diff --git a/sources/Perks/Demolitions/NiceVetDemolitions.uc b/sources/Perks/Demolitions/NiceVetDemolitions.uc index a0c1006..ea36af8 100644 --- a/sources/Perks/Demolitions/NiceVetDemolitions.uc +++ b/sources/Perks/Demolitions/NiceVetDemolitions.uc @@ -39,12 +39,13 @@ static function int AddDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, perkDamage = float(InDamage); if(DmgType == class'NiceDamTypeDemoExplosion') return 1.6 * perkDamage; - if(IsPerkedPickup(pickupClass)) + if(IsPerkedPickup(pickupClass) && class(DmgType) != none) perkDamage *= 1.25; else if( pickupClass != none && pickupClass.default.weight <= class'NiceSkillDemoOffperk'.default.weightBound && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoOffperk') ) perkDamage *= class'NiceSkillDemoOffperk'.default.damageBonus; - if( KFPRI != none && class(DmgType) != none + if( KFPRI != none && class(DmgType) == none + && IsPerkedPickup(pickupClass) && SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillDemoOnperk') ) perkDamage *= class'NiceSkillDemoOnperk'.default.damageBonus; return perkDamage; diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc index f728723..7516cbc 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc @@ -1,4 +1,4 @@ -class NiceDamTypeKrissM extends NiceDamageTypeVetCommando +class NiceDamTypeKrissM extends NiceDamageTypeVetDemolitions abstract; defaultproperties { diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMPickup.uc b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMPickup.uc index d8ec776..043b94d 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMPickup.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMPickup.uc @@ -17,7 +17,7 @@ defaultproperties AmmoItemName="45. ACP Ammo" AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo' EquipmentCategoryID=3 - CorrespondingPerkIndex=3 + CorrespondingPerkIndex=6 InventoryType=class'NiceKrissMMedicGun' PickupMessage="You got the KRISS Vector Medic Gun" PickupSound=Sound'KF_KrissSND.Handling.KF_WEP_KRISS_Handling_Pickup' diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc b/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc index e27b99e..96d8965 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc @@ -1,4 +1,4 @@ -class NiceDamTypeM7A3M extends NiceDamageTypeVetCommando +class NiceDamTypeM7A3M extends NiceDamageTypeVetDemolitions abstract; defaultproperties { diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc index 3454139..c75dd32 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc @@ -14,7 +14,7 @@ defaultproperties AmmoItemName="7.6x40mm Ammo" AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo' EquipmentCategoryID=3 - CorrespondingPerkIndex=3 + CorrespondingPerkIndex=6 InventoryType=class'NiceM7A3MMedicGun' PickupMessage="You got the M7A3 Medic Gun" PickupSound=Sound'KF_M7A3Snd.M7A3_Pickup' diff --git a/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc b/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc index 3af2db7..ee30a1f 100644 --- a/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc +++ b/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc @@ -1,4 +1,4 @@ -class NiceDamTypeMP5M extends NiceDamageTypeVetCommando +class NiceDamTypeMP5M extends NiceDamageTypeVetDemolitions abstract; defaultproperties { diff --git a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MPickup.uc b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MPickup.uc index 39f5464..dbd1e37 100644 --- a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MPickup.uc +++ b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MPickup.uc @@ -14,7 +14,7 @@ defaultproperties AmmoItemName="9x19mm Ammo" AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo' EquipmentCategoryID=3 - CorrespondingPerkIndex=3 + CorrespondingPerkIndex=6 VariantClasses(0)=Class'KFMod.CamoMP5MPickup' InventoryType=class'NiceMP5MMedicGun' PickupMessage="You got the MP5M Medic Gun" diff --git a/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc b/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc index 1076d20..71c97c6 100644 --- a/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc +++ b/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc @@ -1,4 +1,4 @@ -class NiceDamTypeMP7M extends NiceDamageTypeVetCommando +class NiceDamTypeMP7M extends NiceDamageTypeVetDemolitions abstract; defaultproperties { diff --git a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MPickup.uc b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MPickup.uc index 95104e2..cf4f30b 100644 --- a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MPickup.uc +++ b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MPickup.uc @@ -15,7 +15,7 @@ defaultproperties AmmoItemName="4.6x30mm Ammo" AmmoMesh=StaticMesh'KillingFloorStatics.L85Ammo' EquipmentCategoryID=3 - CorrespondingPerkIndex=3 + CorrespondingPerkIndex=6 InventoryType=class'NiceMP7MMedicGun' PickupMessage="You got the MP7M Medic Gun" PickupSound=Sound'KF_MP7Snd.MP7_Pickup' From 879dedcd7dedb0b79439d3e1bfd0a5e8b69ec6e7 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:11:49 +0700 Subject: [PATCH 10/46] Add dynamic spread to SMGs --- sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc | 4 ++++ sources/Weapons/Playable/SMG/M7A3/NiceM7A3MFire.uc | 4 ++++ sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc | 4 ++++ sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc index e47aedf..8502921 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc @@ -27,4 +27,8 @@ defaultproperties FlashEmitterClass=Class'ROEffects.MuzzleFlash1stMP' Spread=500.0 SpreadStyle=SS_Random + minimalSpreadScale=0.0 + activeSpreadScale=0.0 + spreadGainedPerShot=0.125 + spreadLostPerSecond=0.5 } diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MFire.uc b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MFire.uc index 0376bf8..f8d867b 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MFire.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MFire.uc @@ -34,4 +34,8 @@ defaultproperties aimerror=42.000000 Spread=500.0 SpreadStyle=SS_Random + minimalSpreadScale=0.0 + activeSpreadScale=0.0 + spreadGainedPerShot=0.25 + spreadLostPerSecond=0.5 } diff --git a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc index ab4be61..1c3dd73 100644 --- a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc +++ b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc @@ -17,6 +17,10 @@ defaultproperties DamageMax=35 Spread=500.0 SpreadStyle=SS_Random + minimalSpreadScale=0.0 + activeSpreadScale=0.0 + spreadGainedPerShot=0.25 + spreadLostPerSecond=1.0 Momentum=5500.000000 FireRate=0.075000 AmmoClass=class'NiceMP5MAmmo' diff --git a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc index 9806704..073c332 100644 --- a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc +++ b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc @@ -27,4 +27,8 @@ defaultproperties FlashEmitterClass=Class'ROEffects.MuzzleFlash1stMP' Spread=500.0 SpreadStyle=SS_Random + minimalSpreadScale=0.0 + activeSpreadScale=0.0 + spreadGainedPerShot=0.1 + spreadLostPerSecond=0.5 } From 4d50763bc359d6d9895141937bc6db86eda881b8 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:12:23 +0700 Subject: [PATCH 11/46] Fix some of the commando ammo cost discrepancies --- sources/Perks/Commando/NiceVetCommando.uc | 10 ++++++++++ .../Playable/AssaultRifles/AK12/NiceAK12Pickup.uc | 2 +- .../Playable/AssaultRifles/AK47/NiceAK47Pickup.uc | 2 +- .../Playable/AssaultRifles/MKb42/NiceMKb42Pickup.uc | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sources/Perks/Commando/NiceVetCommando.uc b/sources/Perks/Commando/NiceVetCommando.uc index db16fbc..b0f1658 100644 --- a/sources/Perks/Commando/NiceVetCommando.uc +++ b/sources/Perks/Commando/NiceVetCommando.uc @@ -35,6 +35,16 @@ static function float GetMagCapacityMod(KFPlayerReplicationInfo KFPRI, KFWeapon return class'NiceSkillCommandoLargerMags'.default.sizeBonus; return 1.0; } +// Change the cost of particular ammo +static function float GetAmmoCostScaling(KFPlayerReplicationInfo KFPRI, class Item) +{ + local class pickupClass; + pickupClass = class(Item); + if(IsPerkedPickup(pickupClass) && HasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoLargerMags')) { + return class'NiceSkillCommandoLargerMags'.default.sizeBonus; + } + return 1.0; +} static function float GetSyringeChargeRate(KFPlayerReplicationInfo KFPRI){ return 1.5; } diff --git a/sources/Weapons/Playable/AssaultRifles/AK12/NiceAK12Pickup.uc b/sources/Weapons/Playable/AssaultRifles/AK12/NiceAK12Pickup.uc index a9379e2..d910bd9 100644 --- a/sources/Weapons/Playable/AssaultRifles/AK12/NiceAK12Pickup.uc +++ b/sources/Weapons/Playable/AssaultRifles/AK12/NiceAK12Pickup.uc @@ -3,7 +3,7 @@ defaultproperties { Weight=6.000000 cost=750 - AmmoCost=19 + AmmoCost=25 BuyClipSize=40 PowerValue=55 SpeedValue=80 diff --git a/sources/Weapons/Playable/AssaultRifles/AK47/NiceAK47Pickup.uc b/sources/Weapons/Playable/AssaultRifles/AK47/NiceAK47Pickup.uc index db19d61..6dad7d2 100644 --- a/sources/Weapons/Playable/AssaultRifles/AK47/NiceAK47Pickup.uc +++ b/sources/Weapons/Playable/AssaultRifles/AK47/NiceAK47Pickup.uc @@ -3,7 +3,7 @@ defaultproperties { Weight=6.000000 cost=750 - AmmoCost=19 + AmmoCost=26 BuyClipSize=30 PowerValue=40 SpeedValue=80 diff --git a/sources/Weapons/Playable/AssaultRifles/MKb42/NiceMKb42Pickup.uc b/sources/Weapons/Playable/AssaultRifles/MKb42/NiceMKb42Pickup.uc index c97c589..01e2aa8 100644 --- a/sources/Weapons/Playable/AssaultRifles/MKb42/NiceMKb42Pickup.uc +++ b/sources/Weapons/Playable/AssaultRifles/MKb42/NiceMKb42Pickup.uc @@ -3,7 +3,7 @@ defaultproperties { Weight=6.000000 cost=750 - AmmoCost=22 + AmmoCost=19 BuyClipSize=30 PowerValue=40 SpeedValue=85 From bb8a28337861a0ed94843e8016f977d6edbdbf16 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:13:21 +0700 Subject: [PATCH 12/46] Decrease M41A grenade cost --- sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc b/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc index 610f503..e4df249 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc @@ -3,7 +3,7 @@ class NiceM41APickup extends NiceM41APrimaryPickup; defaultproperties { crossPerkIndecies(0)=6 - AmmoCost=60 + AmmoCost=12 BuyClipSize=1 SecondaryAmmoShortName="M41A Frag Grenades" PrimaryWeaponPickup=class'NiceM41APrimaryPickup' From 0e825e2111b1fc31104913a1498721fa0ef48205 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:14:29 +0700 Subject: [PATCH 13/46] Fix SMGs cost and amount values --- sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmo.uc | 4 ++-- sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmoPickup.uc | 2 +- sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmo.uc b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmo.uc index 0eda0d3..e900e0c 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmo.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmo.uc @@ -3,8 +3,8 @@ defaultproperties { WeaponPickupClass=class'NiceM7A3MPickup' AmmoPickupAmount=30 - MaxAmmo=180 - InitialAmount=45 + MaxAmmo=160 + InitialAmount=40 PickupClass=class'NiceM7A3MAmmoPickup' IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=336,Y1=82,X2=382,Y2=125) diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmoPickup.uc b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmoPickup.uc index 0f8acfc..220b8fb 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmoPickup.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MAmmoPickup.uc @@ -1,7 +1,7 @@ class NiceM7A3MAmmoPickup extends NiceAmmoPickup; defaultproperties { - AmmoAmount=15 + AmmoAmount=30 InventoryType=class'NiceM7A3MAmmo' PickupMessage="Rounds 7.6x40mm" StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo' diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc index c75dd32..826c735 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceM7A3MPickup.uc @@ -3,7 +3,7 @@ defaultproperties { Weight=5.000000 cost=1250 - AmmoCost=33 + AmmoCost=50 BuyClipSize=30 PowerValue=45 SpeedValue=60 From 8fb84b9695ed4ff1595a898531084a28d5a58b46 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:14:50 +0700 Subject: [PATCH 14/46] Fix Kriss' headshot damage multiplier --- sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc index 7516cbc..ecb840b 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc @@ -2,5 +2,6 @@ class NiceDamTypeKrissM extends NiceDamageTypeVetDemolitions abstract; defaultproperties { + HeadShotDamageMult=2.000000 WeaponClass=class'NiceKrissMMedicGun' } From 8ae4dac5284276e5d6da52c2dd485d3e79e9b2ab Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:15:13 +0700 Subject: [PATCH 15/46] Buff nailgun --- sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGun.uc | 2 +- .../Weapons/Playable/Shotguns/Nailgun/NiceNailGunAltFire.uc | 3 +++ .../Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc | 4 ++-- .../Weapons/Playable/Shotguns/Nailgun/NiceNailGunFire.uc | 6 +++--- .../Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGun.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGun.uc index b7d85ae..6eaf758 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGun.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGun.uc @@ -10,7 +10,7 @@ defaultproperties reloadMagStartFrame=0.278000 reloadChargeStartFrame=-1.000000 FirstPersonFlashlightOffset=(X=-20.000000,Y=-22.000000,Z=8.000000) - MagCapacity=28 + MagCapacity=42 ReloadRate=2.600000 ReloadAnim="Reload" ReloadAnimRate=1.000000 diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAltFire.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAltFire.uc index 5650ed5..059a239 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAltFire.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAltFire.uc @@ -3,6 +3,9 @@ defaultproperties { bCanFireIncomplete=True ProjectileSpeed=3500.000000 + maxVerticalRecoilAngle=1250 + maxHorizontalRecoilAngle=750 + FireRate=0.600000 DamageType=class'NiceDamTypeNailGunWeak' AmmoPerFire=7 SpreadStyle=SS_Random diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc index a005df5..6c7fbd8 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc @@ -3,8 +3,8 @@ class NiceNailGunAmmo extends NiceAmmo; defaultproperties { WeaponPickupClass=class'NiceNailGunPickup' - AmmoPickupAmount=28 - MaxAmmo=168 + AmmoPickupAmount=42 + MaxAmmo=336 InitialAmount=84 IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=451,Y1=445,X2=510,Y2=500) diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunFire.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunFire.uc index f812f62..969bcdf 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunFire.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunFire.uc @@ -10,8 +10,8 @@ defaultproperties bShouldBounce=True bCausePain=True bulletClass=class'NiceNail' - maxVerticalRecoilAngle=1250 - maxHorizontalRecoilAngle=750 + maxVerticalRecoilAngle=0 + maxHorizontalRecoilAngle=0 bRandomPitchFireSound=True FireSoundRef="KF_NailShotgun.NailShotgun_Fire_Single_M" StereoFireSoundRef="KF_NailShotgun.NailShotgun_Fire_Single_S" @@ -19,7 +19,7 @@ defaultproperties DamageType=class'NiceDamTypeNailGun' DamageMax=66 FireAnimRate=1.250000 - FireRate=0.400000 + FireRate=0.300000 AmmoClass=class'NiceNailGunAmmo' ShakeRotTime=3.000000 ShakeOffsetTime=2.000000 diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc index fc10888..44efb17 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc @@ -4,7 +4,7 @@ defaultproperties Weight=8.000000 cost=250 AmmoCost=17 - BuyClipSize=28 + BuyClipSize=42 PowerValue=70 SpeedValue=55 RangeValue=25 From bc5774f3d63d6872b1c9b1f7430838718482aa15 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:15:30 +0700 Subject: [PATCH 16/46] Fix hunting rifle ammo cost --- .../SniperWeapons/HuntingRifle/NiceHuntingRiflePickup.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Weapons/Playable/SniperWeapons/HuntingRifle/NiceHuntingRiflePickup.uc b/sources/Weapons/Playable/SniperWeapons/HuntingRifle/NiceHuntingRiflePickup.uc index 555932b..55477da 100644 --- a/sources/Weapons/Playable/SniperWeapons/HuntingRifle/NiceHuntingRiflePickup.uc +++ b/sources/Weapons/Playable/SniperWeapons/HuntingRifle/NiceHuntingRiflePickup.uc @@ -6,7 +6,7 @@ defaultproperties { Weight=6.000000 cost=750 - AmmoCost=34 + AmmoCost=22 BuyClipSize=5 PowerValue=55 SpeedValue=42 From 8f1f36972b03f26f8bda6ea3ab1ab094f4f8006a Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sat, 16 Mar 2024 16:15:56 +0700 Subject: [PATCH 17/46] Add some variables for zeds' speed modifications --- sources/Zeds/NiceMonster.uc | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 04bb11d..85b79d9 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -139,6 +139,25 @@ var float lastHeatTick; // resulting in a loss of potential damage var bool bFrugalFuelUsage; +//============================================================================== +//============================================================================== +// > Speed system +// Manages speed modifications from weapon attacks and other effects. +// +// This variable stores with how much stopping power zed was affected. +// Is a value from 0.0 to 1.0 and `1 - stoppingEffect` acts as speed multiplier +// for the zed +var float stoppingEffect; +// (Absolute) Point in time at which recovery would start, updated when zeds +// receives another stopping effect from somewhere +var float stoppingRecoveryStartTime; +// How much stopping effect would be rcovred in a second +var float stoppingRecoveryRate; +// Maximum stopping effect this zed can tank +var float maxStoppingEffect; +// Minimal stopping threshold for the zed (supposed to be subtracted from +// incoming effects' strenght). +var float minStoppingThreshold; //============================================================================== //============================================================================== // > Miscellaneous variables @@ -1570,13 +1589,13 @@ function Freeze(){ StopMovement(); Disable('AnimEnd'); StopAnimating(); - + if(Controller != none){ Controller.FocalPoint = Location + 512*vector(Rotation); Controller.Enemy = none; Controller.Focus = none; if(!Controller.IsInState('Freeze')) - Controller.GoToState('Freeze'); + Controller.GoToState('Freeze'); KFMonsterController(Controller).bUseFreezeHack = true; } bFrozenZed = true; @@ -2216,7 +2235,11 @@ defaultproperties DamageToMonsterScale=5.000000 RagdollLifeSpan=120.000000 ControllerClass=class'NiceMonsterController' - + stoppingEffect=0.0 + stoppingRecoveryStartTime=2.0 + stoppingRecoveryRate=0.5 + maxStoppingEffect=0.5 + minStoppingThreshold=0.0 Begin Object Class=KarmaParamsSkel Name=KarmaParamsSkelN KConvulseSpacing=(Max=2.200000) KLinearDamping=0.150000 From 2bf5f3dbe1dbac904192331dfa8040760730c028 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 19 Mar 2024 13:51:38 +0700 Subject: [PATCH 18/46] Fix healing messages not showing up when healed with medic dart --- sources/NiceReplicationInfo.uc | 37 ++++++++++++------- .../BaseWeaponClasses/Medic/NiceMedicGun.uc | 22 ++++++----- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/sources/NiceReplicationInfo.uc b/sources/NiceReplicationInfo.uc index a685f4e..01295a2 100644 --- a/sources/NiceReplicationInfo.uc +++ b/sources/NiceReplicationInfo.uc @@ -203,34 +203,45 @@ simulated function RemovePoisonAndBleed(NiceHumanPawn healed) } // Tells server to heal given human pawn. -simulated function ServerHealTarget(NiceHumanPawn healed, float charPotency, - Pawn instigator){ +simulated function ServerHealTarget( + NiceHumanPawn healed, + float charPotency, + Pawn instigator +) { local NiceHumanPawn healer; + local PlayerController healedPC; local KFPlayerReplicationInfo KFPRI; + local NiceMedicGun healingTool; local float healTotal; local float healPotency; + if(instigator == none || healed == none) return; if(healed.health <= 0 || healed.health >= healed.healthMax) return; KFPRI = KFPlayerReplicationInfo(instigator.PlayerReplicationInfo); - if(KFPRI == none || KFPRI.ClientVeteranSkill == none) - return; + if(KFPRI == none || KFPRI.ClientVeteranSkill == none) return; healer = NiceHumanPawn(instigator); - if(healer == none) - return; + if(healer == none) return; + + healingTool = NiceMedicGun(healer.weapon); healPotency = KFPRI.ClientVeteranSkill.static.GetHealPotency(KFPRI); healTotal = charPotency * healPotency; - healer.AlphaAmount = 255; - if(NiceMedicGun(healer.weapon) != none) - NiceMedicGun(healer.weapon).ClientSuccessfulHeal(healer, healed); - if(healed.health >= healed.healthMax){ + if(healingTool != none) { + healingTool.ClientSuccessfulHeal(healer, healed); + } + healedPC = PlayerController(healed.controller); + if(healedPC != none) { + healedPC.ClientMessage( + "You've been healed by" @ healer.GetPlayerName(), + 'CriticalEvent'); + } + if(healed.health >= healed.healthMax) { healed.GiveHealth(healTotal, healed.healthMax); return; } HandleNiceHealingMechanicsAndSkills(healer, healed, healPotency); - if(healed.health < healed.healthMax){ - healed.TakeHealing( healed, healTotal, healPotency, - KFWeapon(instigator.weapon)); + if(healed.health < healed.healthMax) { + healed.TakeHealing(healed, healTotal, healPotency, healingTool); } RemovePoisonAndBleed(healed); } diff --git a/sources/Weapons/BaseWeaponClasses/Medic/NiceMedicGun.uc b/sources/Weapons/BaseWeaponClasses/Medic/NiceMedicGun.uc index 4f37338..f18064d 100644 --- a/sources/Weapons/BaseWeaponClasses/Medic/NiceMedicGun.uc +++ b/sources/Weapons/BaseWeaponClasses/Medic/NiceMedicGun.uc @@ -66,15 +66,19 @@ simulated function WeaponTick(float dt){ } super.WeaponTick(dt); } -simulated function ClientSuccessfulHeal(NiceHumanPawn healer, NiceHumanPawn healed){ - if(healed == none) - return; - if(instigator != none && PlayerController(instigator.controller) != none) - PlayerController(instigator.controller). - ClientMessage("You've healed"@healed.GetPlayerName(), 'CriticalEvent'); - if(NiceHumanPawn(instigator) != none && PlayerController(healed.controller) != none) - PlayerController(healed.controller). - ClientMessage("You've been healed by"@healer.GetPlayerName(), 'CriticalEvent'); + +simulated function ClientSuccessfulHeal( + NiceHumanPawn healer, + NiceHumanPawn healed +){ + if(healed == none) { + return; + } + if(instigator != none && PlayerController(instigator.controller) != none) { + PlayerController(instigator.controller).ClientMessage( + "You've healed" @ healed.GetPlayerName(), + 'CriticalEvent'); + } } defaultproperties From 87f60c9c60c4c0081d4e14d3db8d707f537883f1 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 19 Mar 2024 14:34:24 +0700 Subject: [PATCH 19/46] Add visual counter for health regen from healing --- sources/GUI/NiceInteraction.uc | 36 +++++++++++++++++++++++++++++++--- sources/NiceHumanPawn.uc | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/sources/GUI/NiceInteraction.uc b/sources/GUI/NiceInteraction.uc index a52af06..103d2cd 100644 --- a/sources/GUI/NiceInteraction.uc +++ b/sources/GUI/NiceInteraction.uc @@ -107,6 +107,10 @@ function PostRender(Canvas C) local int x, y, center, barWidth, offset; local int missesWidth, missesHeight, missesSpace; local int missesX, missesY; + local TeamInfo team; + local int healthToGive, totalExpectedHealth; + local float textWidth, textHeight; + local string textToDraw; // local Vector CamPos, ViewDir; // local Rotator CamRot; // local float OffsetX, BarLength, BarHeight, XL, YL, posY; @@ -256,6 +260,32 @@ function PostRender(Canvas C) } } + team = C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team; + //// Draw health still in regen timer + healthToGive = ScrnHumanPawn(C.ViewPort.Actor.Pawn).clientHealthToGive; + if (healthToGive > 0) { + totalExpectedHealth = healthToGive + C.ViewPort.Actor.Pawn.health;; + C.Font = class'ROHUD'.Static.LoadSmallFontStatic(3); + if (totalExpectedHealth >= C.ViewPort.Actor.Pawn.healthMax) { + if(team.teamIndex == 0) { + C.SetDrawColor(255, 64, 64); + } + else { + C.SetDrawColor( + team.teamColor.R, + team.teamColor.G, + team.teamColor.B); + } + } + else { + C.SetDrawColor(128, 128, 128); + } + textToDraw = "+" $ healthToGive; + C.TextSize(textToDraw, textWidth, textHeight); + C.SetPos(C.ClipX * 0.05, C.ClipY * 0.9); + C.DrawText(textToDraw); + } + //// Draw cooldowns if (nicePlayer.abilityManager == none) return; @@ -273,7 +303,7 @@ function PostRender(Canvas C) { if (niceMutator.niceCounterSet[i].value != 0 || niceMutator.niceCounterSet[i].bShowZeroValue) { - DrawCounter(C, niceMutator.niceCounterSet[i], x, y, C.ViewPort.Actor.Pawn.PlayerReplicationInfo.Team); + DrawCounter(C, niceMutator.niceCounterSet[i], x, y, team); x += 128 + 4; } } @@ -283,7 +313,7 @@ function PostRender(Canvas C) function DrawCounter(Canvas C, NicePack.CounterDisplay counter, int x, int y, TeamInfo team){ local float borderSpace; local Texture textureToDraw; - local float textWidth, textHeight; + local float textWidth, textHeight; local string textToDraw; // Some per-defined values for drawing local int iconSize, backgroundWidth, backgroundHeight; @@ -320,7 +350,7 @@ function DrawAbilityCooldown(Canvas C, int abilityIndex){ local class niceVet; local int x, y; local string textToDraw; - local float textWidth, textHeight; + local float textWidth, textHeight; local NiceAbilityManager.EAbilityState abilityState; if(C == none) return; if(C.ViewPort == none) return; diff --git a/sources/NiceHumanPawn.uc b/sources/NiceHumanPawn.uc index b6f1ece..448e554 100644 --- a/sources/NiceHumanPawn.uc +++ b/sources/NiceHumanPawn.uc @@ -846,7 +846,7 @@ function VeterancyChanged(){ nicePlayer.TriggerSelectEventOnPerkChange(nicePrevPerkClass, class(KFPRI.ClientVeteranSkill)); } - + super.VeterancyChanged(); } simulated function AltFire(optional float F){ From 1bc35cc348d5e23fd76ec61fdbb419e3db0cb23f Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 20 Mar 2024 20:27:31 +0700 Subject: [PATCH 20/46] Balance adjustments --- sources/Weapons/Playable/Heavy/M41A/NiceM41AAmmo.uc | 4 ++-- sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc | 2 +- .../Weapons/Playable/Heavy/M41A/NiceM41APrimaryPickup.uc | 2 +- .../Weapons/Playable/Heavy/M41A/NiceM41AProjectileAmmo.uc | 2 +- sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc | 2 +- sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc | 4 ++-- sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc | 8 ++++---- sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc | 2 +- .../Playable/Shotguns/Boomstick/NiceBoomStickFire.uc | 1 + .../Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc | 4 ++-- .../Playable/Shotguns/Nailgun/NiceNailGunPickup.uc | 2 +- 11 files changed, 17 insertions(+), 16 deletions(-) diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceM41AAmmo.uc b/sources/Weapons/Playable/Heavy/M41A/NiceM41AAmmo.uc index 6f7b45b..06e02e2 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceM41AAmmo.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceM41AAmmo.uc @@ -4,8 +4,8 @@ defaultproperties { WeaponPickupClass=class'NiceM41APickup' AmmoPickupAmount=66 - MaxAmmo=300 - InitialAmount=75 + MaxAmmo=264 + InitialAmount=66 PickupClass=class'NiceM41AAmmoPickup' IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=336,Y1=82,X2=382,Y2=125) diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc b/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc index e4df249..4dc3f6f 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceM41APickup.uc @@ -3,7 +3,7 @@ class NiceM41APickup extends NiceM41APrimaryPickup; defaultproperties { crossPerkIndecies(0)=6 - AmmoCost=12 + AmmoCost=24 BuyClipSize=1 SecondaryAmmoShortName="M41A Frag Grenades" PrimaryWeaponPickup=class'NiceM41APrimaryPickup' diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceM41APrimaryPickup.uc b/sources/Weapons/Playable/Heavy/M41A/NiceM41APrimaryPickup.uc index 0f05cc6..808f48a 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceM41APrimaryPickup.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceM41APrimaryPickup.uc @@ -3,7 +3,7 @@ defaultproperties { cost=750 Weight=7.000000 - AmmoCost=66 + AmmoCost=25 BuyClipSize=66 PowerValue=70 SpeedValue=100 diff --git a/sources/Weapons/Playable/Heavy/M41A/NiceM41AProjectileAmmo.uc b/sources/Weapons/Playable/Heavy/M41A/NiceM41AProjectileAmmo.uc index a778ca5..1887b81 100644 --- a/sources/Weapons/Playable/Heavy/M41A/NiceM41AProjectileAmmo.uc +++ b/sources/Weapons/Playable/Heavy/M41A/NiceM41AProjectileAmmo.uc @@ -3,7 +3,7 @@ defaultproperties { WeaponPickupClass=class'NiceM41APickup' AmmoPickupAmount=1 - MaxAmmo=8 + MaxAmmo=5 InitialAmount=2 IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=434,Y1=253,X2=506,Y2=292) diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc index ecb840b..ca8b1c2 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc @@ -2,6 +2,6 @@ class NiceDamTypeKrissM extends NiceDamageTypeVetDemolitions abstract; defaultproperties { - HeadShotDamageMult=2.000000 + HeadShotDamageMult=1.500000 WeaponClass=class'NiceKrissMMedicGun' } diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc index 8502921..60029e5 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceKrissMFire.uc @@ -13,8 +13,8 @@ defaultproperties ShellEjectBoneName="Shell_eject" NoAmmoSoundRef="KF_MP7Snd.MP7_DryFire" DamageType=class'NiceDamTypeKrissM' - DamageMin=35 - DamageMax=35 + DamageMin=48 + DamageMax=48 Momentum=12500.000000 FireRate=0.040000 AmmoClass=class'NiceKrissMAmmo' diff --git a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc index 1c3dd73..d636895 100644 --- a/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc +++ b/sources/Weapons/Playable/SMG/MP5M/NiceMP5MFire.uc @@ -5,9 +5,9 @@ defaultproperties FireEndStereoSoundRef="KF_MP5Snd.MP5_Fire_Loop_End_S" AmbientFireSoundRef="KF_MP5Snd.MP5_Fire_Loop" ProjectileSpeed=21250.000000 - RecoilRate=0.0075000 - maxVerticalRecoilAngle=160 - maxHorizontalRecoilAngle=80 + RecoilRate=0.0100000 + maxVerticalRecoilAngle=40 + maxHorizontalRecoilAngle=20 RecoilVelocityScale=0.000000 ShellEjectClass=Class'ROEffects.KFShellEjectMP5SMG' ShellEjectBoneName="Shell_eject" @@ -15,7 +15,7 @@ defaultproperties DamageType=class'NiceDamTypeMP5M' DamageMin=35 DamageMax=35 - Spread=500.0 + Spread=750.0 SpreadStyle=SS_Random minimalSpreadScale=0.0 activeSpreadScale=0.0 diff --git a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc index 073c332..cc238c3 100644 --- a/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc +++ b/sources/Weapons/Playable/SMG/MP7M/NiceMP7MFire.uc @@ -25,7 +25,7 @@ defaultproperties ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000) ShakeOffsetTime=1.250000 FlashEmitterClass=Class'ROEffects.MuzzleFlash1stMP' - Spread=500.0 + Spread=750.0 SpreadStyle=SS_Random minimalSpreadScale=0.0 activeSpreadScale=0.0 diff --git a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc index ce35d5a..070012c 100644 --- a/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc +++ b/sources/Weapons/Playable/Shotguns/Boomstick/NiceBoomStickFire.uc @@ -59,4 +59,5 @@ defaultproperties BotRefireRate=2.500000 aimerror=2.000000 Spread=3000.000000 + FireAnimRate=1.25 } diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc index 6c7fbd8..b0596d7 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunAmmo.uc @@ -4,8 +4,8 @@ defaultproperties { WeaponPickupClass=class'NiceNailGunPickup' AmmoPickupAmount=42 - MaxAmmo=336 - InitialAmount=84 + MaxAmmo=210 + InitialAmount=52 IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=451,Y1=445,X2=510,Y2=500) } diff --git a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc index 44efb17..cfb7a50 100644 --- a/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc +++ b/sources/Weapons/Playable/Shotguns/Nailgun/NiceNailGunPickup.uc @@ -3,7 +3,7 @@ defaultproperties { Weight=8.000000 cost=250 - AmmoCost=17 + AmmoCost=27 BuyClipSize=42 PowerValue=70 SpeedValue=55 From 095157445182025baac2c058d95e1f598cb1b11c Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Fri, 22 Mar 2024 18:48:30 +0700 Subject: [PATCH 21/46] Add stopping power mechanic --- sources/NiceReplicationInfo.uc | 57 +++---- .../Demolitions/NiceDamTypeDemoExplosion.uc | 1 + .../BaseWeaponClasses/NiceWeaponDamageType.uc | 2 + .../Playable/SMG/Kriss/NiceDamTypeKrissM.uc | 1 + .../Playable/SMG/M7A3/NiceDamTypeM7A3M.uc | 1 + .../Playable/SMG/MP5M/NiceDamTypeMP5M.uc | 1 + .../Playable/SMG/MP7M/NiceDamTypeMP7M.uc | 1 + sources/Zeds/Mean/MeanZombieFleshPound.uc | 15 +- sources/Zeds/Nice/NiceZombieBoss.uc | 40 ++--- sources/Zeds/Nice/NiceZombieBossBase.uc | 3 + sources/Zeds/Nice/NiceZombieBrute.uc | 29 +--- sources/Zeds/Nice/NiceZombieBruteBase.uc | 3 +- sources/Zeds/Nice/NiceZombieFleshPound.uc | 20 ++- sources/Zeds/Nice/NiceZombieFleshpoundBase.uc | 2 + sources/Zeds/Nice/NiceZombieGorefast.uc | 14 +- sources/Zeds/Nice/NiceZombieHuskBase.uc | 1 + sources/Zeds/Nice/NiceZombieJason.uc | 19 +-- sources/Zeds/Nice/NiceZombieScrake.uc | 19 +-- sources/Zeds/Nice/NiceZombieScrakeBase.uc | 2 + sources/Zeds/Nice/NiceZombieShiver.uc | 16 +- sources/Zeds/Nice/NiceZombieSiren.uc | 12 +- sources/Zeds/Nice/NiceZombieTeslaHusk.uc | 1 - sources/Zeds/NiceMonster.uc | 144 ++++++++++++------ 23 files changed, 208 insertions(+), 196 deletions(-) diff --git a/sources/NiceReplicationInfo.uc b/sources/NiceReplicationInfo.uc index 01295a2..2da7241 100644 --- a/sources/NiceReplicationInfo.uc +++ b/sources/NiceReplicationInfo.uc @@ -102,31 +102,39 @@ simulated function ServerExplode local Vector dirToVictim; local Vector hitLocation; local float scale1, scale2; + local NiceMonster niceVictim; if(Role < ROLE_Authority) return; foreach VisibleActors(class'Actor', victim, explRadius, explLocation){ - if(victim == none || victim == self) continue; - if(victim.role < ROLE_Authority) continue; - if(ExtendedZCollision(victim) != none) continue; - if(Trigger(victim) != none) continue; - dirToVictim = Normal(victim.location - explLocation); - hitLocation = victim.location - 0.5 * - (victim.collisionHeight + victim.collisionRadius) * dirToVictim; - CalculateDamageScales( scale1, scale2, - victim, explLocation, explRadius, explExp); - // Deal main damage - if(scale1 > 0){ - ServerDealDamage( victim, explDamage * scale1, instigator, - hitLocation, scale1 * momentum * dirToVictim, - explDmgType); - } - // Deal secondary damage - if(allowDoubleExplosion && victim != none && scale2 > 0){ - ServerDealDamage( victim, explDamage * scale2, instigator, - hitLocation, scale2 * momentum * dirToVictim, - explDmgType); - } - if(NiceMonster(victim) != none && NiceMonster(victim).health <= 0) - numKilled ++; + if(victim == none || victim == self) continue; + if(victim.role < ROLE_Authority) continue; + if(ExtendedZCollision(victim) != none) continue; + if(Trigger(victim) != none) continue; + dirToVictim = Normal(victim.location - explLocation); + hitLocation = victim.location - 0.5 * + (victim.collisionHeight + victim.collisionRadius) * dirToVictim; + CalculateDamageScales( scale1, scale2, + victim, explLocation, explRadius, explExp); + // Deal main damage + if(scale1 > 0){ + ServerDealDamage( victim, explDamage * scale1, instigator, + hitLocation, scale1 * momentum * dirToVictim, + explDmgType); + } + // Deal secondary damage + if(allowDoubleExplosion && victim != none && scale2 > 0){ + ServerDealDamage( victim, explDamage * scale2, instigator, + hitLocation, scale2 * momentum * dirToVictim, + explDmgType); + } + niceVictim = NiceMonster(victim); + if(NiceMonster(victim) != none) { + if (NiceMonster(victim).health <= 0) { + numKilled += 1; + } + else { + niceVictim.concussionCountdown = 10.0; + } + } } if(numKilled >= 4) KFGameType(level.game).DramaticEvent(0.05); @@ -272,9 +280,6 @@ simulated function HandleNiceDamageMechanicsAndSkills hasSkill(nicePlayer, class'NiceSkillCommandoTranquilizer'); hasZEDFrenzy = class'NiceVeterancyTypes'.static. hasSkill(nicePlayer, class'NiceSkillMedicZEDFrenzy'); - // Medic's suppression - if(hasTranquilizer) - niceZed.mind = FMin(niceZed.mind, 0.5); // Medic's frenzy if(hasZEDFrenzy && nicePlayer.IsZedTimeActive()){ niceZed.madnessCountDown = diff --git a/sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc b/sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc index a640688..78ab779 100644 --- a/sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc +++ b/sources/Perks/Demolitions/NiceDamTypeDemoExplosion.uc @@ -8,6 +8,7 @@ static function GetHitEffects(out class HitEffects[4], int VictimHealt } defaultproperties { + stoppingPower=0.5 stunMultiplier=0.600000 bIsExplosive=True DeathString="%o filled %k's body with shrapnel." diff --git a/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc b/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc index 62fc867..835503b 100644 --- a/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc +++ b/sources/Weapons/BaseWeaponClasses/NiceWeaponDamageType.uc @@ -27,6 +27,7 @@ var const int MediumZedMinHealth; // If zed's base Health >= this var float PenDmgReduction; // Penetration damage reduction after hitting small zed var float penDecapReduction; // Penetration decapitaion effectiveness reduction after hitting small zed var float penIncapReduction; // Penetration incapacitation (flinch or stun) effectiveness reduction after hitting small zed +var float stoppingPower; // How much stopping power the gun has - % amount zeds will be made to slow down when shot var bool bIsProjectile; // If original damage type's version was derived from 'KFProjectileWeaponDamageType', then set this to true // Scales exp gain according to given HardcoreLevel static function float getScale(int HL){ @@ -88,6 +89,7 @@ defaultproperties BigZedPenDmgReduction=0.500000 BigZedMinHealth=1000 MediumZedPenDmgReduction=0.750000 + stoppingPower=0.0 MediumZedMinHealth=500 PenDmgReduction=0.700000 PawnDamageEmitter=None diff --git a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc index ca8b1c2..48b3dad 100644 --- a/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc +++ b/sources/Weapons/Playable/SMG/Kriss/NiceDamTypeKrissM.uc @@ -2,6 +2,7 @@ class NiceDamTypeKrissM extends NiceDamageTypeVetDemolitions abstract; defaultproperties { + stoppingPower=0.25 HeadShotDamageMult=1.500000 WeaponClass=class'NiceKrissMMedicGun' } diff --git a/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc b/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc index 96d8965..9c584ce 100644 --- a/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc +++ b/sources/Weapons/Playable/SMG/M7A3/NiceDamTypeM7A3M.uc @@ -2,6 +2,7 @@ class NiceDamTypeM7A3M extends NiceDamageTypeVetDemolitions abstract; defaultproperties { + stoppingPower=0.15 HeadShotDamageMult=2.000000 WeaponClass=class'NiceM7A3MMedicGun' } diff --git a/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc b/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc index ee30a1f..89f2bcb 100644 --- a/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc +++ b/sources/Weapons/Playable/SMG/MP5M/NiceDamTypeMP5M.uc @@ -2,6 +2,7 @@ class NiceDamTypeMP5M extends NiceDamageTypeVetDemolitions abstract; defaultproperties { + stoppingPower=0.15 HeadShotDamageMult=2.000000 WeaponClass=class'NiceMP5MMedicGun' } diff --git a/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc b/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc index 71c97c6..a6274cc 100644 --- a/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc +++ b/sources/Weapons/Playable/SMG/MP7M/NiceDamTypeMP7M.uc @@ -5,5 +5,6 @@ defaultproperties bPenetrationHSOnly=True MaxPenetrations=1 HeadShotDamageMult=2.250000 + stoppingPower=0.15 WeaponClass=class'NiceMP7MMedicGun' } diff --git a/sources/Zeds/Mean/MeanZombieFleshPound.uc b/sources/Zeds/Mean/MeanZombieFleshPound.uc index 3bb82a0..b7ac20b 100644 --- a/sources/Zeds/Mean/MeanZombieFleshPound.uc +++ b/sources/Zeds/Mean/MeanZombieFleshPound.uc @@ -27,23 +27,20 @@ Ignores StartChargingFP; bFrustrated = false; if(Controller != none) NiceZombieFleshPoundController(Controller).RageFrustrationTimer = 0; - if( Health>0 && !bZapped ) - { - SetGroundSpeed(GetOriginalGroundSpeed()); - } if( Level.NetMode!=NM_DedicatedServer ) ClientChargingAnims(); NetUpdateTime = Level.TimeSeconds - 1; } + simulated function UpdateGroundSpeed() { + super(NiceMonster).UpdateGroundSpeed(); + if (!bShotAnim) { + groundSpeed *= 2.3; + } + } function Tick( float Delta ) { - if( !bShotAnim ) - { - SetGroundSpeed(OriginalGroundSpeed * 2.3);//2.0; - } - // Keep the flesh pound moving toward its target when attacking if( Role == ROLE_Authority && bShotAnim) { diff --git a/sources/Zeds/Nice/NiceZombieBoss.uc b/sources/Zeds/Nice/NiceZombieBoss.uc index 8384766..2c53c56 100644 --- a/sources/Zeds/Nice/NiceZombieBoss.uc +++ b/sources/Zeds/Nice/NiceZombieBoss.uc @@ -915,9 +915,16 @@ state Charging // How many charge attacks we can do randomly 1-3 NumChargeAttacks = Rand(2) + 1; } + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (bShotAnim) { + groundSpeed *= 1.25; + } else { + groundSpeed *= 2.5; + } + } function EndState() { - SetGroundSpeed(GetOriginalGroundSpeed()); bChargingPlayer = False; ChargeDamage = 0; if( Level.NetMode!=NM_DedicatedServer ) @@ -942,7 +949,6 @@ state Charging if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } - SetGroundSpeed(OriginalGroundSpeed * 1.25); if( LookTarget!=none ) { Acceleration = AccelRate * Normal(LookTarget.Location - Location); @@ -956,16 +962,6 @@ state Charging if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } - - // Zapping slows him down, but doesn't stop him - if( bZapped ) - { - SetGroundSpeed(OriginalGroundSpeed * 1.5); - } - else - { - SetGroundSpeed(OriginalGroundSpeed * 2.5); - } } Global.Tick(Delta); @@ -1071,7 +1067,6 @@ State Escaping extends Charging // Got hurt and running away... if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } - SetGroundSpeed(GetOriginalGroundSpeed()); } else { @@ -1081,23 +1076,20 @@ State Escaping extends Charging // Got hurt and running away... if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } - - // Zapping slows him down, but doesn't stop him - if( bZapped ) - { - SetGroundSpeed(OriginalGroundSpeed * 1.5); - } - else - { - SetGroundSpeed(OriginalGroundSpeed * 2.5); - } } Global.Tick(Delta); } + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (bShotAnim) { + groundSpeed *= 1.25; + } else { + groundSpeed *= 2.5; + } + } function EndState() { - SetGroundSpeed(GetOriginalGroundSpeed()); bChargingPlayer = False; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); diff --git a/sources/Zeds/Nice/NiceZombieBossBase.uc b/sources/Zeds/Nice/NiceZombieBossBase.uc index aa6cade..cd05c38 100644 --- a/sources/Zeds/Nice/NiceZombieBossBase.uc +++ b/sources/Zeds/Nice/NiceZombieBossBase.uc @@ -98,6 +98,9 @@ defaultproperties HealthMax=8000.000000 Health=8000 HeadScale=1.300000 + stoppingRecoveryRate=0.1 + maxStoppingEffect=0.2 + minStoppingThreshold=0.6 MenuName="Nice Patriarch" MovementAnims(0)="WalkF" MovementAnims(1)="WalkF" diff --git a/sources/Zeds/Nice/NiceZombieBrute.uc b/sources/Zeds/Nice/NiceZombieBrute.uc index 8e6c7f1..26860fc 100644 --- a/sources/Zeds/Nice/NiceZombieBrute.uc +++ b/sources/Zeds/Nice/NiceZombieBrute.uc @@ -182,18 +182,6 @@ function TakeDamageClient(int Damage, Pawn InstigatedBy, Vector HitLocation, Vec if (bDecapitated) Died(InstigatedBy.Controller, damageType, HitLocation); } -function TakeFireDamage(int Damage, Pawn Instigator) -{ - Super.TakeFireDamage(Damage, Instigator); - // Adjust movement speed if not charging - if (!bChargingPlayer) - { - if (bBurnified) - GroundSpeed = GetOriginalGroundSpeed() * BurnGroundSpeedMul; - else - GroundSpeed = GetOriginalGroundSpeed(); - } -} function ClawDamageTarget() { local KFHumanPawn HumanTarget; @@ -311,19 +299,16 @@ Ignores StartCharging; NetUpdateTime = Level.TimeSeconds - 1; } + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + groundSpeed = groundSpeed + ((groundSpeed * 0.75 / maxRageCounter * (rageCounter + 1) * rageSpeedTween)); + } function EndState() { bChargingPlayer = false; NiceZombieBruteController(Controller).RageFrustrationTimer = 0; - if (Health > 0) - { - GroundSpeed = GetOriginalGroundSpeed(); - if (bBurnified) - GroundSpeed *= BurnGroundSpeedMul; - } - if( Level.NetMode!=NM_DedicatedServer ) ClientChargingAnims(); @@ -331,12 +316,8 @@ Ignores StartCharging; } function Tick(float Delta) { - if (!bShotAnim) - { + if (!bShotAnim) { RageSpeedTween = FClamp(RageSpeedTween + (Delta * 0.75), 0, 1.0); - GroundSpeed = OriginalGroundSpeed + ((OriginalGroundSpeed * 0.75 / MaxRageCounter * (RageCounter + 1) * RageSpeedTween)); - if (bBurnified) - GroundSpeed *= BurnGroundSpeedMul; } Global.Tick(Delta); diff --git a/sources/Zeds/Nice/NiceZombieBruteBase.uc b/sources/Zeds/Nice/NiceZombieBruteBase.uc index 58af2a0..7bbd5e5 100644 --- a/sources/Zeds/Nice/NiceZombieBruteBase.uc +++ b/sources/Zeds/Nice/NiceZombieBruteBase.uc @@ -33,7 +33,6 @@ var bool bServerBlock; var bool bClientBlock; var float BlockDmgMul; // Multiplier for damage taken from blocked shots var float BlockFireDmgMul; -var float BurnGroundSpeedMul; // Multiplier for ground speed when burning replication { reliable if(Role == ROLE_Authority) @@ -61,7 +60,6 @@ defaultproperties BlockAddScale=2.500000 BlockDmgMul=0.100000 BlockFireDmgMul=1.000000 - BurnGroundSpeedMul=0.700000 StunThreshold=4.000000 flameFuel=0.500000 clientHeadshotScale=1.300000 @@ -110,6 +108,7 @@ defaultproperties Health=1000 HeadHeight=2.500000 HeadScale=1.300000 + minStoppingThreshold=0.1 MenuName="Brute" MovementAnims(0)="BruteWalkC" MovementAnims(1)="BruteWalkC" diff --git a/sources/Zeds/Nice/NiceZombieFleshPound.uc b/sources/Zeds/Nice/NiceZombieFleshPound.uc index 1a7ea05..8d5056d 100644 --- a/sources/Zeds/Nice/NiceZombieFleshPound.uc +++ b/sources/Zeds/Nice/NiceZombieFleshPound.uc @@ -49,7 +49,6 @@ function SetMindControlled(bool bNewMindControlled) if( bNewMindControlled != bZedUnderControl ) { - SetGroundSpeed(OriginalGroundSpeed * 1.25); Health *= 1.25; HealthMax *= 1.25; } @@ -252,21 +251,21 @@ Ignores StartChargingFP; if(fpController == none) fpController.RageFrustrationTimer = 0; - if( Health>0 && !bZapped ) - { - SetGroundSpeed(GetOriginalGroundSpeed()); - } - if( Level.NetMode!=NM_DedicatedServer ) ClientChargingAnims(); NetUpdateTime = Level.TimeSeconds - 1; } + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (!bShotAnim) { + groundSpeed *= 2.3; + } + } function Tick( float Delta ) { if( !bShotAnim ) { - SetGroundSpeed(OriginalGroundSpeed * 2.3);//2.0; if( !bFrustrated && !bZedUnderControl && Level.TimeSeconds>RageEndTime ) { GoToState(''); @@ -330,11 +329,16 @@ Ignores StartChargingFP; state ChargeToMarker extends RageCharging { Ignores StartChargingFP; + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (!bShotAnim) { + groundSpeed *= 2.3; + } + } function Tick( float Delta ) { if( !bShotAnim ) { - SetGroundSpeed(OriginalGroundSpeed * 2.3); if( !bFrustrated && !bZedUnderControl && Level.TimeSeconds>RageEndTime ) { GoToState(''); diff --git a/sources/Zeds/Nice/NiceZombieFleshpoundBase.uc b/sources/Zeds/Nice/NiceZombieFleshpoundBase.uc index 6380eb1..54fc8c3 100644 --- a/sources/Zeds/Nice/NiceZombieFleshpoundBase.uc +++ b/sources/Zeds/Nice/NiceZombieFleshpoundBase.uc @@ -80,6 +80,8 @@ defaultproperties Health=1650 HeadHeight=2.500000 HeadScale=1.300000 + maxStoppingEffect=0.05 + minStoppingThreshold=0.68 MenuName="Nice Flesh Pound" MovementAnims(0)="PoundWalk" MovementAnims(1)="WalkB" diff --git a/sources/Zeds/Nice/NiceZombieGorefast.uc b/sources/Zeds/Nice/NiceZombieGorefast.uc index 6b75e97..a696b0e 100644 --- a/sources/Zeds/Nice/NiceZombieGorefast.uc +++ b/sources/Zeds/Nice/NiceZombieGorefast.uc @@ -45,7 +45,6 @@ function SetMindControlled(bool bNewMindControlled) if( bNewMindControlled != bZedUnderControl ) { - SetGroundSpeed(OriginalGroundSpeed * 1.25); Health *= 1.25; HealthMax *= 1.25; } @@ -73,13 +72,6 @@ function RangedAttack(Actor A){ if(!bShotAnim && !bDecapitated && VSize(A.Location - Location) <= 700) GoToState('RunningState'); } -simulated function Tick(float DeltaTime){ - super.Tick(DeltaTime); - if(IsInState('RunningState')) - SetGroundSpeed(GetOriginalGroundSpeed() * 1.875); - else - SetGroundSpeed(GetOriginalGroundSpeed()); -} state RunningState{ // Set the zed to the zapped behavior simulated function SetZappedBehavior(){ @@ -94,7 +86,6 @@ state RunningState{ if(bZapped) GoToState(''); else{ - SetGroundSpeed(OriginalGroundSpeed * 1.875); bRunning = true; if(Level.NetMode != NM_DedicatedServer) PostNetReceive(); @@ -103,7 +94,6 @@ state RunningState{ } } function EndState(){ - SetGroundSpeed(GetOriginalGroundSpeed()); bRunning = false; if(Level.NetMode != NM_DedicatedServer) PostNetReceive(); @@ -112,6 +102,10 @@ state RunningState{ NetUpdateTime = Level.TimeSeconds - 1; } + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + groundSpeed *= 1.875; + } function RemoveHead(){ GoToState(''); Global.RemoveHead(); diff --git a/sources/Zeds/Nice/NiceZombieHuskBase.uc b/sources/Zeds/Nice/NiceZombieHuskBase.uc index 7c93117..89b8a58 100644 --- a/sources/Zeds/Nice/NiceZombieHuskBase.uc +++ b/sources/Zeds/Nice/NiceZombieHuskBase.uc @@ -60,6 +60,7 @@ defaultproperties HeadHeight=1.000000 HeadScale=1.350000 AmbientSoundScaling=8.000000 + stoppingRecoveryRate=0.05 MenuName="Nice Husk" MovementAnims(0)="WalkF" MovementAnims(1)="WalkB" diff --git a/sources/Zeds/Nice/NiceZombieJason.uc b/sources/Zeds/Nice/NiceZombieJason.uc index ab0a1f6..c32c255 100644 --- a/sources/Zeds/Nice/NiceZombieJason.uc +++ b/sources/Zeds/Nice/NiceZombieJason.uc @@ -105,15 +105,11 @@ State SawingLoop else GoToState(''); } } -simulated function float GetOriginalGroundSpeed() -{ - local float result; - result = OriginalGroundSpeed; - if ( bWasRaged || bCharging ) - result *= 3.5; - else if( bZedUnderControl ) - result *= 1.25; - return result; +simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (bWasRaged || bCharging) { + groundSpeed *= 3.5; + } } state RunningState { @@ -124,7 +120,6 @@ state RunningState GoToState(''); else { bCharging = true; - SetGroundSpeed(GetOriginalGroundSpeed()); if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); NetUpdateTime = Level.TimeSeconds - 1; @@ -133,8 +128,6 @@ state RunningState function EndState() { bCharging = False; - if( !bZapped ) - SetGroundSpeed(GetOriginalGroundSpeed()); if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); } @@ -163,6 +156,8 @@ defaultproperties ChallengeSound(2)=None ChallengeSound(3)=None ScoringValue=300 + maxStoppingEffect=0.25 + minStoppingThreshold=0.25 MenuName="Jason" AmbientSound=Sound'ScrnZedPack_S.Jason.Jason_Sound' Mesh=SkeletalMesh'ScrnZedPack_A.JasonMesh' diff --git a/sources/Zeds/Nice/NiceZombieScrake.uc b/sources/Zeds/Nice/NiceZombieScrake.uc index 190e4fb..22f2797 100644 --- a/sources/Zeds/Nice/NiceZombieScrake.uc +++ b/sources/Zeds/Nice/NiceZombieScrake.uc @@ -83,7 +83,6 @@ function SetMindControlled(bool bNewMindControlled) if( bNewMindControlled != bZedUnderControl ) { - SetGroundSpeed(OriginalGroundSpeed * 1.25); Health *= 1.25; HealthMax *= 1.25; } @@ -185,8 +184,9 @@ state RunningState { return false; } - simulated function float GetOriginalGroundSpeed() { - return 3.5 * OriginalGroundSpeed; + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + groundSpeed *= 3.5; } function BeginState(){ local NiceHumanPawn rageTarget, rageCause; @@ -214,7 +214,6 @@ state RunningState if(bZapped) GoToState(''); else{ - SetGroundSpeed(OriginalGroundSpeed * 3.5); bCharging = true; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); @@ -224,10 +223,6 @@ state RunningState } function EndState() { - if( !bZapped ) - { - SetGroundSpeed(GetOriginalGroundSpeed()); - } bCharging = False; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); @@ -265,8 +260,9 @@ State SawingLoop { return false; } - simulated function float GetOriginalGroundSpeed() { - return OriginalGroundSpeed * AttackChargeRate; + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + groundSpeed *= attackChargeRate; } function bool CanGetOutOfWay() { @@ -279,7 +275,6 @@ State SawingLoop // Randomly have the scrake charge during an attack so it will be less predictable if(Health/HealthMax < 0.5 || FRand() <= 0.95) { - SetGroundSpeed(OriginalGroundSpeed * AttackChargeRate); bCharging = true; if( Level.NetMode!=NM_DedicatedServer ) PostNetReceive(); @@ -327,8 +322,6 @@ State SawingLoop { AmbientSound=default.AmbientSound; MeleeDamage = Max( DifficultyDamageModifer() * default.MeleeDamage, 1 ); - - SetGroundSpeed(GetOriginalGroundSpeed()); bCharging = False; if(Level.NetMode != NM_DedicatedServer) PostNetReceive(); diff --git a/sources/Zeds/Nice/NiceZombieScrakeBase.uc b/sources/Zeds/Nice/NiceZombieScrakeBase.uc index 6ccd9f6..2905831 100644 --- a/sources/Zeds/Nice/NiceZombieScrakeBase.uc +++ b/sources/Zeds/Nice/NiceZombieScrakeBase.uc @@ -63,6 +63,8 @@ defaultproperties HealthMax=1000.000000 Health=1000 HeadHeight=2.200000 + maxStoppingEffect=0.15 + minStoppingThreshold=0.15 MenuName="Nice Scrake" MovementAnims(0)="SawZombieWalk" MovementAnims(1)="SawZombieWalk" diff --git a/sources/Zeds/Nice/NiceZombieShiver.uc b/sources/Zeds/Nice/NiceZombieShiver.uc index fbd612a..72c110e 100644 --- a/sources/Zeds/Nice/NiceZombieShiver.uc +++ b/sources/Zeds/Nice/NiceZombieShiver.uc @@ -179,7 +179,6 @@ state Running Global.Tick(Delta); if (RunUntilTime < Level.TimeSeconds) GotoState(''); - GroundSpeed = GetOriginalGroundSpeed(); } function BeginState() { @@ -190,13 +189,12 @@ state Running function EndState() { bRunning = false; - GroundSpeed = global.GetOriginalGroundSpeed(); RunCooldownEnd = Level.TimeSeconds + PeriodRunCoolBase + FRand() * PeriodRunCoolRan; MovementAnims[0] = WalkAnim; } - function float GetOriginalGroundSpeed() - { - return global.GetOriginalGroundSpeed() * 2.5; + simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + groundSpeed *= 2.5; } function bool CanSpeedAdjust() { @@ -219,14 +217,6 @@ simulated function bool AnimNeedsWait(name TestAnim) } return ExpectingChannel == 0; } -simulated function float GetOriginalGroundSpeed() -{ - local float result; - result = OriginalGroundSpeed; - if( bZedUnderControl ) - result *= 1.25; - return result; -} simulated function HandleAnimation(float Delta) { // hehehe diff --git a/sources/Zeds/Nice/NiceZombieSiren.uc b/sources/Zeds/Nice/NiceZombieSiren.uc index ad5b69b..1ea867c 100644 --- a/sources/Zeds/Nice/NiceZombieSiren.uc +++ b/sources/Zeds/Nice/NiceZombieSiren.uc @@ -281,6 +281,12 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class 0){ currScreamTime = Level.TimeSeconds - screamStartTime; diff --git a/sources/Zeds/Nice/NiceZombieTeslaHusk.uc b/sources/Zeds/Nice/NiceZombieTeslaHusk.uc index 030c45f..ff60b33 100644 --- a/sources/Zeds/Nice/NiceZombieTeslaHusk.uc +++ b/sources/Zeds/Nice/NiceZombieTeslaHusk.uc @@ -709,7 +709,6 @@ defaultproperties HealEnergyDrain=0.200000 ProjectileFireInterval=5.000000 BurnDamageScale=1.000000 - mind=0.000000 bFireImmune=False MoanVoice=SoundGroup'KF_EnemiesFinalSnd_CIRCUS.Husk.Husk_Talk' BleedOutDuration=5.000000 diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 85b79d9..0c13d76 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -24,6 +24,7 @@ class NiceMonster extends KFMonster #exec OBJ LOAD FILE=KF_EnemyGlobalSndTwo.uax #exec OBJ LOAD FILE=KFZED_FX_T.utx +var bool initializationComplete; //============================================================================== //============================================================================== // > Affliction system @@ -75,13 +76,15 @@ var float stunLoopStart, stunLoopEnd, idleInsertFrame; var bool bWasIdleStun; // Were we using idleanimation for stun? var float prevStunAnimFrame; // At which tick we were? //============================================================================== -// >> Another default stun system allows tostuns zeds by repeatedly dealing +// >> Another default stun system allows to stun zeds by repeatedly dealing // head damage to them fast enough: // 1. Dealing head damage increases accumulated damage // 2. If head damage was received for a certain time period, - // accumulated damage starts to decrease // 3. If accumulated damage is high enough, passes 'IsStunPossible' check -// and has low enough mind level - normal duration stun activates +// - normal duration stun activates +// How much more time will this zed spend concussed? +var float concussionCountdown; // Accumulated head damage var float accHeadDamage; // Rate (per second) at which accumulated head damage diminishes @@ -91,16 +94,6 @@ var float headRecoveryTime; // Count down variable for above mentioned time var float headRecoveryCountDown; -//============================================================================== -//============================================================================== -// > Mind system -// Largly underdeveloped and currently only exists to decide whether or not -// zed can be stunned by accumulating head damage -// Current mind level (1.0 - default and maximum value) -var float mind; -// Treshold, required for stun by accumulated head damage -var float accStunMindLvl; - //============================================================================== //============================================================================== // > Temperature system @@ -148,16 +141,14 @@ var bool bFrugalFuelUsage; // Is a value from 0.0 to 1.0 and `1 - stoppingEffect` acts as speed multiplier // for the zed var float stoppingEffect; -// (Absolute) Point in time at which recovery would start, updated when zeds -// receives another stopping effect from somewhere -var float stoppingRecoveryStartTime; -// How much stopping effect would be rcovred in a second +// How much stopping effect would be recovred in a second var float stoppingRecoveryRate; -// Maximum stopping effect this zed can tank +// Maximum `stoppingEffect` value zed can accumulate var float maxStoppingEffect; // Minimal stopping threshold for the zed (supposed to be subtracted from // incoming effects' strenght). var float minStoppingThreshold; + //============================================================================== //============================================================================== // > Miscellaneous variables @@ -241,6 +232,7 @@ simulated function PostBeginPlay(){ SavedExtCollision = MyExtCollision.bCollideActors; } } + initializationComplete = true; } //============================================================================== @@ -381,6 +373,15 @@ simulated function FearTick(float deltaTime){ + 0.75 * accelRate * Normal(Location - fearCenter); } //============================================================================== +// >> Decrease active stopping power on the zed as the time goes by +simulated function StoppingPowerTick(float deltaTime) { + if (stoppingEffect <= 0.0 || concussionCountdown > 0.0) { + return; + } + stoppingEffect -= deltaTime * stoppingRecoveryRate; + stoppingEffect = FMax(0, stoppingEffect); +} +//============================================================================== // >> Set of functions to handle animation changes during stun simulated function CalcRemainigStunStructure( name seqName, float oFrame, @@ -470,14 +471,14 @@ simulated function StunTick(float deltaTime){ } //============================================================================== // >> Set of functions to handle stun from head damage accumulation -function AccumulateHeadDamage( float addDamage, +function AccumulateHeadDamage( float addDamage, bool bIsHeadshot, NicePlayerController nicePlayer){ if(bIsHeadshot){ AccHeadDamage += addDamage; HeadRecoveryCountDown = HeadRecoveryTime; if(AccHeadDamage > (default.HeadHealth / 1.5) - && (Mind <= AccStunMindLvl && IsStunPossible())) + && (concussionCountdown > 0.0 && IsStunPossible())) DoStun(nicePlayer.pawn,,,, 1.0); } else if(HeadRecoveryCountDown > 0.0) @@ -485,11 +486,13 @@ function AccumulateHeadDamage( float addDamage, HeadRecoveryTime / 2); } function HeadDamageRecoveryTick(float delta){ - HeadRecoveryCountDown -= delta; - HeadRecoveryCountDown = FMax(0.0, HeadRecoveryCountDown); - if(HeadRecoveryCountDown <= 0.0) - AccHeadDamage -= delta * HeadDamageRecoveryRate; - AccHeadDamage = FMax(AccHeadDamage, 0.0); + concussionCountdown -= delta; + concussionCountdown = FMax(0.0, concussionCountdown); + headRecoveryCountDown -= delta; + headRecoveryCountDown = FMax(0.0, headRecoveryCountDown); + if(headRecoveryCountDown <= 0.0) + accHeadDamage -= delta * HeadDamageRecoveryRate; + accHeadDamage = FMax(accHeadDamage, 0.0); } //============================================================================== // >> Function that calls actual 'HeatTick' when needed @@ -546,15 +549,6 @@ simulated function FakeHeatTick(float deltaTime){ // >> Ticks from TWI's code // Updates zed's speed if it's not relevant; // code, specific to standalone game and listen servers was cut out -simulated function NonRelevantSpeedupTick(float deltaTime){ - if(Level.netMode == NM_Client || !CanSpeedAdjust()) return; - if(Level.TimeSeconds - LastReplicateTime > 0.5) - SetGroundSpeed(default.GroundSpeed * (300.0 / default.GroundSpeed)); - else{ - LastSeenOrRelevantTime = Level.TimeSeconds; - SetGroundSpeed(GetOriginalGroundSpeed()); - } -} // Kill zed if it has been bleeding long enough simulated function BleedOutTick(float deltaTick) @@ -605,7 +599,6 @@ simulated function TWITick(float deltaTime){ // If we've flagged this character to be destroyed next tick, handle that if(bDestroyNextTick && TimeSetDestroyNextTickTime < Level.TimeSeconds) Destroy(); - NonRelevantSpeedupTick(deltaTime); // Reset AnimAction if(bResetAnimAct && ResetAnimActTime < Level.TimeSeconds){ AnimAction = ''; @@ -628,8 +621,10 @@ simulated function Tick(float deltaTime){ DecapTick(deltaTime); FearTick(deltaTime); StunTick(deltaTime); + StoppingPowerTick(deltaTime); HeadDamageRecoveryTick(deltaTime); FakeHeatTick(deltaTime); + UpdateGroundSpeed(); // TWI's tick TWITick(deltaTime); } @@ -1613,7 +1608,7 @@ function UnFreeze(){ GroundSpeed = GetOriginalGroundSpeed(); bFrozenZed = false; } -function TakeDamageClient( int damage, +function TakeDamageClient( int damage, Pawn instigatedBy, Vector hitLocation, Vector momentum, @@ -1632,22 +1627,24 @@ function TakeDamageClient( int damage, KFPRI = KFPlayerReplicationInfo(instigatedBy.PlayerReplicationInfo); if(headHealth <= 0) headshotLevel = 0.0; + // Handle special weapon effects + HandleStoppingPower(damageType, headshotLevel); // Handle elemental damage components - ExtractElementalDamage( regDamage, heatDamage, damage, + ExtractElementalDamage(regDamage, heatDamage, damage, instigatedBy, hitLocation, momentum, damageType, KFPRI, headshotLevel, lockonTime); - FireDamageEffects( HeatDamage, instigatedBy, hitLocation, momentum, + FireDamageEffects( HeatDamage, instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI); - FrostEffects( instigatedBy, hitLocation, momentum, + FrostEffects( instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI); // Handle body parts damage components - ExtractPartsDamage( bodyDamage, headDamage, painDamage, + ExtractPartsDamage( bodyDamage, headDamage, painDamage, RegDamage + HeatDamage, instigatedBy, hitLocation, momentum, damageType, KFPRI, headshotLevel, lockonTime); - DoRightPainReaction( painDamage, instigatedBy, hitLocation, momentum, + DoRightPainReaction( painDamage, instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI); - DealPartsDamage( bodyDamage, headDamage, instigatedBy, + DealPartsDamage( bodyDamage, headDamage, instigatedBy, hitLocation, momentum, damageType, KFPRI, headshotLevel, lockonTime); AddKillAssistant(instigatedBy, bodyDamage); @@ -1658,6 +1655,28 @@ function TakeDamageClient( int damage, // like why the fuck is it being done HERE? Makes no fucking sense bBackstabbed = false; } +function HandleStoppingPower( + class damageType, + float headshotLevel +) { + local float strength; + local float actualMinStoppingThreshold, actualMaxStoppingEffect; + + strength = damageType.default.stoppingPower; + if (headshotLevel > 0.0) { + strength *= 2; + } + if (concussionCountdown > 0) { + actualMinStoppingThreshold = FMax(0.0, minStoppingThreshold - 0.2); + actualMaxStoppingEffect = FMin(0.9, maxStoppingEffect + 0.2); + } + else { + actualMinStoppingThreshold = minStoppingThreshold; + actualMaxStoppingEffect = maxStoppingEffect; + } + strength = FMax(0, strength - actualMinStoppingThreshold); + stoppingEffect = FMin(actualMaxStoppingEffect, stoppingEffect + strength); +} function TakeDamage(int damage, Pawn instigatedBy, Vector hitLocation, @@ -1798,7 +1817,6 @@ simulated function UnSetBurningBehavior(){ if(Role == Role_Authority){ Intelligence = default.Intelligence; if(!bZapped){ - SetGroundSpeed(GetOriginalGroundSpeed()); AirSpeed = default.AirSpeed; WaterSpeed = default.WaterSpeed; } @@ -1810,6 +1828,39 @@ simulated function UnSetBurningBehavior(){ WalkAnims[i] = default.WalkAnims[i]; } } +simulated function SetGroundSpeed(float newGroundSpeed) { + if (initializationComplete) { + UpdateGroundSpeed(); + } else { + // Let `KFMonster`'s code setup original speed for this zed. + // This is a hack to be removed later, when we'll be untangling + // initialization code + super.SetGroundSpeed(newGroundSpeed); + } +} +simulated function UpdateGroundSpeed() { + if (TryNonRelevantSpeedup()) { + return; + } + groundSpeed = GetOriginalGroundSpeed(); + groundSpeed *= (1.0 - stoppingEffect); + if (bDecapitated) { + groundSpeed *= 0.8; + } +} +// If this function returns `true`, then we shouldn't touch speed further, +// because a speed hack was used for the zed +simulated function bool TryNonRelevantSpeedup(){ + if(level.netMode == NM_Client || !CanSpeedAdjust()) { + return false; + } + if(level.timeSeconds - lastReplicateTime > 0.5) { + groundSpeed = default.groundSpeed * (300.0 / default.groundSpeed); + return true; + } + lastSeenOrRelevantTime = level.timeSeconds; + return false; +} simulated function ServerDropFaster(NiceHumanPawn nicePawn){ if(nicePawn == none) return; if(Health > 0) @@ -1827,7 +1878,7 @@ simulated function RemoveHead(){ if(kfDmgType != none && kfDmgType.default.bIsMeleeDamage) bMeleeDecapitated = true; SetAnimAction('HitF'); - SetGroundSpeed(GroundSpeed *= 0.80); + UpdateGroundSpeed(); // No more raspy breathin'...cuz he has no throat or mouth :S AmbientSound = MiscSound; if(Health > 0) @@ -2220,8 +2271,6 @@ defaultproperties lastStunTime=-1.000000 headDamageRecoveryRate=100.000000 headRecoveryTime=1.000000 - mind=1.000000 - accStunMindLvl=0.500000 bCanBurn=True fuelRatio=0.750000 heatDissipationRate=0.666000 @@ -2236,9 +2285,8 @@ defaultproperties RagdollLifeSpan=120.000000 ControllerClass=class'NiceMonsterController' stoppingEffect=0.0 - stoppingRecoveryStartTime=2.0 - stoppingRecoveryRate=0.5 - maxStoppingEffect=0.5 + stoppingRecoveryRate=0.025 + maxStoppingEffect=0.25 minStoppingThreshold=0.0 Begin Object Class=KarmaParamsSkel Name=KarmaParamsSkelN KConvulseSpacing=(Max=2.200000) From e79d49ce0d7132a3bf2f39bd410f34a9e9e5f034 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 23 Apr 2024 23:24:11 +0700 Subject: [PATCH 22/46] Change explosives mechanics --- sources/NiceReplicationInfo.uc | 38 +++--- sources/NiceRules.uc | 2 +- sources/Weapons/NiceBulletAdapter.uc | 4 +- .../Playable/Explosives/LAW/NiceLAWFire.uc | 2 +- sources/Weapons/Playable/Grenades/NiceNade.uc | 126 +++--------------- sources/Zeds/NiceMonster.uc | 16 +++ 6 files changed, 65 insertions(+), 123 deletions(-) diff --git a/sources/NiceReplicationInfo.uc b/sources/NiceReplicationInfo.uc index 2da7241..5c0c9b7 100644 --- a/sources/NiceReplicationInfo.uc +++ b/sources/NiceReplicationInfo.uc @@ -71,6 +71,7 @@ simulated function CalculateDamageScales( out float scale1, out float scale2, local Vector victimPoint1, victimPoint2; local float swap; victimPoint1 = victim.location; + victimPoint2.z += victim.CollisionHeight * 0.25; victimPoint2 = victim.location; victimPoint2.z += victim.CollisionHeight * 0.75; scale1 = GetDamageScale(victim, explosionLocation, victimPoint1, @@ -93,9 +94,9 @@ simulated function ServerExplode float momentum, Vector explLocation, Pawn instigator, - optional bool allowDoubleExplosion, optional Actor explosionTarget, - optional vector explosiveDirection + optional vector explosiveDirection, + optional bool preventProximityHeadDamage ){ local Actor victim; local int numKilled; @@ -109,26 +110,33 @@ simulated function ServerExplode if(victim.role < ROLE_Authority) continue; if(ExtendedZCollision(victim) != none) continue; if(Trigger(victim) != none) continue; + + niceVictim = NiceMonster(victim); dirToVictim = Normal(victim.location - explLocation); hitLocation = victim.location - 0.5 * (victim.collisionHeight + victim.collisionRadius) * dirToVictim; CalculateDamageScales( scale1, scale2, victim, explLocation, explRadius, explExp); + // Deal head damage if explosion is close enough to the victim's head + if ( niceVictim != none && !preventProximityHeadDamage + && niceVictim.GetDistanceToHead(explLocation) <= explRadius * 0.1) + { + ServerDealDamage( victim, explDamage, instigator, + hitLocation, 0.0 * dirToVictim, + explDmgType, 0.5); + } // Deal main damage - if(scale1 > 0){ - ServerDealDamage( victim, explDamage * scale1, instigator, - hitLocation, scale1 * momentum * dirToVictim, - explDmgType); + if(scale1 > 0 || scale2 > 0) { + ServerDealDamage( + victim, + explDamage * FMax(scale1, scale2), + instigator, + hitLocation, + FMax(scale1, scale2) * momentum * dirToVictim, + explDmgType); } - // Deal secondary damage - if(allowDoubleExplosion && victim != none && scale2 > 0){ - ServerDealDamage( victim, explDamage * scale2, instigator, - hitLocation, scale2 * momentum * dirToVictim, - explDmgType); - } - niceVictim = NiceMonster(victim); - if(NiceMonster(victim) != none) { - if (NiceMonster(victim).health <= 0) { + if(niceVictim != none) { + if (niceVictim.health <= 0) { numKilled += 1; } else { diff --git a/sources/NiceRules.uc b/sources/NiceRules.uc index b2defeb..e94c7df 100644 --- a/sources/NiceRules.uc +++ b/sources/NiceRules.uc @@ -128,7 +128,7 @@ function bool PreventDeath(Pawn Killed, Controller Killer, class dam class'NiceSkillDemoReactiveArmor'.default.explExponent, class'NiceDamTypeDemoSafeExplosion', class'NiceSkillDemoReactiveArmor'.default.explMomentum, - killed.location, killed, true + killed.location, killed ); return true; } diff --git a/sources/Weapons/NiceBulletAdapter.uc b/sources/Weapons/NiceBulletAdapter.uc index 4234c72..beb7401 100644 --- a/sources/Weapons/NiceBulletAdapter.uc +++ b/sources/Weapons/NiceBulletAdapter.uc @@ -28,9 +28,9 @@ static function Explode( bullet.charExplosionMomentum, hitLocation, bullet.instigator, - true, explosionTarget, - Vector(bullet.Rotation) + Vector(bullet.Rotation), + bullet.bStuck ); if (KFMonster(bullet.base) != none && bullet.bStuck && bullet.bStuckToHead) { diff --git a/sources/Weapons/Playable/Explosives/LAW/NiceLAWFire.uc b/sources/Weapons/Playable/Explosives/LAW/NiceLAWFire.uc index 096355b..93016d8 100644 --- a/sources/Weapons/Playable/Explosives/LAW/NiceLAWFire.uc +++ b/sources/Weapons/Playable/Explosives/LAW/NiceLAWFire.uc @@ -19,7 +19,7 @@ defaultproperties StereoFireSoundRef="KF_LAWSnd.LAW_FireST" NoAmmoSoundRef="KF_LAWSnd.LAW_DryFire" DamageType=class'NiceDamTypeLAWBlunt' - DamageMax=750 + DamageMax=350 bSplashDamage=True bRecommendSplashDamage=True bWaitForRelease=True diff --git a/sources/Weapons/Playable/Grenades/NiceNade.uc b/sources/Weapons/Playable/Grenades/NiceNade.uc index 48b778b..b984b18 100644 --- a/sources/Weapons/Playable/Grenades/NiceNade.uc +++ b/sources/Weapons/Playable/Grenades/NiceNade.uc @@ -39,114 +39,32 @@ function TakeDamage(int Damage, Pawn InstigatedBy, Vector HitLocation, Vector Mo Explode(HitLocation, vect(0,0,1)); } } -simulated function HurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) -{ - local actor Victims; - local float damageScale, dist; - local vector dir; - local int NumKilled; - local KFMonster KFMonsterVictim; - local bool bMonster; - local Pawn P; - local KFPawn KFP; - local array CheckedPawns; - local int i; - local bool bAlreadyChecked; - local SRStatsBase Stats; - if ( bHurtEntry ) - return; - bHurtEntry = true; - - if( Role == ROLE_Authority && Instigator != none && Instigator.PlayerReplicationInfo != none ) - Stats = SRStatsBase(Instigator.PlayerReplicationInfo.SteamStatsAndAchievements); - - foreach CollidingActors (class 'Actor', Victims, DamageRadius, HitLocation) - { - P = none; - KFMonsterVictim = none; - bMonster = false; - KFP = none; - bAlreadyChecked = false; +simulated function HurtRadius( + float damageAmount, + float damageRadius, + class damageType, + float momentum, + Vector hitLocation +) { + local NicePlayerController niceController; + local NiceReplicationInfo niceRI; - // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag - if( (Victims != self) && (Hurtwall != Victims) && (Victims.Role == ROLE_Authority) && !Victims.IsA('FluidSurfaceInfo') - && ExtendedZCollision(Victims)==None ) - { - if( (Instigator==None || Instigator.Health<=0) && KFPawn(Victims)!=None ) - Continue; - dir = Victims.Location - HitLocation; - dist = FMax(1,VSize(dir)); - dir = dir/dist; - damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); + if (instigator == none) return; + niceController = NicePlayerController(instigator.controller); + if (niceController == none) return; + niceRI = niceController.niceRI; + if (niceRI == none) return; - if ( Instigator == None || Instigator.Controller == None ) - { - Victims.SetDelayedDamageInstigatorController( InstigatorController ); - } + Destroy(); - P = Pawn(Victims); - if( P != none ) { - for (i = 0; i < CheckedPawns.Length; i++) { - if (CheckedPawns[i] == P) { - bAlreadyChecked = true; - break; - } - } - if( bAlreadyChecked ) - continue; - CheckedPawns[CheckedPawns.Length] = P; - - KFMonsterVictim = KFMonster(Victims); - if( KFMonsterVictim != none && KFMonsterVictim.Health <= 0 ) - KFMonsterVictim = none; - - KFP = KFPawn(Victims); - - if( KFMonsterVictim != none ) { - damageScale *= KFMonsterVictim.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity)); - bMonster = true; // in case TakeDamage() and further Die() deletes the monster - } - else if( KFP != none ) { - damageScale *= KFP.GetExposureTo(Location + 15 * -Normal(PhysicsVolume.Gravity)); - } - - if ( damageScale <= 0) - continue; - } - if(NiceMonster(Victims) != none) - Victims.TakeDamage(damageScale * DamageAmount,Instigator,Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir - ,(damageScale * Momentum * dir), niceExplosiveDamage); - else - Victims.TakeDamage(damageScale * DamageAmount,Instigator,Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir - ,(damageScale * Momentum * dir), DamageType); - - if( bMonster && (KFMonsterVictim == none || KFMonsterVictim.Health < 1) ) { - NumKilled++; - } - - if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0) - { - Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, InstigatorController, DamageType, Momentum, HitLocation); - } - } - } - - if( Role == ROLE_Authority ) - { - if ( bBlewInHands && NumKilled >= 5 && Stats != none ) - class'ScrnAchievements'.static.ProgressAchievementByID(Stats.Rep, 'SuicideBomber', 1); - - if ( NumKilled >= 4 ) - { - KFGameType(Level.Game).DramaticEvent(0.05); - } - else if ( NumKilled >= 2 ) - { - KFGameType(Level.Game).DramaticEvent(0.03); - } - } - bHurtEntry = false; + niceRI.ServerExplode(damageAmount, + damageRadius, + 1.0, + niceExplosiveDamage, + momentum, + hitLocation, + instigator); } // Overridden to spawn different AvoidMarker simulated function HitWall( vector HitNormal, actor Wall ){ diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 0c13d76..e3776dc 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -681,6 +681,22 @@ simulated function float IsHeadshotClient( Vector Loc, return 1.0 - (distance / (headRadius * headScale * additionalScale)); return 0.0; } +// Calculates distance from `location` to this zed's head. +simulated function float GetDistanceToHead(Vector location) { + local Coords headBoneCoords; + local Vector headLocation; + + local Vector AToLineOrig; + local Vector lineDir; + + if(headBone == '') { + return 0.0; + } + headBoneCoords = GetBoneCoords(headBone); + headLocation = + headBoneCoords.Origin + headHeight * headScale * headBoneCoords.XAxis; + return VSize(location - headLocation); +} // In case of a future modifications: // check if it's a player doing damage before relying on it function ModDamage( out int damage, From 99aac4018227f7a1b2657fe8e4670b13effa299c Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 4 Aug 2024 10:56:50 +0700 Subject: [PATCH 23/46] Add update 13 to this branch --- sources/Perks/Commando/NiceVetCommando.uc | 8 +- .../BaseWeaponClasses/NiceScopedWeapon.uc | 46 +- sources/Weapons/NiceFire.uc | 1 + sources/Weapons/NiceWeapon.uc | 56 +- .../HFR/NiceDamTypeHFRAssaultRifle.uc | 19 - .../Playable/Incendiary/HFR/NiceHFR.uc | 520 +----------------- .../Playable/Incendiary/HFR/NiceHFRAmmo.uc | 8 +- .../Incendiary/HFR/NiceHFRAmmoPickup.uc | 4 +- .../Playable/Incendiary/HFR/NiceHFRBullet.uc | 11 + .../Playable/Incendiary/HFR/NiceHFRPFire.uc | 23 +- .../Playable/Incendiary/HFR/NiceHFRPickup.uc | 11 +- .../Playable/Incendiary/HFR/NiceHFRTendril.uc | 2 +- sources/Zeds/Nice/NiceZombieBossBase.uc | 1 - sources/Zeds/Nice/NiceZombieCrawler.uc | 19 +- sources/Zeds/Nice/NiceZombieFleshPound.uc | 12 +- sources/Zeds/Nice/NiceZombieSiren.uc | 4 +- sources/Zeds/NiceMonster.uc | 176 +++--- 17 files changed, 254 insertions(+), 667 deletions(-) delete mode 100644 sources/Weapons/Playable/Incendiary/HFR/NiceDamTypeHFRAssaultRifle.uc create mode 100644 sources/Weapons/Playable/Incendiary/HFR/NiceHFRBullet.uc diff --git a/sources/Perks/Commando/NiceVetCommando.uc b/sources/Perks/Commando/NiceVetCommando.uc index b0f1658..65abf48 100644 --- a/sources/Perks/Commando/NiceVetCommando.uc +++ b/sources/Perks/Commando/NiceVetCommando.uc @@ -15,6 +15,12 @@ static function class GetNadeType(KFPlayerReplicationInfo KFPRI){ //return class'NiceMedicNadePoison'; return class'NiceNade'; } +static function int AddFireDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class DmgType){ + if(class(DmgType) != none){ + return float(InDamage) * 1.5; + } + return 0.0; +} static function float GetHealthBarsDistanceMulti(KFPlayerReplicationInfo KFPRI){ /*if(KFPRI != none && SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoStrategist')) return class'NiceSkillCommandoStrategist'.default.visionRadius;*/ @@ -112,7 +118,7 @@ defaultproperties OnHUDIcons(3)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Blue',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Blue',DrawColor=(B=255,G=255,R=255,A=255)) OnHUDIcons(4)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Purple',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Purple',DrawColor=(B=255,G=255,R=255,A=255)) OnHUDIcons(5)=(PerkIcon=Texture'ScrnTex.Perks.Perk_Commando_Orange',StarIcon=Texture'ScrnTex.Perks.Hud_Perk_Star_Orange',DrawColor=(B=255,G=255,R=255,A=255)) - CustomLevelInfo="Level up by doing damage with perked weapons|15% faster reload with all weapons|10% faster movement speed|You get four additional Zed-Time Extensions|See health and cloacked zeds from 16 meters distance|Better Syringe handling" + CustomLevelInfo="Level up by doing damage with perked weapons|15% faster reload with all weapons|10% faster movement speed|You get four additional Zed-Time Extensions|See health and cloaked zeds from 16 meters distance|Better Syringe handling" PerkIndex=3 OnHUDIcon=Texture'KillingFloorHUD.Perks.Perk_Commando' OnHUDGoldIcon=Texture'KillingFloor2HUD.Perk_Icons.Perk_Commando_Gold' diff --git a/sources/Weapons/BaseWeaponClasses/NiceScopedWeapon.uc b/sources/Weapons/BaseWeaponClasses/NiceScopedWeapon.uc index b5c5e03..009bf41 100644 --- a/sources/Weapons/BaseWeaponClasses/NiceScopedWeapon.uc +++ b/sources/Weapons/BaseWeaponClasses/NiceScopedWeapon.uc @@ -3,7 +3,7 @@ class NiceScopedWeapon extends NiceWeapon #exec OBJ LOAD FILE=ScopeShaders.utx #exec OBJ LOAD FILE=..\Textures\NicePackT.utx #exec OBJ LOAD FILE=ScrnWeaponPack_T.utx -#exec OBJ LOAD FILE=ScrnWeaponPack_A.ukx +#exec OBJ LOAD FILE=ScrnWeaponPack_A.ukx var() Material ZoomMat; var() Sound ZoomSound; var() int lenseMaterialID; // used since material id's seem to change alot @@ -18,31 +18,47 @@ var Shader ScopeScriptedShader; // The shader that combi var Material ScriptedTextureFallback; // The texture to render if the users system doesn't support shaders // new scope vars var Combiner ScriptedScopeCombiner; -var texture TexturedScopeTexture; +var Material TexturedScopeTexture; var bool bInitializedScope; // Set to true when the scope has been initialized var string ZoomMatRef; var string ScriptedTextureFallbackRef; -var texture CrosshairTex; +var Material CrosshairTex; var string CrosshairTexRef; + +static function Material PreloadUnknownMaterial(string reference) { + local Material result; + + // Try to load as various types of materials + result = FinalBlend(DynamicLoadObject(reference, class'FinalBlend', true)); + if(result != none) { + return result; + } + result = Combiner(DynamicLoadObject(reference, class'Combiner', true)); + if(result != none) { + return result; + } + result = Shader(DynamicLoadObject(reference, class'Shader', true)); + if(result != none) { + return result; + } + result = Texture(DynamicLoadObject(reference, class'Texture', true)); + if(result != none) { + return result; + } + result = Material(DynamicLoadObject(reference, class'Material')); + return result; +} + static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount){ local NiceScopedWeapon W; super.PreloadAssets(Inv, bSkipRefCount); if(default.ZoomMat == none && default.ZoomMatRef != ""){ - // Try to load as various types of materials - default.ZoomMat = FinalBlend(DynamicLoadObject(default.ZoomMatRef, class'FinalBlend', true)); - if(default.ZoomMat == none) - default.ZoomMat = Combiner(DynamicLoadObject(default.ZoomMatRef, class'Combiner', true)); - if(default.ZoomMat == none) - default.ZoomMat = Shader(DynamicLoadObject(default.ZoomMatRef, class'Shader', true)); - if(default.ZoomMat == none) - default.ZoomMat = Texture(DynamicLoadObject(default.ZoomMatRef, class'Texture', true)); - if(default.ZoomMat == none) - default.ZoomMat = Material(DynamicLoadObject(default.ZoomMatRef, class'Material')); + default.ZoomMat = PreloadUnknownMaterial(default.ZoomMatRef); } if(default.ScriptedTextureFallback == none && default.ScriptedTextureFallbackRef != "") - default.ScriptedTextureFallback = texture(DynamicLoadObject(default.ScriptedTextureFallbackRef, class'texture')); + default.ScriptedTextureFallback = PreloadUnknownMaterial(default.ScriptedTextureFallbackRef); if(default.CrosshairTex == none && default.CrosshairTexRef != "") - default.CrosshairTex = Texture(DynamicLoadObject(default.CrosshairTexRef, class'texture')); + default.CrosshairTex = PreloadUnknownMaterial(default.CrosshairTexRef); W = NiceScopedWeapon(Inv); if(W != none){ W.ZoomMat = default.ZoomMat; diff --git a/sources/Weapons/NiceFire.uc b/sources/Weapons/NiceFire.uc index bc253e4..82812b9 100644 --- a/sources/Weapons/NiceFire.uc +++ b/sources/Weapons/NiceFire.uc @@ -744,4 +744,5 @@ defaultproperties activeSpreadScale=1 spreadGainedPerShot=0 spreadLostPerSecond=0 + RecoilVelocityScale = 0 } diff --git a/sources/Weapons/NiceWeapon.uc b/sources/Weapons/NiceWeapon.uc index b975465..7cada8c 100644 --- a/sources/Weapons/NiceWeapon.uc +++ b/sources/Weapons/NiceWeapon.uc @@ -146,6 +146,7 @@ var bool bAutoReloadPaused; // This is used to 'pause' auto relo var float autoReloadPauseFrame; // Frame at which current pause began var bool bAutoReloadRateApplied; // Flag that remembers whether or not we've already applied reload speed up for current auto reload (to avoid constant animation's speed updates) var float autoReloadSpeedModifier; +var bool updatedDefaultReloadValues; // Acrtive reload-related variables // Active reload state enum EActiveReloadState{ @@ -219,6 +220,8 @@ static function bool UnloadAssets(){ return default.ReferenceCount == 0; } simulated function PostBeginPlay(){ + local float swapSpeedMod, reloadSpeedMod; + if(default.recordedZoomTime < 0) default.recordedZoomTime = ZoomTime; recordedZoomTime = default.recordedZoomTime; @@ -240,6 +243,31 @@ simulated function PostBeginPlay(){ if(FireModeClass[0] != none) stdFireRate = FireModeClass[0].default.fireRate; super.PostBeginPlay(); + // Hack solution - speed up reload and swap speed + swapSpeedMod = 2.0; + reloadSpeedMod = 1.5; + bringUpTime /= swapSpeedMod; + putDownTime /= swapSpeedMod; + selectAnimRate *= swapSpeedMod; + putDownAnimRate *= swapSpeedMod; + quickPutDownTime /= swapSpeedMod; + quickBringUpTime /= swapSpeedMod; + if (!default.updatedDefaultReloadValues) { + if(reloadType == RTYPE_AUTO) { + if (fireModeClass[0] != none) { + fireModeClass[0].default.FireAnimRate *= reloadSpeedMod; + } + if (fireModeClass[1] != none) { + fireModeClass[1].default.FireAnimRate *= reloadSpeedMod; + } + } else { + reloadRate /= reloadSpeedMod; + reloadAnimRate *= reloadSpeedMod; + default.reloadRate = reloadRate; + default.reloadAnimRate = reloadAnimRate; + } + default.updatedDefaultReloadValues = true; + } } // Allows to prevent leaving iron sights unwillingly @@ -1094,6 +1122,7 @@ simulated function int GetMagazineAmmo(){ else return MagAmmoRemaining; } + simulated function bool AllowReload(){ local int actualMagSize; actualMagSize = GetMagazineAmmo(); @@ -1127,6 +1156,7 @@ simulated function float GetCurrentReloadMult(){ local NiceHumanPawn nicePawn; local NicePlayerController nicePlayer; local class niceVet; + nicePawn = NiceHumanPawn(Instigator); nicePlayer = NicePlayerController(Instigator.Controller); if(nicePawn != none) @@ -1624,17 +1654,17 @@ simulated function float GetAmmoMulti() defaultproperties { - recordedZoomTime=-1.000000 - SecondaryCharge=1 - LaserAttachmentClass=Class'ScrnLaserAttachmentFirstPerson' - LaserDotClass=Class'ScrnLocalLaserDot' - LaserAttachmentBone="LightBone" - MagazineBone="Magazine" - bHasChargePhase=True - autoReloadSpeedModifier=1.000000 - bCanActiveReload=True - activeSlowdown=0.850000 - activeSpeedup=1.150000 - activeWindow=0.060000 - bModeZeroCanDryFire=True + recordedZoomTime=-1.000000 + SecondaryCharge=1 + LaserAttachmentClass=Class'ScrnLaserAttachmentFirstPerson' + LaserDotClass=Class'ScrnLocalLaserDot' + LaserAttachmentBone="LightBone" + MagazineBone="Magazine" + bHasChargePhase=True + autoReloadSpeedModifier=1.000000 + bCanActiveReload=True + activeSlowdown=0.850000 + activeSpeedup=1.150000 + activeWindow=0.060000 + bModeZeroCanDryFire=True } diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceDamTypeHFRAssaultRifle.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceDamTypeHFRAssaultRifle.uc deleted file mode 100644 index 4bd3a15..0000000 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceDamTypeHFRAssaultRifle.uc +++ /dev/null @@ -1,19 +0,0 @@ -class NiceDamTypeHFRAssaultRifle extends NiceDamTypeFire - abstract; -defaultproperties -{ - heatPart=0.500000 - HeadShotDamageMult=6.000000 - bCheckForHeadShots=True - WeaponClass=class'NiceHFR' - DeathString="%k killed %o (Horzine Flame Rifle)." - FemaleSuicide="%o shot herself in the foot." - MaleSuicide="%o shot himself in the foot." - bRagdollBullet=True - PawnDamageEmitter=Class'ROEffects.ROBloodPuff' - LowGoreDamageEmitter=Class'ROEffects.ROBloodPuffNoGore' - LowDetailEmitter=Class'ROEffects.ROBloodPuffSmall' - KDamageImpulse=5500.000000 - KDeathVel=175.000000 - KDeathUpKick=15.000000 -} diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFR.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFR.uc index 15a1683..e5d0d55 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFR.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFR.uc @@ -1,316 +1,5 @@ -// Modification of the AAR525 weapons by: [B.R]HekuT -class NiceHFR extends KFWeapon; -#exec OBJ LOAD FILE=KillingFloorWeapons.utx -#exec OBJ LOAD FILE=KillingFloorHUD.utx -#exec OBJ LOAD FILE=Inf_Weapons_Foley.uax -#exec OBJ LOAD FILE=KF_Weapons5_Scopes_Trip_T.utx -var() Material ZoomMat; -var() int lenseMaterialID; -var() float scopePortalFOVHigh; -var() float scopePortalFOV; -var() vector XoffsetScoped; -var() vector XoffsetHighDetail; -var() int scopePitch; -var() int scopeYaw; -var() int scopePitchHigh; -var() int scopeYawHigh; -var ScriptedTexture ScopeScriptedTexture; -var Shader ScopeScriptedShader; -var Material ScriptedTextureFallback; -var Combiner ScriptedScopeCombiner; -var Combiner ScriptedScopeStatic; -var texture TexturedScopeTexture; -var bool bInitializedScope; -var string ZoomMatRef; -var string ScriptedTextureFallbackRef; -static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount) -{ - super.PreloadAssets(Inv, bSkipRefCount); - default.ZoomMat = FinalBlend(DynamicLoadObject(default.ZoomMatRef, class'FinalBlend', true)); - default.ScriptedTextureFallback = texture(DynamicLoadObject(default.ScriptedTextureFallbackRef, class'texture', true)); - if ( M99SniperRifle(Inv) != none ) - { - M99SniperRifle(Inv).ZoomMat = default.ZoomMat; - M99SniperRifle(Inv).ScriptedTextureFallback = default.ScriptedTextureFallback; - } -} -static function bool UnloadAssets() -{ - if ( super.UnloadAssets() ) - { - default.ZoomMat = none; - default.ScriptedTextureFallback = none; - } - return true; -} -exec function pfov(int thisFOV) -{ - if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() ) - return; - scopePortalFOV = thisFOV; -} -exec function pPitch(int num) -{ - if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() ) - return; - scopePitch = num; - scopePitchHigh = num; -} -exec function pYaw(int num) -{ - if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() ) - return; - scopeYaw = num; - scopeYawHigh = num; -} -simulated exec function TexSize(int i, int j) -{ - if( !class'ROEngine.ROLevelInfo'.static.RODebugMode() ) - return; - ScopeScriptedTexture.SetSize(i, j); -} -simulated function bool ShouldDrawPortal() -{ - if( bAimingRifle ) - return true; - else - return false; -} -simulated function PostBeginPlay() -{ - super.PostBeginPlay(); - KFScopeDetail = class'KFMod.KFWeapon'.default.KFScopeDetail; - UpdateScopeMode(); -} -simulated function UpdateScopeMode() -{ - if (Level.NetMode != NM_DedicatedServer && Instigator != none && Instigator.IsLocallyControlled() && - Instigator.IsHumanControlled() ) - { - if( KFScopeDetail == KF_ModelScope ) - { - scopePortalFOV = default.scopePortalFOV; - ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV); - if (bAimingRifle) - { - PlayerViewOffset = XoffsetScoped; - } +class NiceHFR extends NiceScopedWeapon; - if( ScopeScriptedTexture == none ) - { - ScopeScriptedTexture = ScriptedTexture(Level.ObjectPool.AllocateObject(class'ScriptedTexture')); - } - - ScopeScriptedTexture.FallBackMaterial = ScriptedTextureFallback; - ScopeScriptedTexture.SetSize(512,512); - ScopeScriptedTexture.Client = Self; - - if( ScriptedScopeCombiner == none ) - { - ScriptedScopeCombiner = Combiner(Level.ObjectPool.AllocateObject(class'Combiner')); - ScriptedScopeCombiner.Material1 = Texture'KF_Weapons5_Scopes_Trip_T.Scope.MilDot'; - ScriptedScopeCombiner.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader'; - ScriptedScopeCombiner.CombineOperation = CO_Multiply; - ScriptedScopeCombiner.AlphaOperation = AO_Use_Mask; - ScriptedScopeCombiner.Material2 = ScopeScriptedTexture; - } - - if( ScopeScriptedShader == none ) - { - ScopeScriptedShader = Shader(Level.ObjectPool.AllocateObject(class'Shader')); - ScopeScriptedShader.Diffuse = ScriptedScopeCombiner; - ScopeScriptedShader.SelfIllumination = ScriptedScopeCombiner; - ScopeScriptedShader.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader'; - } - - bInitializedScope = true; - } - else if( KFScopeDetail == KF_ModelScopeHigh ) - { - scopePortalFOV = scopePortalFOVHigh; - ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOVHigh); - if (bAimingRifle) - { - PlayerViewOffset = XoffsetHighDetail; - } - - if( ScopeScriptedTexture == none ) - { - ScopeScriptedTexture = ScriptedTexture(Level.ObjectPool.AllocateObject(class'ScriptedTexture')); - } - ScopeScriptedTexture.FallBackMaterial = ScriptedTextureFallback; - ScopeScriptedTexture.SetSize(1024,1024); - ScopeScriptedTexture.Client = Self; - - if( ScriptedScopeCombiner == none ) - { - ScriptedScopeCombiner = Combiner(Level.ObjectPool.AllocateObject(class'Combiner')); - ScriptedScopeCombiner.Material1 = Texture'KF_Weapons5_Scopes_Trip_T.Scope.MilDot'; - ScriptedScopeCombiner.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader'; - ScriptedScopeCombiner.CombineOperation = CO_Multiply; - ScriptedScopeCombiner.AlphaOperation = AO_Use_Mask; - ScriptedScopeCombiner.Material2 = ScopeScriptedTexture; - } - - if( ScopeScriptedShader == none ) - { - ScopeScriptedShader = Shader(Level.ObjectPool.AllocateObject(class'Shader')); - ScopeScriptedShader.Diffuse = ScriptedScopeCombiner; - ScopeScriptedShader.SelfIllumination = ScriptedScopeCombiner; - ScopeScriptedShader.FallbackMaterial = Shader'ScopeShaders.Zoomblur.LensShader'; - } - - bInitializedScope = true; - } - else if (KFScopeDetail == KF_TextureScope) - { - ZoomedDisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV); - PlayerViewOffset.X = default.PlayerViewOffset.X; - - bInitializedScope = true; - } - } -} -simulated event RenderTexture(ScriptedTexture Tex) -{ - local rotator RollMod; - RollMod = Instigator.GetViewRotation(); - if(Owner != none && Instigator != none && Tex != none && Tex.Client != none) - Tex.DrawPortal(0,0,Tex.USize,Tex.VSize,Owner,(Instigator.Location + Instigator.EyePosition()), RollMod, scopePortalFOV ); -} -/** - * Handles all the functionality for zooming in including - * setting the parameters for the weapon, pawn, and playercontroller - * - * @param bAnimateTransition whether or not to animate this zoom transition - */ -simulated function ZoomIn(bool bAnimateTransition) -{ - super(BaseKFWeapon).ZoomIn(bAnimateTransition); - bAimingRifle = True; - if( KFHumanPawn(Instigator)!=none ) - KFHumanPawn(Instigator).SetAiming(True); - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ) - { - if( AimInSound != none ) - { - PlayOwnedSound(AimInSound, SLOT_Interact,,,,, false); - } - } -} -/** - * Handles all the functionality for zooming out including - * setting the parameters for the weapon, pawn, and playercontroller - * - * @param bAnimateTransition whether or not to animate this zoom transition - */ -simulated function ZoomOut(bool bAnimateTransition) -{ - super.ZoomOut(bAnimateTransition); - bAimingRifle = False; - if( KFHumanPawn(Instigator)!=none ) - KFHumanPawn(Instigator).SetAiming(False); - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ) - { - if( AimOutSound != none ) - { - PlayOwnedSound(AimOutSound, SLOT_Interact,,,,, false); - } - KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0); - } -} -simulated event OnZoomInFinished() -{ - local name anim; - local float frame, rate; - GetAnimParams(0, anim, frame, rate); - if (ClientState == WS_ReadyToFire) - { - if (anim == IdleAnim) - { - PlayIdle(); - } - } - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none && - KFScopeDetail == KF_TextureScope ) - { - KFPlayerController(Instigator.Controller).TransitionFOV(PlayerIronSightFOV,0.0); - } -} -simulated event RenderOverlays(Canvas Canvas) -{ - local int m; - local PlayerController PC; - if (Instigator == none) - return; - PC = PlayerController(Instigator.Controller); - if(PC == none) - return; - if(!bInitializedScope && PC != none ) - { - UpdateScopeMode(); - } - Canvas.DrawActor(none, false, true); - for (m = 0; m < NUM_FIRE_MODES; m++) - { - if (FireMode[m] != none) - { - FireMode[m].DrawMuzzleFlash(Canvas); - } - } - - SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self) ); - SetRotation( Instigator.GetViewRotation() + ZoomRotInterp); - PreDrawFPWeapon(); - - if(bAimingRifle && PC != none && (KFScopeDetail == KF_ModelScope || KFScopeDetail == KF_ModelScopeHigh)) - { - if (ShouldDrawPortal()) - { - if ( ScopeScriptedTexture != none ) - { - Skins[LenseMaterialID] = ScopeScriptedShader; - ScopeScriptedTexture.Client = Self; - ScopeScriptedTexture.Revision = (ScopeScriptedTexture.Revision +1); - } - } - - bDrawingFirstPerson = true; - Canvas.DrawBoundActor(self, false, false,DisplayFOV,PC.Rotation,rot(0,0,0),Instigator.CalcZoomedDrawOffset(self)); - bDrawingFirstPerson = false; - } - else if( KFScopeDetail == KF_TextureScope && PC.DesiredFOV == PlayerIronSightFOV && bAimingRifle) - { - Skins[LenseMaterialID] = ScriptedTextureFallback; - - SetZoomBlendColor(Canvas); - - Canvas.Style = ERenderStyle.STY_Normal; - Canvas.SetPos(0, 0); - Canvas.DrawTile(ZoomMat, (Canvas.SizeX - Canvas.SizeY) / 2, Canvas.SizeY, 0.0, 0.0, 8, 8); - Canvas.SetPos(Canvas.SizeX, 0); - Canvas.DrawTile(ZoomMat, -(Canvas.SizeX - Canvas.SizeY) / 2, Canvas.SizeY, 0.0, 0.0, 8, 8); - - Canvas.Style = 255; - Canvas.SetPos((Canvas.SizeX - Canvas.SizeY) / 2,0); - Canvas.DrawTile(ZoomMat, Canvas.SizeY, Canvas.SizeY, 0.0, 0.0, 1024, 1024); - - Canvas.Font = Canvas.MedFont; - Canvas.SetDrawColor(200,150,0); - - Canvas.SetPos(Canvas.SizeX * 0.16, Canvas.SizeY * 0.43); - Canvas.DrawText("Zoom: 3.0"); - - Canvas.SetPos(Canvas.SizeX * 0.16, Canvas.SizeY * 0.47); - } - else - { - Skins[LenseMaterialID] = ScriptedTextureFallback; - bDrawingFirstPerson = true; - Canvas.DrawActor(self, false, false, DisplayFOV); - bDrawingFirstPerson = false; - } -} simulated function float CalcAspectRatioAdjustedFOV(float AdjustFOV) { local KFPlayerController KFPC; @@ -333,204 +22,15 @@ simulated function float CalcAspectRatioAdjustedFOV(float AdjustFOV) return AdjustFOV; } } -simulated function AdjustIngameScope() -{ - local PlayerController PC; - if(Instigator == none || PlayerController(Instigator.Controller) == none) - return; - PC = PlayerController(Instigator.Controller); - if( !bHasScope ) - return; - switch (KFScopeDetail) - { - case KF_ModelScope: - if( bAimingRifle ) - DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV); - if ( PC.DesiredFOV == PlayerIronSightFOV && bAimingRifle ) - { - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ) - { - KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0); -} - } - break; - case KF_TextureScope: - if( bAimingRifle ) - DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV); - if ( bAimingRifle && PC.DesiredFOV != PlayerIronSightFOV ) - { - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ) - { - KFPlayerController(Instigator.Controller).TransitionFOV(PlayerIronSightFOV,0.0); - } - } - break; - - case KF_ModelScopeHigh: - if( bAimingRifle ) - { - if( ZoomedDisplayFOVHigh > 0 ) - { - DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOVHigh); - } - else - { - DisplayFOV = CalcAspectRatioAdjustedFOV(default.ZoomedDisplayFOV); - } - } - if ( bAimingRifle && PC.DesiredFOV == PlayerIronSightFOV ) - { - if( Level.NetMode != NM_DedicatedServer && KFPlayerController(Instigator.Controller) != none ) - { - KFPlayerController(Instigator.Controller).TransitionFOV(KFPlayerController(Instigator.Controller).DefaultFOV,0.0); - } - } - break; - } - UpdateScopeMode(); -} -simulated event Destroyed() -{ - if (ScopeScriptedTexture != none) - { - ScopeScriptedTexture.Client = none; - Level.ObjectPool.FreeObject(ScopeScriptedTexture); - ScopeScriptedTexture=none; - } - if (ScriptedScopeCombiner != none) - { - ScriptedScopeCombiner.Material2 = none; - Level.ObjectPool.FreeObject(ScriptedScopeCombiner); - ScriptedScopeCombiner = none; - } - if (ScopeScriptedShader != none) - { - ScopeScriptedShader.Diffuse = none; - ScopeScriptedShader.SelfIllumination = none; - Level.ObjectPool.FreeObject(ScopeScriptedShader); - ScopeScriptedShader = none; - } - Super.Destroyed(); -} -simulated function PreTravelCleanUp() -{ - if (ScopeScriptedTexture != none) - { - ScopeScriptedTexture.Client = none; - Level.ObjectPool.FreeObject(ScopeScriptedTexture); - ScopeScriptedTexture=none; - } - if (ScriptedScopeCombiner != none) - { - ScriptedScopeCombiner.Material2 = none; - Level.ObjectPool.FreeObject(ScriptedScopeCombiner); - ScriptedScopeCombiner = none; - } - if (ScopeScriptedShader != none) - { - ScopeScriptedShader.Diffuse = none; - ScopeScriptedShader.SelfIllumination = none; - Level.ObjectPool.FreeObject(ScopeScriptedShader); - ScopeScriptedShader = none; - } -} -state PendingClientWeaponSet -{ - simulated function Timer() - { - if ( Pawn(Owner) != none && !bIsReloading ) - { - ClientWeaponSet(bPendingSwitch); - } - - if ( IsInState('PendingClientWeaponSet') ) - { - SetTimer(0.1, false); - } - } - simulated function BeginState() - { - SetTimer(0.1, false); - } - simulated function EndState() - { - } -} -simulated function SetZoomBlendColor(Canvas c) -{ - local Byte val; - local Color clr; - local Color fog; - clr.R = 255; - clr.G = 255; - clr.B = 255; - clr.A = 255; - if( Instigator.Region.Zone.bDistanceFog ) - { - fog = Instigator.Region.Zone.DistanceFogColor; - val = 0; - val = Max( val, fog.R); - val = Max( val, fog.G); - val = Max( val, fog.B); - if( val > 128 ) - { - val -= 128; - clr.R -= val; - clr.G -= val; - clr.B -= val; - } - } - c.DrawColor = clr; -} -function bool RecommendRangedAttack() -{ - return true; -} -function float SuggestAttackStyle() -{ - return -1.0; -} -function bool RecommendLongRangedAttack() -{ - return true; -} -simulated function AnimEnd(int channel) -{ - if(!FireMode[1].IsInState('FireLoop')) - { - Super.AnimEnd(channel); - } -} -simulated function WeaponTick(float dt) -{ - Super.WeaponTick(dt); -} -simulated function bool StartFire(int Mode) -{ - if( Mode == 0 ) - return super.StartFire(Mode); - if( !super.StartFire(Mode) ) - return false; - - if( AmmoAmount(0) <= 0 ) - { - return false; - } - AnimStopLooping(); - if( !FireMode[Mode].IsInState('FireLoop') && (AmmoAmount(0) > 0) ) - { - FireMode[Mode].StartFiring(); - return true; - } - else - { - return false; - } - return true; -} defaultproperties { + reloadPreEndFrame=0.339 + reloadEndFrame=0.732 + reloadChargeEndFrame=-1.000000 + reloadMagStartFrame=0.643 + reloadChargeStartFrame=-1.000000 + magazineBone="Magazine" lenseMaterialID=3 scopePortalFOVHigh=22.000000 scopePortalFOV=12.000000 @@ -538,13 +38,13 @@ defaultproperties ScriptedTextureFallbackRef="NicePackT.HFR.CBLens_cmb" bHasScope=True ZoomedDisplayFOVHigh=35.000000 - MagCapacity=10 + MagCapacity=50 ReloadRate=3.000000 ReloadAnim="Reload" ReloadAnimRate=0.600000 WeaponReloadAnim="Reload_M4" bSteadyAim=True - Weight=7.000000 + Weight=5.000000 bHasAimingMode=True IdleAimAnim="Idle" StandardDisplayFOV=60.000000 @@ -562,7 +62,7 @@ defaultproperties PlayerIronSightFOV=65.000000 ZoomedDisplayFOV=32.000000 FireModeClass(0)=class'NiceHFRPFire' - FireModeClass(1)=class'NiceHFRBurstFire' + FireModeClass(1)=Class'KFMod.NoFire' PutDownAnim="PutDown" AIRating=0.700000 CurrentRating=0.700000 diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmo.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmo.uc index 2d11ca5..04466fc 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmo.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmo.uc @@ -1,10 +1,10 @@ -class NiceHFRAmmo extends KFAmmunition; +class NiceHFRAmmo extends NiceAmmo; #EXEC OBJ LOAD FILE=KillingFloorHUD.utx defaultproperties { - AmmoPickupAmount=15 - MaxAmmo=100 - InitialAmount=40 + AmmoPickupAmount=75 + MaxAmmo=300 + InitialAmount=75 PickupClass=class'NiceHFRAmmoPickup' IconMaterial=Texture'KillingFloorHUD.Generic.HUD' IconCoords=(X1=336,Y1=82,X2=382,Y2=125) diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmoPickup.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmoPickup.uc index 40d9353..6eeaba4 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmoPickup.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRAmmoPickup.uc @@ -1,7 +1,7 @@ -class NiceHFRAmmoPickup extends KFAmmoPickup; +class NiceHFRAmmoPickup extends NiceAmmoPickup; defaultproperties { - AmmoAmount=15 + AmmoAmount=50 InventoryType=class'NiceHFRAmmo' PickupMessage="Fire balloon" StaticMesh=StaticMesh'KillingFloorStatics.L85Ammo' diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRBullet.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRBullet.uc new file mode 100644 index 0000000..09fc990 --- /dev/null +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRBullet.uc @@ -0,0 +1,11 @@ +class NiceHFRBullet extends NiceBullet; + +defaultproperties +{ + bDisableComplexMovement=False + trailXClass=None + StaticMeshRef="ZED_FX_SM.Energy.ZED_FX_Energy_Card" + DrawScale=0.500000 + ambientSoundRef="KF_FY_ZEDV2SND.WEP_ZEDV2_Projectile_Loop" + explosionImpact=(bImportanEffect=True,decalClass=Class'KFMod.FlameThrowerBurnMark_Medium',EmitterClass=Class'KFMod.ZEDMKIIPrimaryProjectileImpact',emitterShiftWall=20.000000,emitterShiftPawn=20.000000,noiseRef="KF_FY_ZEDV2SND.WEP_ZEDV2_Projectile_Explode",noiseVolume=2.000000) +} diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc index 142fb8d..5601513 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc @@ -1,25 +1,29 @@ -class NiceHFRPFire extends KFFire; +class NiceHFRPFire extends NiceFire; + defaultproperties { + ProjectileSpeed=1000.000000 FireAimedAnim="Fire_Iron" - RecoilRate=0.120000 - maxVerticalRecoilAngle=500 + RecoilRate=0.070000 + maxVerticalRecoilAngle=70 + maxHorizontalRecoilAngle=35 bAccuracyBonusForSemiAuto=True bRandomPitchFireSound=False - FireSoundRef="KF_SP_LongmusketSnd.KFO_Sniper_Fire_M" - StereoFireSoundRef="KF_SP_LongmusketSnd.KFO_Sniper_Fire_S" - NoAmmoSoundRef="KF_AK47Snd.AK47_DryFire" - DamageType=class'NiceDamTypeHFRAssaultRifle' + FireSoundRef="KF_FY_ZEDV2SND.WEP_ZEDV2_Fire_M" + StereoFireSoundRef="KF_FY_ZEDV2SND.WEP_ZEDV2_Fire_S" + NoAmmoSoundRef="KF_ZEDGunSnd.KF_WEP_ZED_Dryfire" + DamageType=class'NiceDamTypeHFR' DamageMax=50 Momentum=8500.000000 - bWaitForRelease=True + bWaitForRelease=False TransientSoundVolume=1.200000 TransientSoundRadius=500.000000 FireLoopAnim="Fire" FireAnimRate=0.909000 TweenTime=0.025000 FireForce="AssaultRifleFire" - FireRate=0.600000 + FireRate=0.096000 + bulletClass=class'NiceHFRBullet' AmmoClass=class'NiceHFRAmmo' AmmoPerFire=1 ShakeRotMag=(X=50.000000,Y=50.000000,Z=350.000000) @@ -32,5 +36,4 @@ defaultproperties FlashEmitterClass=Class'ROEffects.MuzzleFlash1stSPSniper' aimerror=42.000000 Spread=0.015000 - SpreadStyle=SS_Random } diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPickup.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPickup.uc index 8fc434a..295e41d 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPickup.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPickup.uc @@ -1,18 +1,19 @@ -class NiceHFRPickup extends KFWeaponPickup; +class NiceHFRPickup extends NiceWeaponPickup; defaultproperties { - Weight=7.000000 - AmmoCost=30 - BuyClipSize=15 + Weight=5.000000 + AmmoCost=26 + BuyClipSize=50 PowerValue=100 SpeedValue=100 RangeValue=40 + cost=750 Description="Advanced horzine flame rifle." ItemName="Horzine flame rifle" ItemShortName="HFR" AmmoItemName="Fire balloon" AmmoMesh=StaticMesh'KillingFloorStatics.FT_AmmoMesh' - CorrespondingPerkIndex=5 + CorrespondingPerkIndex=3 EquipmentCategoryID=3 InventoryType=class'NiceHFR' PickupMessage="You got the HFR." diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRTendril.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRTendril.uc index c175971..4d6c567 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRTendril.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRTendril.uc @@ -1,6 +1,6 @@ class NiceHFRTendril extends FlameTendril; defaultproperties { - Damage=36.000000 + Damage=16.000000 MyDamageType=class'NiceDamTypeHFR' } diff --git a/sources/Zeds/Nice/NiceZombieBossBase.uc b/sources/Zeds/Nice/NiceZombieBossBase.uc index cd05c38..3e5eea6 100644 --- a/sources/Zeds/Nice/NiceZombieBossBase.uc +++ b/sources/Zeds/Nice/NiceZombieBossBase.uc @@ -52,7 +52,6 @@ defaultproperties ClawMeleeDamageRange=85.000000 ImpaleMeleeDamageRange=45.000000 fuelRatio=0.400000 - bFrugalFuelUsage=False clientHeadshotScale=1.200000 ZapThreshold=5.000000 ZappedDamageMod=1.250000 diff --git a/sources/Zeds/Nice/NiceZombieCrawler.uc b/sources/Zeds/Nice/NiceZombieCrawler.uc index a4ce6cf..43c0ad1 100644 --- a/sources/Zeds/Nice/NiceZombieCrawler.uc +++ b/sources/Zeds/Nice/NiceZombieCrawler.uc @@ -34,17 +34,20 @@ event Landed(vector HitNormal) } event Bump(actor Other) { + local int actualDamage; // TODO: is there a better way if(bPouncing && KFHumanPawn(Other)!=none ) { - KFHumanPawn(Other).TakeDamage(((MeleeDamage - (MeleeDamage * 0.05)) + (MeleeDamage * (FRand() * 0.1))), self ,self.Location,self.velocity, class'NiceZedMeleeDamageType'); - if (KFHumanPawn(Other).Health <=0) - { - //TODO - move this to humanpawn.takedamage? Also see KFMonster.MeleeDamageTarget - KFHumanPawn(Other).SpawnGibs(self.rotation, 1); - } - //After impact, there'll be no momentum for further bumps - bPouncing=false; + actualDamage = MeleeDamage; + ModDamageFromZed(actualDamage, class'NiceZedMeleeDamageType'); + KFHumanPawn(Other).TakeDamage(((actualDamage * 0.95) + (actualDamage * (FRand() * 0.1))), self ,self.Location,self.velocity, class'NiceZedMeleeDamageType'); + if (KFHumanPawn(Other).Health <=0) + { + //TODO - move this to humanpawn.takedamage? Also see KFMonster.MeleeDamageTarget + KFHumanPawn(Other).SpawnGibs(self.rotation, 1); + } + //After impact, there'll be no momentum for further bumps + bPouncing=false; } } // Blend his attacks so he can hit you in mid air. diff --git a/sources/Zeds/Nice/NiceZombieFleshPound.uc b/sources/Zeds/Nice/NiceZombieFleshPound.uc index 8d5056d..17c0fa5 100644 --- a/sources/Zeds/Nice/NiceZombieFleshPound.uc +++ b/sources/Zeds/Nice/NiceZombieFleshPound.uc @@ -441,7 +441,7 @@ function SpinDamage(actor Target) local vector HitLocation; local Name TearBone; local Float dummy; - local float DamageAmount; + local int damageAmount; local vector PushDir; local KFHumanPawn HumanTarget; if(target==none) @@ -456,8 +456,9 @@ function SpinDamage(actor Target) } if (Target !=none && Target.IsA('KFDoorMover')) { - Target.TakeDamage(DamageAmount , self ,HitLocation,pushdir, class'NiceZedMeleeDamageType'); - PlaySound(MeleeAttackHitSound, SLOT_Interact, 1.25); + ModDamageFromZed(DamageAmount, class'NiceZedMeleeDamageType'); + Target.TakeDamage(DamageAmount , self ,HitLocation,pushdir, class'NiceZedMeleeDamageType'); + PlaySound(MeleeAttackHitSound, SLOT_Interact, 1.25); } if (KFHumanPawn(Target)!=none) { @@ -465,8 +466,9 @@ function SpinDamage(actor Target) if (HumanTarget.Controller != none) HumanTarget.Controller.ShakeView(RotMag, RotRate, RotTime, OffsetMag, OffsetRate, OffsetTime); - //TODO - line below was KFPawn. Does this whole block need to be KFPawn, or is it OK as KFHumanPawn? - KFHumanPawn(Target).TakeDamage(DamageAmount, self ,HitLocation,pushdir, class'NiceZedMeleeDamageType'); + ModDamageFromZed(DamageAmount, class'NiceZedMeleeDamageType'); + //TODO - line below was KFPawn. Does this whole block need to be KFPawn, or is it OK as KFHumanPawn? + KFHumanPawn(Target).TakeDamage(DamageAmount, self ,HitLocation,pushdir, class'NiceZedMeleeDamageType'); if (KFHumanPawn(Target).Health <=0) { diff --git a/sources/Zeds/Nice/NiceZombieSiren.uc b/sources/Zeds/Nice/NiceZombieSiren.uc index 1ea867c..6f13cf4 100644 --- a/sources/Zeds/Nice/NiceZombieSiren.uc +++ b/sources/Zeds/Nice/NiceZombieSiren.uc @@ -223,7 +223,7 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class niceVet; @@ -266,7 +266,7 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class 0) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index e3776dc..e07c396 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -127,10 +127,7 @@ var float heatDissipationRate; var float heatTicksPerSecond; // Tracks last time heat tick occured var float lastHeatTick; -// If set to 'true' - low-value ticks of fire DoT will waste accordingly small -// amount of fuel, otherwise they will always waste some minimal amount, -// resulting in a loss of potential damage -var bool bFrugalFuelUsage; +var float MIN_HEAT, MAX_HEAT; //============================================================================== //============================================================================== @@ -475,7 +472,7 @@ function AccumulateHeadDamage( float addDamage, bool bIsHeadshot, NicePlayerController nicePlayer){ if(bIsHeadshot){ - AccHeadDamage += addDamage; + AccHeadDamage += addDamage * 0.5; HeadRecoveryCountDown = HeadRecoveryTime; if(AccHeadDamage > (default.HeadHealth / 1.5) && (concussionCountdown > 0.0 && IsStunPossible())) @@ -686,9 +683,6 @@ simulated function float GetDistanceToHead(Vector location) { local Coords headBoneCoords; local Vector headLocation; - local Vector AToLineOrig; - local Vector lineDir; - if(headBone == '') { return 0.0; } @@ -707,28 +701,28 @@ function ModDamage( out int damage, float headshotLevel, KFPlayerReplicationInfo KFPRI, optional float lockonTime){ - local NicePlayerController nicePlayer; - local bool hasGiantSlayer; - local int bonusDamageStacks; - if(KFPRI == none || KFPRI.ClientVeteranSkill == none) return; - // Add perked damage - damage = KFPRI.ClientVeteranSkill.Static.AddDamage( KFPRI, self, - KFPawn(instigatedBy), - damage, damageType); - // Skill bonuses - if(instigatedBy == none) - return; - nicePlayer = NicePlayerController(instigatedBy.controller); - if(nicePlayer == none) - return; - hasGiantSlayer = class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, - class'NiceSkillCommandoGiantSlayer'); - if(!hasGiantSlayer) - return; - bonusDamageStacks = - int(health / class'NiceSkillCommandoGiantSlayer'.default.healthStep); - damage *= 1.0f + bonusDamageStacks * - class'NiceSkillCommandoGiantSlayer'.default.bonusDamageMult; + local NicePlayerController nicePlayer; + local bool hasGiantSlayer; + local int bonusDamageStacks; + if(KFPRI == none || KFPRI.ClientVeteranSkill == none) return; + // Add perked damage + damage = KFPRI.ClientVeteranSkill.Static.AddDamage( KFPRI, self, + KFPawn(instigatedBy), + damage, damageType); + // Skill bonuses + if(instigatedBy == none) + return; + nicePlayer = NicePlayerController(instigatedBy.controller); + if(nicePlayer == none) + return; + hasGiantSlayer = class'NiceVeterancyTypes'.static.hasSkill(nicePlayer, + class'NiceSkillCommandoGiantSlayer'); + if(!hasGiantSlayer) + return; + bonusDamageStacks = + int(health / class'NiceSkillCommandoGiantSlayer'.default.healthStep); + damage *= 1.0f + bonusDamageStacks * + class'NiceSkillCommandoGiantSlayer'.default.bonusDamageMult; } function ModRegularDamage( out int damage, Pawn instigatedBy, @@ -750,9 +744,6 @@ function ModRegularDamage( out int damage, damage = niceVet.static.AddRegDamage( KFPRI, self, KFPawn(instigatedBy), damage, damageType); - // Add some damage against crispy zeds - if(bCrispified) - damage += (Max(1200 - default.Health, 0) * damage) / 1200; // Skills bonuses if(nicePlayer == none) return; hasOverkillSkill = class'NiceVeterancyTypes'.static. @@ -841,13 +832,15 @@ function int ModBodyDamage( out int damage, return painDamage; } // Do effects, based on fire damage dealt to monster -function FireDamageEffects( int damage, +function FireDamageEffects(out int damage, Pawn instigatedBy, Vector hitLocation, Vector momentum, class damageType, float headshotLevel, KFPlayerReplicationInfo KFPRI){ + local float heatDelta, bonusFireDamage; + local bool shouldBeSetOnFire, isFireWeapon; damage = FMax(0.0, damage); iceCrustStrenght = FMax(0.0, iceCrustStrenght); if(bFrozenZed){ @@ -865,24 +858,39 @@ function FireDamageEffects( int damage, } damage /= 10; } - if(damage <= 0) return; + if(damage <= 0) { + return; + } // Turn up the heat! // (we can only make it twice as hot with that damage, // but set limit at least at 50, as if we've dealt at least 25 heat damage) - heat += (damage * HeatIncScale()) + heatDelta = (damage * HeatIncScale()) * FMin(1.0, FMax(0.0, (2 - Abs(heat) / FMax(25, Abs(damage) )))); + if (concussionCountdown > 0) { + heat += heatDelta * 2; + } else { + heat += heatDelta; + } CapHeat(); // Change damage type if new one was stronger if(!bOnFire || damage * HeatIncScale() > lastBurnDamage){ fireDamageClass = damageType; burnInstigator = instigatedBy; } + // Double heat damage at the cost of the fuel, if zed is already on fire + isFireWeapon = (damageType.default.heatPart >= 0.75); + if (bOnFire && isFireWeapon) { + bonusFireDamage = FMax(FMin(damage, flameFuel), 0); + flameFuel -= bonusFireDamage; + damage += bonusFireDamage; + } // Set on fire, if necessary - if(heat > GetIgnitionPoint() && !bOnFire && bCanBurn){ + shouldBeSetOnFire = (heat > GetIgnitionPoint()) || isFireWeapon; + if(shouldBeSetOnFire && !bOnFire && bCanBurn){ bBurnified = true; bOnFire = true; burnInstigator = instigatedBy; - fireDamageClass = damageType; + fireDamageClass = damageType; lastHeatTick = Level.TimeSeconds; } } @@ -1017,6 +1025,10 @@ function DealHeadDamage( int damage, // Actual damage effects // Skull injury killed a zed if(HeadHealth <= 0) return; + // Additional weakpoint damage to burning zeds from non-flame weapons + if (bOnFire && damageType.default.heatPart < 0.75) { + damage += 100; + } HeadHealth -= damage; if(nicePlayer != none && IsFinisher(damage, damageType, nicePlayer, true)) HeadHealth -= damage; @@ -1199,6 +1211,9 @@ function EPainReaction GetRightPainReaction(int painDamage, local int stunScore, flinchScore; local bool bStunPass, bFlinchPass, bMiniFlinshPass; local class niceVet; + if (bOnFire) { + return PREACTION_NONE; + } if(KFPRI != none) niceVet = class(KFPRI.ClientVeteranSkill); stunScore = painDamage; @@ -1649,8 +1664,8 @@ function TakeDamageClient( int damage, ExtractElementalDamage(regDamage, heatDamage, damage, instigatedBy, hitLocation, momentum, damageType, KFPRI, headshotLevel, lockonTime); - FireDamageEffects( HeatDamage, instigatedBy, hitLocation, momentum, - damageType, headshotLevel, KFPRI); + FireDamageEffects(HeatDamage, instigatedBy, hitLocation, + momentum, damageType, headshotLevel, KFPRI); FrostEffects( instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI); // Handle body parts damage components @@ -1660,9 +1675,9 @@ function TakeDamageClient( int damage, headshotLevel, lockonTime); DoRightPainReaction( painDamage, instigatedBy, hitLocation, momentum, damageType, headshotLevel, KFPRI); - DealPartsDamage( bodyDamage, headDamage, instigatedBy, - hitLocation, momentum, damageType, KFPRI, - headshotLevel, lockonTime); + DealPartsDamage( bodyDamage, headDamage, + instigatedBy, hitLocation, momentum, damageType, + KFPRI, headshotLevel, lockonTime); AddKillAssistant(instigatedBy, bodyDamage); // Rewrite values of last deal damage, instigator, etc. UpdateLastDamageVars( instigatedBy, bodyDamage, damageType, @@ -1738,15 +1753,12 @@ function TakeDamage(int damage, } } function TakeFireDamage(int damage, Pawn instigator){ - local bool bLowFuel, bHighHeat; local Vector DummyHitLoc, DummyMomentum; super(Skaarj).TakeDamage( damage, instigator, dummyHitLoc, dummyMomentum, fireDamageClass); lastBurnDamage = damage; // Melt em' :) - bHighHeat = heat > default.health / 20; - bLowFuel = FlameFuel < 0.75 * InitFlameFuel; - if(FlameFuel <= 0 || bHighHeat && bLowFuel) + if(FlameFuel <= 0) ZombieCrispUp(); } function TakeFrostDamage(int damage, Pawn instigator){ @@ -1769,34 +1781,43 @@ simulated function ZombieCrispUp(){ Skins[3]=Combiner'PatchTex.Common.BurnSkinEmbers_cmb'; } simulated function HeatTick(){ - local float iceDamage; + local float iceDamage, heatDamage; + // Update heat value if(!bOnFire || flameFuel <= 0) heat *= heatDissipationRate; - else{ - if(flameFuel < heat) - heat = flameFuel * 1.1 + (heat - flameFuel) * heatDissipationRate; - else + else { + if(flameFuel < heat) { + heat = flameFuel * 1.1 + (heat - flameFuel) * heatDissipationRate; + } else { heat = heat * 1.1; - if(bFrugalFuelUsage) - flameFuel -= heat; - else - flameFuel -= FMax(heat, InitFlameFuel / 15); + } + if (flameFuel >= 0) { + // Burning always deals at least 5% damage (of the total fuel), + // up to additional 5%, depending on the heat levels. + heatDamage = 5 + 5 * FMin(heat, flameFuel) / initFlameFuel; // calc % + heatDamage = FMin(flameFuel, healthMax * heatDamage / 100.0); + flameFuel -= heatDamage; + } else { + // 5 damage for burning without fuel + heatDamage = 5.0; + } } CapHeat(); if(Abs(heat) < 1) heat = 0.0; // Update on-fire status if(bOnFire){ - if(heat > 0) - TakeFireDamage(heat + rand(5), burnInstigator); - else{ - bBurnified = false; - UnSetBurningBehavior(); - RemoveFlamingEffects(); - StopBurnFX(); - bOnFire = false; - } + if(heat > 0) { + TakeFireDamage(heatDamage, burnInstigator); + } + else { + bBurnified = false; + UnSetBurningBehavior(); + RemoveFlamingEffects(); + StopBurnFX(); + bOnFire = false; + } } // Update frozen status (always deal frost damage) iceCrustStrenght = FMax(iceCrustStrenght, heat); @@ -1815,9 +1836,9 @@ simulated function HeatTick(){ } simulated function SetBurningBehavior(){ bBurningBehavior = true; - if(default.Health >= 1000) return; - if(Role == Role_Authority) - Intelligence = BRAINS_Retarded; + if(default.Health >= 1000) { + return; + } MovementAnims[0] = BurningWalkFAnims[Rand(3)]; WalkAnims[0] = BurningWalkFAnims[Rand(3)]; MovementAnims[1] = BurningWalkAnims[0]; @@ -1863,6 +1884,17 @@ simulated function UpdateGroundSpeed() { if (bDecapitated) { groundSpeed *= 0.8; } + if (bCrispified) { + groundSpeed *= 1.25; + } +} +simulated function ModDamageFromZed( + out int damage, + class damageType +) { + if (bCrispified) { + damage *= 2; + } } // If this function returns `true`, then we shouldn't touch speed further, // because a speed hack was used for the zed @@ -2093,8 +2125,8 @@ function float HeatIncScale(){ return 100.0 / default.health; } function CapHeat(){ - heat = FMin(heat, 135 + rand(10) - 5); - heat = FMax(heat, -150 + rand(10) - 5); + heat = FMin(heat, MAX_HEAT); + heat = FMax(heat, MIN_HEAT); } function bool TryMeleeReachTarget(out Vector hitLocation){ local Actor hitActor; @@ -2135,6 +2167,7 @@ function bool MeleeDamageTarget(int hitDamage, Vector pushDir){ local KFHumanPawn kfHumanPawn; if(Level.netMode == NM_Client) return false; if(controller == none || controller.target == none) return false; + ModDamageFromZed(hitDamage, niceZombieDamType); // Melee for doors kfHumanPawn = KFHumanPawn(controller.target); bTargetIsDoor = controller.target.IsA('KFDoorMover'); @@ -2291,7 +2324,6 @@ defaultproperties fuelRatio=0.750000 heatDissipationRate=0.666000 heatTicksPerSecond=3.000000 - bFrugalFuelUsage=True clientHeadshotScale=1.000000 FrozenMaterial=Texture'HTec_A.Overlay.IceOverlay' ShatteredIce=class'NiceIceChunkEmitter' @@ -2304,6 +2336,8 @@ defaultproperties stoppingRecoveryRate=0.025 maxStoppingEffect=0.25 minStoppingThreshold=0.0 + MIN_HEAT = -150.0 + MAX_HEAT = 135.0 Begin Object Class=KarmaParamsSkel Name=KarmaParamsSkelN KConvulseSpacing=(Max=2.200000) KLinearDamping=0.150000 From 6eb879f0d118484a40f4e893998dc2dca23b7934 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 1 Sep 2024 17:27:29 +0700 Subject: [PATCH 24/46] Remove strict difference between mostly fire and non-fire damage sources --- sources/Zeds/NiceMonster.uc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index e07c396..f9a0ba1 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -840,7 +840,6 @@ function FireDamageEffects(out int damage, float headshotLevel, KFPlayerReplicationInfo KFPRI){ local float heatDelta, bonusFireDamage; - local bool shouldBeSetOnFire, isFireWeapon; damage = FMax(0.0, damage); iceCrustStrenght = FMax(0.0, iceCrustStrenght); if(bFrozenZed){ @@ -878,15 +877,13 @@ function FireDamageEffects(out int damage, burnInstigator = instigatedBy; } // Double heat damage at the cost of the fuel, if zed is already on fire - isFireWeapon = (damageType.default.heatPart >= 0.75); - if (bOnFire && isFireWeapon) { - bonusFireDamage = FMax(FMin(damage, flameFuel), 0); + if (bOnFire) { + bonusFireDamage = FMax(FMin(damage, flameFuel) * 0.25, 0); flameFuel -= bonusFireDamage; damage += bonusFireDamage; } // Set on fire, if necessary - shouldBeSetOnFire = (heat > GetIgnitionPoint()) || isFireWeapon; - if(shouldBeSetOnFire && !bOnFire && bCanBurn){ + if(heat > GetIgnitionPoint() && !bOnFire && bCanBurn){ bBurnified = true; bOnFire = true; burnInstigator = instigatedBy; @@ -1007,7 +1004,7 @@ function DealDecapDamage( int damage, hasSkill(nicePlayer, class'NiceSkillSharpshooterDieAlready')) ServerDropFaster(NiceHumanPawn(nicePlayer.pawn)); } -function DealHeadDamage( int damage, +function DealHeadDamage( int damage, Pawn instigatedBy, Vector hitLocation, Vector momentum, @@ -1026,8 +1023,8 @@ function DealHeadDamage( int damage, // Skull injury killed a zed if(HeadHealth <= 0) return; // Additional weakpoint damage to burning zeds from non-flame weapons - if (bOnFire && damageType.default.heatPart < 0.75) { - damage += 100; + if (bOnFire) { + damage += 100 * (1 - damageType.default.heatPart); } HeadHealth -= damage; if(nicePlayer != none && IsFinisher(damage, damageType, nicePlayer, true)) From b4b3111440264cb8c17e7fae42797aac0d546846 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 1 Sep 2024 17:59:26 +0700 Subject: [PATCH 25/46] Replace flat damage bonus to burning zeds with scorchmark mechanic --- sources/Zeds/NiceMonster.uc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index f9a0ba1..b673714 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -127,6 +127,7 @@ var float heatDissipationRate; var float heatTicksPerSecond; // Tracks last time heat tick occured var float lastHeatTick; +var float scorchmarkDamage; var float MIN_HEAT, MAX_HEAT; //============================================================================== @@ -499,6 +500,11 @@ simulated function FakeHeatTick(float deltaTime){ local float oFrame; local float oRate; local NiceMonsterController niceZedController; + if (bOnFire) { + // 100 of the scorchmark damage should restore every 1/10 of a second + scorchmarkDamage += deltaTime * 10 * 100; + scorchmarkDamage = FMin(scorchmarkDamage, 100); + } if(lastHeatTick + (1 / HeatTicksPerSecond) < Level.TimeSeconds){ if(bOnFire && !bBurningBehavior) SetBurningBehavior(); @@ -1024,7 +1030,8 @@ function DealHeadDamage( int damage, if(HeadHealth <= 0) return; // Additional weakpoint damage to burning zeds from non-flame weapons if (bOnFire) { - damage += 100 * (1 - damageType.default.heatPart); + damage += scorchmarkDamage * (1 - damageType.default.heatPart); + scorchmarkDamage *= damageType.default.heatPart; } HeadHealth -= damage; if(nicePlayer != none && IsFinisher(damage, damageType, nicePlayer, true)) From da810d50f12061de5786ad313fcee54acd465192 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 1 Sep 2024 18:10:17 +0700 Subject: [PATCH 26/46] Fix unintended fire damage buffs --- sources/Perks/Commando/NiceVetCommando.uc | 6 ------ sources/Perks/NiceVeterancyTypes.uc | 2 -- sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/sources/Perks/Commando/NiceVetCommando.uc b/sources/Perks/Commando/NiceVetCommando.uc index 65abf48..7e94b9f 100644 --- a/sources/Perks/Commando/NiceVetCommando.uc +++ b/sources/Perks/Commando/NiceVetCommando.uc @@ -15,12 +15,6 @@ static function class GetNadeType(KFPlayerReplicationInfo KFPRI){ //return class'NiceMedicNadePoison'; return class'NiceNade'; } -static function int AddFireDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class DmgType){ - if(class(DmgType) != none){ - return float(InDamage) * 1.5; - } - return 0.0; -} static function float GetHealthBarsDistanceMulti(KFPlayerReplicationInfo KFPRI){ /*if(KFPRI != none && SomeoneHasSkill(NicePlayerController(KFPRI.Owner), class'NiceSkillCommandoStrategist')) return class'NiceSkillCommandoStrategist'.default.visionRadius;*/ diff --git a/sources/Perks/NiceVeterancyTypes.uc b/sources/Perks/NiceVeterancyTypes.uc index 24560b4..418c6b1 100644 --- a/sources/Perks/NiceVeterancyTypes.uc +++ b/sources/Perks/NiceVeterancyTypes.uc @@ -219,8 +219,6 @@ static function int AddRegDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injure } // Allows to buff only fire component of damage. static function int AddFireDamage(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, int InDamage, class DmgType){ - if(DmgType != none) - return InDamage * DmgType.default.heatPart; return InDamage; } static function float stunDurationMult(KFPlayerReplicationInfo KFPRI, KFMonster Injured, KFPawn DamageTaker, class DmgType){ diff --git a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc index 5601513..5d2d770 100644 --- a/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc +++ b/sources/Weapons/Playable/Incendiary/HFR/NiceHFRPFire.uc @@ -2,7 +2,7 @@ class NiceHFRPFire extends NiceFire; defaultproperties { - ProjectileSpeed=1000.000000 + ProjectileSpeed=2000.000000 FireAimedAnim="Fire_Iron" RecoilRate=0.070000 maxVerticalRecoilAngle=70 From 3d0315b28b25a6001481931345fb40d64ddc3ca1 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 1 Sep 2024 20:06:55 +0700 Subject: [PATCH 27/46] Change heat and fire damage calculations --- sources/Zeds/NiceMonster.uc | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index b673714..46b700a 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -1785,35 +1785,33 @@ simulated function ZombieCrispUp(){ Skins[3]=Combiner'PatchTex.Common.BurnSkinEmbers_cmb'; } simulated function HeatTick(){ - local float iceDamage, heatDamage; + local float iceDamage; + local float heatRelativeLevel, heatMultiplier; + heatRelativeLevel = FMin(heat, flameFuel) / initFlameFuel; + if (heatRelativeLevel < 0.05) { + heatMultiplier = 1.5; + } else { + heatMultiplier = 1.1; + } // Update heat value if(!bOnFire || flameFuel <= 0) heat *= heatDissipationRate; else { if(flameFuel < heat) { - heat = flameFuel * 1.1 + (heat - flameFuel) * heatDissipationRate; + heat = flameFuel * heatMultiplier + (heat - flameFuel) * heatDissipationRate; } else { - heat = heat * 1.1; - } - if (flameFuel >= 0) { - // Burning always deals at least 5% damage (of the total fuel), - // up to additional 5%, depending on the heat levels. - heatDamage = 5 + 5 * FMin(heat, flameFuel) / initFlameFuel; // calc % - heatDamage = FMin(flameFuel, healthMax * heatDamage / 100.0); - flameFuel -= heatDamage; - } else { - // 5 damage for burning without fuel - heatDamage = 5.0; + heat = heat * heatMultiplier; } } + flameFuel = FMax(0, flameFuel - heat); CapHeat(); if(Abs(heat) < 1) heat = 0.0; // Update on-fire status if(bOnFire){ if(heat > 0) { - TakeFireDamage(heatDamage, burnInstigator); + TakeFireDamage(heat, burnInstigator); } else { bBurnified = false; @@ -2341,7 +2339,7 @@ defaultproperties maxStoppingEffect=0.25 minStoppingThreshold=0.0 MIN_HEAT = -150.0 - MAX_HEAT = 135.0 + MAX_HEAT = 200.0 Begin Object Class=KarmaParamsSkel Name=KarmaParamsSkelN KConvulseSpacing=(Max=2.200000) KLinearDamping=0.150000 From 0d87e12977a84c0876599397a35452664586aff8 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 1 Sep 2024 20:50:38 +0700 Subject: [PATCH 28/46] Changed brute textures to his old ones --- sources/Zeds/Nice/NiceZombieBruteBase.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Zeds/Nice/NiceZombieBruteBase.uc b/sources/Zeds/Nice/NiceZombieBruteBase.uc index 7bbd5e5..5780f19 100644 --- a/sources/Zeds/Nice/NiceZombieBruteBase.uc +++ b/sources/Zeds/Nice/NiceZombieBruteBase.uc @@ -122,7 +122,7 @@ defaultproperties AmbientSound=SoundGroup'ScrnZedPack_S.Brute.BruteIdle1Shot' Mesh=SkeletalMesh'ScrnZedPack_A.BruteMesh' PrePivot=(Z=0.000000) - Skins(0)=Combiner'ScrnZedPack_T.Brute.Brute_Final' + Skins(0)=Texture'NicePackT.MonsterBrute.WPCBruteT' Mass=600.000000 RotationRate=(Yaw=45000,Roll=0) } From 2384dc34d122582e4202514fab0aa37ddc4c8e06 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 29 Oct 2024 02:52:55 +0700 Subject: [PATCH 29/46] Remove Shivers' collision removal on teleport This should hopefully remove any issues with them not taking any damage during teleport --- sources/Zeds/Nice/NiceZombieShiver.uc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/Zeds/Nice/NiceZombieShiver.uc b/sources/Zeds/Nice/NiceZombieShiver.uc index 72c110e..8e88b16 100644 --- a/sources/Zeds/Nice/NiceZombieShiver.uc +++ b/sources/Zeds/Nice/NiceZombieShiver.uc @@ -281,7 +281,7 @@ simulated function Tick(float Delta) { SetCollision(true, true); FlashTeleport(); - SetCollision(false, false); + SetCollision(true, false); FadeStage = 2; } } @@ -322,7 +322,7 @@ function StartTeleport() { FadeStage = 1; AlphaFader = 255; - SetCollision(false, false); + SetCollision(true, false); bFlashTeleporting = true; } function FlashTeleport() From 8dc8f35b08738ad095af6803a95cc184f237da2d Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 29 Oct 2024 03:00:45 +0700 Subject: [PATCH 30/46] Remove `Claw3` animation from Shiver --- sources/Zeds/Nice/NiceZombieShiver.uc | 43 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/sources/Zeds/Nice/NiceZombieShiver.uc b/sources/Zeds/Nice/NiceZombieShiver.uc index 8e88b16..1a883ff 100644 --- a/sources/Zeds/Nice/NiceZombieShiver.uc +++ b/sources/Zeds/Nice/NiceZombieShiver.uc @@ -38,6 +38,33 @@ simulated function PostBeginPlay() } } } + +simulated event SetAnimAction(name NewAction) { + local int meleeAnimIndex; + + if (bFrozenZed) return; + if (newAction == '') return; + + if (newAction == 'Claw') { + meleeAnimIndex = Rand(2); // Shivers only have two animations now + newAction = meleeAnims[meleeAnimIndex]; + currentDamtype = zombieDamType[meleeAnimIndex]; + } else if(newAction == 'DoorBash') { + currentDamtype = zombieDamType[Rand(3)]; + } + expectingChannel = DoAnimAction(NewAction); + if (AnimNeedsWait(newAction)) { + bWaitForAnim = true; + } else { + bWaitForAnim = false; + } + if (level.netMode != NM_Client) { + animAction = newAction; + bResetAnimAct = True; + resetAnimActTime = level.timeSeconds + 0.3; + } +} + simulated function Destroyed() { if (Level.NetMode != NM_DedicatedServer && MatAlphaSkin != none) @@ -429,10 +456,16 @@ simulated function int DoAnimAction( name AnimName ) } defaultproperties { - HeadOffsetY=-3.000000 + headOffsetY=-3.000000 idleInsertFrame=0.468000 - OnlineHeadshotOffset=(X=19.000000,Z=39.000000) - ScoringValue=15 - HeadRadius=8.000000 - HeadHeight=3.000000 + onlineHeadshotOffset=(X=19.000000,Z=39.000000) + scoringValue=15 + headRadius=8.000000 + headHeight=3.000000 + // Override third animation just in case. + // However it shouldn't be required since we've already changed + // `SetAnimAction` function to only use first two animations + meleeAnims(0)="Claw" + meleeAnims(1)="Claw2" + meleeAnims(2)="Claw" } From 8f5511e899ed70c8a60cdfb24414137a1f853143 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 29 Oct 2024 03:17:30 +0700 Subject: [PATCH 31/46] Add attack delay to Shivers right after teleport Now shivers cannot attack for 0.5 seconds after teleporting, which should help with them getting cheap shots on players. --- sources/Zeds/Nice/NiceZombieShiver.uc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sources/Zeds/Nice/NiceZombieShiver.uc b/sources/Zeds/Nice/NiceZombieShiver.uc index 1a883ff..a28b0d1 100644 --- a/sources/Zeds/Nice/NiceZombieShiver.uc +++ b/sources/Zeds/Nice/NiceZombieShiver.uc @@ -3,6 +3,7 @@ class NiceZombieShiver extends NiceZombieShiverBase; var float TeleportBlockTime; var float HeadOffsetY; var transient bool bRunning, bClientRunning; +var float teleportAttackCooldownEndTime; replication { reliable if ( Role == ROLE_Authority) @@ -39,6 +40,12 @@ simulated function PostBeginPlay() } } +function bool CanAttack(Actor target) { + if (level.timeSeconds < teleportAttackCooldownEndTime) + return false; + return super.CanAttack(target); +} + simulated event SetAnimAction(name NewAction) { local int meleeAnimIndex; @@ -407,6 +414,7 @@ function FlashTeleport() Teleported: bFlashTeleporting = false; LastFlashTime = Level.TimeSeconds; + teleportAttackCooldownEndTime = level.timeSeconds + 0.5; } function Died(Controller Killer, class damageType, vector HitLocation) { From a003061d6df8a9c157733389ad66285b22856643 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 29 Oct 2024 03:36:40 +0700 Subject: [PATCH 32/46] Add zeds changing `moveTarget` when in-fighting starts --- sources/Zeds/NiceMonsterController.uc | 1 + 1 file changed, 1 insertion(+) diff --git a/sources/Zeds/NiceMonsterController.uc b/sources/Zeds/NiceMonsterController.uc index 1bcb5ab..59fd849 100644 --- a/sources/Zeds/NiceMonsterController.uc +++ b/sources/Zeds/NiceMonsterController.uc @@ -480,6 +480,7 @@ function bool SetEnemy( pawn newEnemy, // Do fight if we can if(bCanForceFight) { + moveTarget = newEnemy; ChangeEnemy(newEnemy, true); FightEnemy(false); return true; From 324e644db4e243f1ae1688f95ba35609f11e6270 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 29 Oct 2024 03:57:46 +0700 Subject: [PATCH 33/46] Add mechanic that buffs clots from the siren's scream Increase their speed by 50% and tankiness by not receving any body damage upon decapitation while under the effects. --- sources/Zeds/Nice/NiceZombieClot.uc | 26 ++++++++++++++++++++++++++ sources/Zeds/Nice/NiceZombieSiren.uc | 5 +++++ 2 files changed, 31 insertions(+) diff --git a/sources/Zeds/Nice/NiceZombieClot.uc b/sources/Zeds/Nice/NiceZombieClot.uc index 57875e8..71f8939 100644 --- a/sources/Zeds/Nice/NiceZombieClot.uc +++ b/sources/Zeds/Nice/NiceZombieClot.uc @@ -5,6 +5,8 @@ class NiceZombieClot extends NiceZombieClotBase; #exec OBJ LOAD FILE=KF_Specimens_Trip_T.utx #exec OBJ LOAD FILE=MeanZedSkins.utx +var float sirenBoostTimeout; + function ClawDamageTarget() { local vector PushDir; @@ -109,9 +111,33 @@ simulated function int DoAnimAction( name AnimName ) } return super.DoAnimAction( AnimName ); } +function DealDecapDamage( int damage, + Pawn instigatedBy, + Vector hitLocation, + Vector momentum, + class damageType, + float headshotLevel, + KFPlayerReplicationInfo KFPRI, + optional float lockonTime) { + if (sirenBoostTimeout > 0) { + RemoveHead(); + } else { + super.DealDecapDamage(damage, instigatedBy, hitLocation, momentum, + damageType, headshotLevel, KFPRI, lockonTime); + } +} +simulated function UpdateGroundSpeed() { + super.UpdateGroundSpeed(); + if (sirenBoostTimeout > 0) { + groundSpeed *= 1.5; + } +} simulated function Tick(float DeltaTime) { super.Tick(DeltaTime); + if (sirenBoostTimeout >= 0) { + sirenBoostTimeout -= deltaTime; + } if( bShotAnim && Role == ROLE_Authority ) { if( LookTarget!=none ) diff --git a/sources/Zeds/Nice/NiceZombieSiren.uc b/sources/Zeds/Nice/NiceZombieSiren.uc index 6f13cf4..aa15090 100644 --- a/sources/Zeds/Nice/NiceZombieSiren.uc +++ b/sources/Zeds/Nice/NiceZombieSiren.uc @@ -226,6 +226,7 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class niceVet; + local NiceZombieClot niceClot; if (bHurtEntry || Health <= 0 || HeadHealth <= 0 || bIsStunned) return; @@ -243,6 +244,10 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class Date: Tue, 29 Oct 2024 04:15:16 +0700 Subject: [PATCH 34/46] Add distance to target limit for mean husks' spam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Husks now only spam fireballs in a rage when within 30 units of their target. They’ll still keep track of the number of shots and enter this enraged state regardless of distance, but close proximity is required for rapid-fire. --- sources/Zeds/Mean/MeanZombieHusk.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Zeds/Mean/MeanZombieHusk.uc b/sources/Zeds/Mean/MeanZombieHusk.uc index b0ada50..efbb5fb 100644 --- a/sources/Zeds/Mean/MeanZombieHusk.uc +++ b/sources/Zeds/Mean/MeanZombieHusk.uc @@ -37,7 +37,7 @@ function RangedAttack(Actor A) { //Increment the number of consecutive shtos taken and apply the cool down if needed totalShots ++; consecutiveShots ++; - if(consecutiveShots < 3 && totalShots > maxNormalShots) + if(consecutiveShots < 3 && totalShots > maxNormalShots && VSize(a.location - location) <= 900) NextFireProjectileTime = Level.TimeSeconds; else{ NextFireProjectileTime = Level.TimeSeconds + ProjectileFireInterval + (FRand() * 2.0); From 501662a7d77d7fe56f687e30db27f27b5e85185d Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Wed, 30 Oct 2024 03:21:47 +0700 Subject: [PATCH 35/46] Fix harpoon badly attaching to some static meshes Just needed to add proper computation of relative location, that takes into account mesh's own rotation. --- sources/Weapons/NiceBullet.uc | 2 +- sources/Weapons/NiceProjectileSpawner.uc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sources/Weapons/NiceBullet.uc b/sources/Weapons/NiceBullet.uc index 8e03861..216ee99 100644 --- a/sources/Weapons/NiceBullet.uc +++ b/sources/Weapons/NiceBullet.uc @@ -710,7 +710,7 @@ function Stick(Actor target, Vector hitLocation) { expData.affectedByScream = charAffectedByScream; if (!target.IsA('NiceMonster')) { - hitLocation -= target.location; + hitLocation = (hitLocation - target.location) << target.rotation; boneStick = 'None'; resultTarget = target; } else { diff --git a/sources/Weapons/NiceProjectileSpawner.uc b/sources/Weapons/NiceProjectileSpawner.uc index 5334af4..a8ee953 100644 --- a/sources/Weapons/NiceProjectileSpawner.uc +++ b/sources/Weapons/NiceProjectileSpawner.uc @@ -259,6 +259,7 @@ static function SpawnStuckProjectile( } else { spawnedBullet.SetBase(base); spawnedBullet.SetRelativeLocation(shift); + spawnedBullet.SetRelativeRotation(direction - base.rotation); } } From 3716813a7b4b7e1c841d109389dda0cf827b5143 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Tue, 26 Nov 2024 02:10:50 +0700 Subject: [PATCH 36/46] 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 37/46] 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 38/46] 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 39/46] 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 40/46] 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 41/46] 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 42/46] 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 43/46] 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 44/46] 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 45/46] 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 46/46] 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." +}