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,