class ScrnCrossbuzzsawBlade extends CrossbuzzsawBlade; var Actor ImpactActorFixed; // original ImpactActor isn't replicated corectly var float ShutMeUpTime; replication { reliable if ( Role==ROLE_Authority ) ImpactActorFixed; } simulated function PostBeginPlay() { super.PostBeginPlay(); ShutMeUpTime += Level.TimeSeconds; } simulated function PostNetReceive() { if ( Role < ROLE_Authority ){ if ( bHidden ) Destroy(); else if( ImpactActorFixed!=None && Base != ImpactActorFixed ) GoToState('OnWall'); } } // destroy an actor and make sure it will be destroyed on clients too simulated function ReplicatedDestroy() { if ( Level.NetMode == NM_Client || Level.NetMode == NM_StandAlone ) { Destroy(); } else { bHidden = true; SetCollision(false, false); SetPhysics(PHYS_None); Velocity = vect(0,0,0); Speed = 0; NetUpdateTime = Level.TimeSeconds - 1; SetTimer(1.0, false); } } function Timer() { Destroy(); } simulated function Tick( float Delta ) { super.Tick(Delta); if ( AmbientSound != None && ShutMeUpTime > Level.TimeSeconds ) AmbientSound = None; // make sure I'll shutup } // overrided to change calss to ReplicatedDestroy() simulated state OnWall { Ignores HitWall; simulated function BeginState() { bCollideWorld = False; AmbientSound = None; if( Trail!=None ) Trail.mRegen = False; if( Corona != none ) { Corona.Kill(); } SetCollisionSize(75,50); UV2Texture=FadeColor'PatchTex.Common.PickupOverlay'; NetUpdateFrequency = 2.0; } function ProcessTouch (Actor Other, vector HitLocation) { local Inventory inv; if( !bHidden && Pawn(Other)!=None && Pawn(Other).Inventory!=None ) { for( inv=Pawn(Other).Inventory; inv!=None; inv=inv.Inventory ) { if( Crossbuzzsaw(Inv)!=None && Weapon(inv).AmmoAmount(0) HitPoints; local KFPawn HitPawn; local bool bHitWhipAttachment; local Pawn P; if ( bHidden || Other == none || Other == Instigator || Other.Base == Instigator || !Other.bBlockHitPointTraces || Other==IgnoreImpactPawn || (IgnoreImpactPawn != none && Other.Base == IgnoreImpactPawn) ) return; X = Vector(Rotation); if( ROBulletWhipAttachment(Other) != none ) { bHitWhipAttachment=true; if(!Other.Base.bDeleteMe) { Other = Instigator.HitPointTrace(TempHitLocation, HitNormal, HitLocation + (65535 * X), HitPoints, HitLocation,, 1); if( Other == none || HitPoints.Length == 0 ) return; HitPawn = KFPawn(Other); if (Role == ROLE_Authority) { if ( HitPawn != none ) { // Hit detection debugging /*log("Bullet hit "$HitPawn.PlayerReplicationInfo.PlayerName); HitPawn.HitStart = HitLocation; HitPawn.HitEnd = HitLocation + (65535 * X);*/ if( !HitPawn.bDeleteMe ) HitPawn.ProcessLocationalDamage(Damage, Instigator, TempHitLocation, MomentumTransfer * X, MyDamageType,HitPoints); Damage *= 0.80; Velocity *= 0.85; IgnoreImpactPawn = HitPawn; if( Level.NetMode!=NM_Client ) PlayhitNoise(Pawn(Other)!=none && Pawn(Other).ShieldStrength>0); } } } return; } if ( Pawn(Other)!=None && Vehicle(Other)==None ) P = Pawn(Other); else if ( ExtendedZCollision(Other)!=None && Pawn(Other.Owner)!=None ) P = Pawn(Other.Owner); if( Level.NetMode!=NM_Client ) PlayhitNoise(P != none && P.ShieldStrength>0 ); if( P != none ) { IgnoreImpactPawn = P; if( P.IsHeadShot(HitLocation, X, 1.0) ) P.TakeDamage(Damage * HeadShotDamageMult, Instigator, HitLocation, MomentumTransfer * X, DamageTypeHeadShot); else P.TakeDamage(Damage, Instigator, HitLocation, MomentumTransfer * X, MyDamageType); // If blade kills pawn, decatipates it or it was already decapitated, // then apply lower damage and speed reduction // -- PooSH if ( Physics==PHYS_Projectile && (P == none || P.Health <= 0 || (KFMonster(P) != none && KFMonster(P).bDecapitated)) ) { Damage *= 0.85; // vanilla = 0.8 Velocity *= 0.9; // vanilla = 0.85 } else { Damage *= 0.60; // vanilla = 0.8 Velocity *= 0.75; // vanilla = 0.85 if ( Damage < default.Damage * 0.50 ) { if ( Bounces > 0 ) Bounces--; // lower amount of bounces, if blade hit many zeds already if ( Role == ROLE_Authority && Bounces == 0 && Damage < default.Damage * 0.20 ) ReplicatedDestroy(); } } } else { Other.TakeDamage(Damage, Instigator, HitLocation, MomentumTransfer * X, MyDamageType); } } simulated function Stick(actor HitActor, vector HitLocation) { super.Stick(HitActor, HitLocation); ImpactActorFixed = ImpactActor; // replicate properly NetUpdateTime = Level.TimeSeconds - 1; } defaultproperties { ShutMeUpTime=10.000000 HeadShotDamageMult=2.500000 Damage=400.000000 DamageRadius=0.000000 MyDamageType=Class'ScrnBalanceSrv.ScrnDamTypeCrossbuzzsaw' LifeSpan=60.000000 }