diff --git a/sources/Zeds/Nice/NiceZombieHusk.uc b/sources/Zeds/Nice/NiceZombieHusk.uc index 88cb718..aa95471 100644 --- a/sources/Zeds/Nice/NiceZombieHusk.uc +++ b/sources/Zeds/Nice/NiceZombieHusk.uc @@ -125,18 +125,28 @@ function float GetStunDurationMult(Pawn instigatedBy, Vector hitLocation, Vector return 0.5 * stunDurationMultiplier; } -function SpawnTwoShots(){ - local vector X,Y,Z, FireStart; +function SpawnTwoShots() +{ + local vector X, Y, Z, FireStart; local rotator FireRotation; local KFMonsterController KFMonstControl; - if(controller != none && KFDoorMover(controller.Target) != none){ - controller.Target.TakeDamage(22,Self,Location,vect(0,0,0),Class'DamTypeVomit'); + + // can NOT shoot if brainless, dying, falling, being moved by other husks + if (Controller == none || IsInState('ZombieDying') || IsInState('GettingOutOfTheWayOfShot') || Physics == PHYS_Falling) + return; + + if (KFDoorMover(controller.Target) != none) + { + controller.Target.TakeDamage(22, Self, Location, vect(0, 0, 0), class'DamTypeVomit'); return; } - GetAxes(Rotation,X,Y,Z); + + GetAxes(Rotation, X, Y, Z); FireStart = GetBoneCoords('Barrel').Origin; - if(!SavedFireProperties.bInitialized){ - SavedFireProperties.AmmoClass = Class'SkaarjAmmo'; + + if (!SavedFireProperties.bInitialized) + { + SavedFireProperties.AmmoClass = class'SkaarjAmmo'; SavedFireProperties.ProjectileClass = HuskFireProjClass; SavedFireProperties.WarnTargetPct = 1; SavedFireProperties.MaxRange = 65535; @@ -146,17 +156,29 @@ function SpawnTwoShots(){ SavedFireProperties.bInstantHit = false; SavedFireProperties.bInitialized = true; } + // Turn off extra collision before spawning vomit, otherwise spawn fails ToggleAuxCollision(false); - if(controller != none) - FireRotation = controller.AdjustAim(SavedFireProperties,FireStart,600); + + FireRotation = controller.AdjustAim(SavedFireProperties, FireStart, 600); + foreach DynamicActors(class'KFMonsterController', KFMonstControl) - if(KFMonstControl != controller && PointDistToLine(KFMonstControl.Pawn.Location, vector(FireRotation), FireStart) < 75) - KFMonstControl.GetOutOfTheWayOfShot(vector(FireRotation),FireStart); - Spawn(HuskFireProjClass,,, FireStart, FireRotation); + { + // ignore zeds that the husk can't see, Joabyy + if (KFMonstControl == none || KFMonstControl == controller || !LineOfSightTo(KFMonstControl)) + continue; + + if (PointDistToLine(KFMonstControl.Pawn.Location, vector(FireRotation), FireStart) < 75) + KFMonstControl.GetOutOfTheWayOfShot(vector(FireRotation), FireStart); + } + + // added projectile owner... + Spawn(HuskFireProjClass, self, , FireStart, FireRotation); + // Turn extra collision back on ToggleAuxCollision(true); } + // Get the closest point along a line to another point simulated function float PointDistToLine(vector Point, vector Line, vector Origin, optional out vector OutClosestPoint) { diff --git a/sources/Zeds/Nice/NiceZombieSiren.uc b/sources/Zeds/Nice/NiceZombieSiren.uc index c98be06..f361024 100644 --- a/sources/Zeds/Nice/NiceZombieSiren.uc +++ b/sources/Zeds/Nice/NiceZombieSiren.uc @@ -202,6 +202,7 @@ simulated function DoShakeEffect() } } } + simulated function HurtRadius(float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation) { local actor Victims; @@ -211,43 +212,57 @@ simulated function HurtRadius(float DamageAmount, float DamageRadius, class niceVet; - if(bHurtEntry || Health <= 0 || HeadHealth <= 0 || bIsStunned) + + if (bHurtEntry || Health <= 0 || HeadHealth <= 0 || bIsStunned) return; bHurtEntry = true; + InitMomentum = Momentum; - if(screamStartTime > 0 && currScreamTiming == 0) + if (screamStartTime > 0 && currScreamTiming == 0) MakeNewScreamBall(); - foreach VisibleCollidingActors(class 'Actor', Victims, DamageRadius, HitLocation){ - Momentum = InitMomentum; - // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag - // Or Karma actors in this case. Self inflicted Death due to flying chairs is uncool for a zombie of your stature. - if((Victims != self) && !Victims.IsA('FluidSurfaceInfo') && !Victims.IsA('KFMonster') && !Victims.IsA('ExtendedZCollision')){ - dir = Victims.Location - HitLocation; - dist = FMax(1,VSize(dir)); - dir = dir/dist; - damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); - humanPawn = KFHumanPawn(Victims); - if(humanPawn == none) // If it aint human, don't pull the vortex crap on it. - Momentum = 0; - else{ // Also don't do it if we're sharpshooter with a right skill - niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(humanPawn.PlayerReplicationInfo); - if(niceVet != none && !niceVet.static.CanBePulled(KFPlayerReplicationInfo(humanPawn.PlayerReplicationInfo))) - Momentum = 0; - } - if(Victims.IsA('KFGlassMover')) // Hack for shattering in interesting ways. - UsedDamageAmount = 100000; // Siren always shatters glass - else - UsedDamageAmount = DamageAmount; + // was VisibleCollidingActors + foreach CollidingActors(class'Actor', Victims, DamageRadius, HitLocation) + { + // some optimizations + // https://wiki.beyondunreal.com/Legacy:Code_Optimization#Optimize_iterator_use + if (Victims.bStatic || Victims.Physics == PHYS_None || !FastTrace(Victims.Location, Location) ) + continue; // skip this actor - Victims.TakeDamage(damageScale * UsedDamageAmount,Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), DamageType); + Momentum = InitMomentum; + // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag + // Or Karma actors in this case. Self inflicted Death due to flying chairs is uncool for a zombie of your stature. + if ((Victims != self) && !Victims.IsA('FluidSurfaceInfo') && !Victims.IsA('KFMonster') && !Victims.IsA('ExtendedZCollision')) + { + dir = Victims.Location - HitLocation; + dist = FMax(1,VSize(dir)); + dir = dir/dist; + damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); + humanPawn = KFHumanPawn(Victims); + if (humanPawn == none) // If it aint human, don't pull the vortex crap on it. + Momentum = 0; + else + { // Also don't do it if we're sharpshooter with a right skill + niceVet = class'NiceVeterancyTypes'.static.GetVeterancy(humanPawn.PlayerReplicationInfo); + if (niceVet != none && !niceVet.static.CanBePulled(KFPlayerReplicationInfo(humanPawn.PlayerReplicationInfo))) + Momentum = 0; + } - if (Instigator != none && Vehicle(Victims) != none && Vehicle(Victims).Health > 0) - Vehicle(Victims).DriverRadiusDamage(UsedDamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation); - } + if (Victims.IsA('KFGlassMover')) // Hack for shattering in interesting ways. + UsedDamageAmount = 100000; // Siren always shatters glass + else + UsedDamageAmount = DamageAmount; + + Victims.TakeDamage(damageScale * UsedDamageAmount,Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), DamageType); + + if (Instigator != none && Vehicle(Victims) != none && Vehicle(Victims).Health > 0) + Vehicle(Victims).DriverRadiusDamage(UsedDamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation); + } } + bHurtEntry = false; } + // When siren loses her head she's got nothin' Kill her. function RemoveHead(){ Super.RemoveHead(); diff --git a/sources/Zeds/Nice/NiceZombieStalker.uc b/sources/Zeds/Nice/NiceZombieStalker.uc index 0a75dde..3e2c054 100644 --- a/sources/Zeds/Nice/NiceZombieStalker.uc +++ b/sources/Zeds/Nice/NiceZombieStalker.uc @@ -214,7 +214,7 @@ function RemoveHead() } simulated function PlayDying(class DamageType, vector HitLoc) { - Super.PlayDying(DamageType,HitLoc); + Super(NiceMonster).PlayDying(DamageType,HitLoc); if(bUnlit) bUnlit=!bUnlit; LocalKFHumanPawn = none; diff --git a/sources/Zeds/Nice/NiceZombieTeslaHusk.uc b/sources/Zeds/Nice/NiceZombieTeslaHusk.uc index 4362308..030c45f 100644 --- a/sources/Zeds/Nice/NiceZombieTeslaHusk.uc +++ b/sources/Zeds/Nice/NiceZombieTeslaHusk.uc @@ -266,7 +266,7 @@ function Died(Controller Killer, class damageType, vector HitLocatio } simulated event PlayDying(class DamageType, vector HitLoc) { - super.PlayDying(DamageType, HitLoc); + super(NiceMonster).PlayDying(DamageType, HitLoc); if ( DecapitationSparks != none ) DecapitationSparks.Destroy(); AmbientSound = none; } diff --git a/sources/Zeds/NiceMonster.uc b/sources/Zeds/NiceMonster.uc index 4162201..32fcb4e 100644 --- a/sources/Zeds/NiceMonster.uc +++ b/sources/Zeds/NiceMonster.uc @@ -2039,14 +2039,26 @@ function bool MeleeDamageTarget(int hitDamage, Vector pushDir){ } return true; } -state ZombieDying { - ignores AnimEnd, Trigger, Bump, HitWall, HeadVolumeChange, + + +state ZombieDying +{ + ignores AnimEnd, Trigger, Bump, HitWall, HeadVolumeChange, PhysicsVolumeChange, Falling, BreathTimer, Died, RangedAttack; + + // #1 disable zed collisions on death + simulated function BeginState() + { + super.BeginState(); + DisableCollisions(); + } + simulated function Landed(vector HitNormal){ SetCollision(false, false, false); if(!bDestroyNextTick) Disable('Tick'); } + simulated function TakeDamageClient(int damage, Pawn InstigatedBy, Vector hitLocation, @@ -2095,6 +2107,29 @@ state ZombieDying { } } } + + +// #2 disable zed collisions on death +simulated function PlayDying(class DamageType, vector HitLoc) +{ + super.PlayDying(DamageType, HitLoc); + DisableCollisions(); +} + + +// disables all collisions +simulated function DisableCollisions() +{ + bBlockActors = false; + bBlockPlayers = false; + bBlockProjectiles = false; + bProjTarget = false; + bBlockZeroExtentTraces = false; + bBlockNonZeroExtentTraces = false; + bBlockHitPointTraces = false; +} + + defaultproperties { stunDurationMultiplier=0.5