rott/kf_sources/KFMod/Classes/KFDECO_Smashable.uc
2026-07-14 20:27:09 +07:00

245 lines
6.3 KiB
Ucode

//-----------------------------------------------------------
// 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<DamageType> ExplosionDamType;
var() class<Pickup> 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> 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> 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
}