226 lines
5.4 KiB
Ucode
226 lines
5.4 KiB
Ucode
//=============================================================================
|
|
// Decoration.
|
|
//=============================================================================
|
|
class Decoration extends Actor
|
|
abstract
|
|
placeable
|
|
native;
|
|
|
|
// If set, the pyrotechnic or explosion when item is damaged.
|
|
var() class<actor> EffectWhenDestroyed;
|
|
var() bool bPushable;
|
|
var() bool bDamageable;
|
|
var bool bPushSoundPlaying;
|
|
var bool bSplash;
|
|
|
|
var() sound PushSound, EndPushSound;
|
|
var const int numLandings; // Used by engine physics.
|
|
var() class<inventory> contents; // spawned when destroyed
|
|
|
|
var() int NumFrags; // number of fragments to spawn when destroyed
|
|
var() texture FragSkin; // skin to use for fragments
|
|
var() class<Fragment> FragType; // type of fragment to use
|
|
var vector FragMomentum; // momentum to be imparted to frags when destroyed
|
|
var() int Health;
|
|
var() float SplashTime;
|
|
|
|
var const NavigationPoint LastAnchor; // recent nearest path
|
|
var float LastValidAnchorTime; // last time a valid anchor was found
|
|
|
|
event NotReachableBy(Pawn P); // called when FindPathToward this decoration fails (used by GameObjects)
|
|
|
|
function bool CanSplash()
|
|
{
|
|
if ( (Level.TimeSeconds - SplashTime > 0.25)
|
|
&& (Physics == PHYS_Falling)
|
|
&& (Abs(Velocity.Z) > 100) )
|
|
{
|
|
SplashTime = Level.TimeSeconds;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function Drop(vector newVel);
|
|
|
|
function Landed(vector HitNormal)
|
|
{
|
|
local rotator NewRot;
|
|
|
|
if (Velocity.Z<-500)
|
|
TakeDamage(100,Pawn(Owner),HitNormal,HitNormal*10000,class'Crushed');
|
|
Velocity = vect(0,0,0);
|
|
NewRot = Rotation;
|
|
NewRot.Pitch = 0;
|
|
NewRot.Roll = 0;
|
|
SetRotation(NewRot);
|
|
}
|
|
|
|
function HitWall (vector HitNormal, actor Wall)
|
|
{
|
|
Landed(HitNormal);
|
|
}
|
|
|
|
function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation,
|
|
Vector momentum, class<DamageType> damageType, optional int HitIndex)
|
|
{
|
|
Instigator = InstigatedBy;
|
|
if (!bDamageable || (Health<0) )
|
|
Return;
|
|
if ( Instigator != None )
|
|
MakeNoise(1.0);
|
|
Health -= NDamage;
|
|
FragMomentum = Momentum;
|
|
if (Health <0)
|
|
Destroy();
|
|
else
|
|
{
|
|
SetPhysics(PHYS_Falling);
|
|
Momentum.Z = 1000;
|
|
Velocity=Momentum/Mass;
|
|
}
|
|
}
|
|
|
|
singular function PhysicsVolumeChange( PhysicsVolume NewVolume )
|
|
{
|
|
if( NewVolume.bWaterVolume )
|
|
{
|
|
if( bSplash && !PhysicsVolume.bWaterVolume && Mass<=Buoyancy
|
|
&& ((Abs(Velocity.Z) < 100) || (Mass == 0)) && (FRand() < 0.05) && !PlayerCanSeeMe() )
|
|
{
|
|
bSplash = false;
|
|
SetPhysics(PHYS_None);
|
|
}
|
|
}
|
|
if( PhysicsVolume.bWaterVolume && (Buoyancy > Mass) )
|
|
{
|
|
if( Buoyancy > 1.1 * Mass )
|
|
Buoyancy = 0.95 * Buoyancy; // waterlog
|
|
else if( Buoyancy > 1.03 * Mass )
|
|
Buoyancy = 0.99 * Buoyancy;
|
|
}
|
|
}
|
|
|
|
function Trigger( actor Other, pawn EventInstigator )
|
|
{
|
|
Instigator = EventInstigator;
|
|
TakeDamage( 1000, Instigator, Location, Vect(0,0,1)*900, class'Crushed');
|
|
}
|
|
|
|
singular function BaseChange()
|
|
{
|
|
if( Velocity.Z < -500 )
|
|
TakeDamage( (1-Velocity.Z/30),Instigator,Location,vect(0,0,0) , class'Crushed');
|
|
|
|
if( base == None )
|
|
{
|
|
if ( !bInterpolating && bPushable && (Physics == PHYS_None) )
|
|
SetPhysics(PHYS_Falling);
|
|
}
|
|
else if( Pawn(Base) != None )
|
|
{
|
|
Base.TakeDamage( (1-Velocity.Z/400)* mass/Base.Mass,Instigator,Location,0.5 * Velocity , class'Crushed');
|
|
Velocity.Z = 100;
|
|
if (FRand() < 0.5)
|
|
Velocity.X += 70;
|
|
else
|
|
Velocity.Y += 70;
|
|
SetPhysics(PHYS_Falling);
|
|
}
|
|
else if( Decoration(Base)!=None && Velocity.Z<-500 )
|
|
{
|
|
Base.TakeDamage((1 - Mass/Base.Mass * Velocity.Z/30), Instigator, Location, 0.2 * Velocity, class'Crushed');
|
|
Velocity.Z = 100;
|
|
if (FRand() < 0.5)
|
|
Velocity.X += 70;
|
|
else
|
|
Velocity.Y += 70;
|
|
SetPhysics(PHYS_Falling);
|
|
}
|
|
else
|
|
instigator = None;
|
|
}
|
|
|
|
simulated function Destroyed()
|
|
{
|
|
local inventory dropped;
|
|
local int i;
|
|
local Fragment s;
|
|
local float BaseSize;
|
|
|
|
if ( Role == ROLE_Authority )
|
|
{
|
|
if( (Contents!=None) && !Level.bStartup )
|
|
{
|
|
dropped = Spawn(Contents);
|
|
dropped.DropFrom(Location);
|
|
}
|
|
|
|
TriggerEvent( Event, Self, None);
|
|
|
|
if ( bPushSoundPlaying )
|
|
PlaySound(EndPushSound, SLOT_Misc);
|
|
}
|
|
|
|
if ( (Level.NetMode != NM_DedicatedServer )
|
|
&& !PhysicsVolume.bDestructive
|
|
&& (NumFrags > 0) && (FragType != None) )
|
|
{
|
|
// spawn fragments
|
|
BaseSize = 0.8 * sqrt(CollisionRadius*CollisionHeight)/NumFrags;
|
|
for ( i=0; i<numfrags; i++ )
|
|
{
|
|
s = Spawn( FragType, Owner,,Location + CollisionRadius * VRand());
|
|
s.CalcVelocity(FragMomentum);
|
|
if ( FragSkin != None )
|
|
s.Skins[0] = FragSkin;
|
|
s.SetDrawScale(BaseSize * (0.5+0.7*FRand()));
|
|
}
|
|
}
|
|
|
|
Super.Destroyed();
|
|
}
|
|
|
|
function Timer()
|
|
{
|
|
PlaySound(EndPushSound, SLOT_Misc);
|
|
bPushSoundPlaying=False;
|
|
}
|
|
|
|
function Bump( actor Other )
|
|
{
|
|
local float speed, oldZ;
|
|
if( bPushable && (Pawn(Other)!=None) && (Other.Mass > 40) )
|
|
{
|
|
oldZ = Velocity.Z;
|
|
speed = VSize(Other.Velocity);
|
|
Velocity = Other.Velocity * FMin(120.0, 20 + speed)/speed;
|
|
if ( Physics == PHYS_None )
|
|
{
|
|
Velocity.Z = 25;
|
|
if (!bPushSoundPlaying)
|
|
{
|
|
PlaySound(PushSound, SLOT_Misc);
|
|
bPushSoundPlaying = True;
|
|
}
|
|
}
|
|
else
|
|
Velocity.Z = oldZ;
|
|
SetPhysics(PHYS_Falling);
|
|
SetTimer(0.3,False);
|
|
Instigator = Pawn(Other);
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
bCanBeDamaged=true
|
|
bStatic=True
|
|
bStasis=True
|
|
Mass=100.000000
|
|
DrawType=DT_Mesh
|
|
bOrientOnSlope=true
|
|
bShouldBaseAtStartup=true
|
|
NetUpdateFrequency=10
|
|
}
|