//----------------------------------------------------------- // It Breaks good.. //----------------------------------------------------------- class KFDECO_Smashable extends decoration; var () float RespawnTime; var () bool bNeedsSingleShot; // If true, it will only smash on damage if it's all in a single shot var bool bImperviusToPlayer; // If true, the player can't smash it var () bool bExplosive; var () float ExplosionDamage; var () float ExplosionRadius; var () float ExplosionForce; var class ExplosionDamType; var() class DestroyedContents; // spawned when destroyed var() bool bContentsRespawn; function Reset() { super.Reset(); Gotostate('Working'); } simulated function PostBeginPlay() { super.PostBeginPlay(); disable('tick'); CullDistance = default.CullDistance; } function BreakApart(vector HitLocation, vector momentum) { // If we are single player or on a listen server, just spawn the actor, otherwise // bHidden will trigger the effect if (Level.NetMode == NM_ListenServer || Level.NetMode == NM_StandAlone) { if ( (EffectWhenDestroyed!=None ) && EffectIsRelevant(location,false) ) Spawn( EffectWhenDestroyed, Owner,, Location ); } gotostate('Broken'); } auto state Working { function BeginState() { super.BeginState(); SetCollision(true,true,true); NetUpdateTime = Level.TimeSeconds - 1; bHidden = false; //Health = default.health; } function EndState() { local Pawn DummyPawn; local pickup DroppedPickup; local vector AdjustedLoc; super.EndState(); NetUpdateTime = Level.TimeSeconds - 1; bHidden = true; SetCollision(false,false,false); TriggerEvent( Event, self , DummyPawn); //PostNetReceive(); Spawn( EffectWhenDestroyed, Owner,, Location ); AdjustedLoc = Location; AdjustedLoc.Z += 0.5 * collisionHeight; if (bExplosive) HurtRadius( ExplosionDamage, ExplosionRadius, ExplosionDamType, ExplosionForce, Location ); if ( Role == ROLE_Authority ) { if( (DestroyedContents!=None) && !Level.bStartup ) { DroppedPickup = Spawn(DestroyedContents,,,AdjustedLoc ); if( !bContentsRespawn && DroppedPickup!=None ) DroppedPickup.RespawnTime = 0; } } } function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class damageType, optional int HitIndex) { if ( Instigator != None ) MakeNoise(1.0); if (bNeedsSingleShot) { if (Damage > Health) BreakApart(HitLocation, Momentum); } else { Health -= Damage; if ( Health < 0 ) BreakApart(HitLocation, Momentum); } } function Bump( actor Other ) { if ( Mover(Other) != None && Mover(Other).bResetting ) return; if ( UnrealPawn(Other)!=None && bImperviusToPlayer ) return; if ( VSize(Other.Velocity)>500 ) BreakApart(Other.Location, Other.Velocity); } function bool EncroachingOn(Actor Other) { if ( Mover(Other) != None && Mover(Other).bResetting ) return false; BreakApart(Other.Location, Other.Velocity); return false; } event EncroachedBy(Actor Other) { if ( Mover(Other) != None && Mover(Other).bResetting ) return; BreakApart(Other.Location, Other.Velocity); } } state Broken { function BeginState() { super.BeginState(); if(RespawnTime > 0) SetTimer(RespawnTime,false); } event Timer() { local pawn p; super.Timer(); foreach RadiusActors(class'Pawn', P, CollisionRadius * 1.25) { SetTimer(5,false); return; } GotoState('Working'); } } simulated function PostNetReceive() { if ( bHidden && EffectWhenDestroyed != none && EffectIsRelevant(location,false) ) Spawn( EffectWhenDestroyed, Owner,, Location ); } /* HurtRadius() Hurt locally authoritative actors within the radius. */ simulated function HurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) { local actor Victims; local float damageScale, dist; local vector dir; if( bHurtEntry ) return; bHurtEntry = true; foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation ) { // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag if( (Victims != self) && (Victims.Role == ROLE_Authority) && (!Victims.IsA('FluidSurfaceInfo')) ) { dir = Victims.Location - HitLocation; dist = FMax(1,VSize(dir)); dir = dir/dist; damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); Victims.TakeDamage ( damageScale * DamageAmount, Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), DamageType ); } } bHurtEntry = false; } //============================================================================= // defaultproperties //============================================================================= defaultproperties { bStatic=false bStasis=false bDamageable=true bCanBeDamaged=true bEdShouldSnap=true bUseCylinderCollision=false bCollideActors=true bCollideWorld=true bBlockActors=true bBlockKarma=true bFixedRotationDir=true bPushable=false bMovable=true bOrientOnSlope=true bNoDelete = true RespawnTime=0 bNeedsSingleShot=false bImperviusToPlayer=true bNetInitialRotation=true RemoteRole=ROLE_SimulatedProxy bNetNotify=true CullDistance=4500 NetUpdateFrequency=1 Physics = PHYS_None }