Files
UT2k4-Mod-UT2341/Sources/Classes/UT2341BioGlob.uc
2022-11-28 01:19:02 +00:00

390 lines
9.8 KiB
Ucode

/*
UT99's bio glob base damage is 30 - however, the damaging function (Timer()) in 99
multiplies bio damage by the current drawscale
primary shots have drawscale 2.0
alt fire shots have drawscale between 1.8 and 4.28
we therefore specify the primary damage as 60, and scale damage by (1 + 0.155 * (GoopLevel - 1))
*/
class UT2341BioGlob extends Projectile;
var xEmitter Trail;
var() float GloblingSpeed;
var() float RestTime;
var() float TouchDetonationDelay; // gives player a split second to jump to gain extra momentum from blast
var() float DripTime;
var() int MaxGoopLevel;
var int GoopLevel;
var float GoopVolume;
var Vector SurfaceNormal;
var int Rand3;
var bool bCheckedSurface;
var() bool bMergeGlobs;
var bool bDrip;
var bool bOnMover;
var() Sound ExplodeSound;
var AvoidMarker Fear;
replication
{
reliable if (bNetInitial && Role == ROLE_Authority)
Rand3;
}
simulated function PostBeginPlay()
{
Super.PostBeginPlay();
SetOwner(None);
LoopAnim('flying', 1.0);
if (Role == ROLE_Authority)
{
Velocity = Vector(Rotation) * Speed;
Velocity.Z += TossZ;
}
if (Role == ROLE_Authority)
Rand3 = Rand(3);
if ( (Level.NetMode != NM_DedicatedServer) && ((Level.DetailMode == DM_Low) || Level.bDropDetail) )
{
bDynamicLight = false;
LightType = LT_None;
}
}
function AdjustSpeed()
{
if ( GoopLevel > 1 )
{
//UT had different stats for the alt glob
Damage = 100;
Velocity = Vector(Rotation) * 1000;
Velocity.Z += TossZ;
}
}
simulated function PostNetBeginPlay()
{
if (Role < ROLE_Authority && Physics == PHYS_None)
{
Landed(Vector(Rotation));
}
}
simulated function Destroyed()
{
if ( !bNoFX && EffectIsRelevant(Location,false) )
{
//Spawn(class'xEffects.GoopSmoke');
//Spawn(class'xEffects.GoopSparks');
Spawn(class'FX_BioExplosion');
}
if ( Fear != None )
Fear.Destroy();
if (Trail != None)
Trail.Destroy();
Super.Destroyed();
}
simulated function MergeWithGlob(int AdditionalGoopLevel)
{
}
auto state Flying
{
simulated function Landed( Vector HitNormal )
{
local Rotator NewRot;
local int CoreGoopLevel;
if ( Level.NetMode != NM_DedicatedServer )
{
PlaySound(ImpactSound, SLOT_Misc);
// explosion effects
}
SurfaceNormal = HitNormal;
// spawn globlings
CoreGoopLevel = Rand3 + MaxGoopLevel - 3;
if (GoopLevel > CoreGoopLevel)
{
if (Role == ROLE_Authority)
SplashGlobs(GoopLevel - CoreGoopLevel);
SetGoopLevel(CoreGoopLevel);
}
spawn(class'BioDecal',,,, rotator(-HitNormal));
bCollideWorld = false;
SetCollisionSize(GoopVolume*10.0, GoopVolume*10.0);
bProjTarget = true;
NewRot = Rotator(HitNormal);
NewRot.Roll += 32768;
SetRotation(NewRot);
SetPhysics(PHYS_None);
bCheckedsurface = false;
if ( (Level.Game != None) && (Level.Game.NumBots > 0) )
Fear = Spawn(class'AvoidMarker');
GotoState('OnGround');
}
simulated function HitWall( Vector HitNormal, Actor Wall )
{
Landed(HitNormal);
if ( !Wall.bStatic && !Wall.bWorldGeometry )
{
bOnMover = true;
SetBase(Wall);
if (Base == None)
BlowUp(Location);
}
}
simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
local UT2341BioGlob Glob;
Glob = UT2341BioGlob(Other);
if ( Glob != None )
{
if (Glob.Owner == None || (Glob.Owner != Owner && Glob.Owner != self))
{
if (bMergeGlobs)
{
Glob.MergeWithGlob(GoopLevel); // balancing on the brink of infinite recursion
bNoFX = true;
Destroy();
}
else
{
BlowUp( HitLocation );
}
}
}
else if (Other != Instigator && (Other.IsA('Pawn') || Other.IsA('DestroyableObjective') || Other.bProjTarget))
BlowUp( HitLocation );
else if ( Other != Instigator && Other.bBlockActors )
HitWall( Normal(HitLocation-Location), Other );
}
}
state OnGround
{
simulated function BeginState()
{
PlayAnim('hit');
SetTimer(RestTime, false);
}
simulated function Timer()
{
if (bDrip)
{
bDrip = false;
SetCollisionSize(default.CollisionHeight, default.CollisionRadius);
Velocity = PhysicsVolume.Gravity * 0.2;
SetPhysics(PHYS_Falling);
bCollideWorld = true;
bCheckedsurface = false;
bProjTarget = false;
LoopAnim('flying', 1.0);
GotoState('Flying');
}
else
{
BlowUp(Location);
}
}
simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
if ( Other.IsA('Pawn') && (Other != Base) )
{
bDrip = false;
SetTimer(TouchDetonationDelay, false);
}
}
function TakeDamage( int Damage, Pawn InstigatedBy, Vector HitLocation, Vector Momentum, class<DamageType> DamageType )
{
if (DamageType.default.bDetonatesGoop)
{
bDrip = false;
SetTimer(0.1, false);
}
}
simulated function AnimEnd(int Channel)
{
local float DotProduct;
if (!bCheckedSurface)
{
DotProduct = SurfaceNormal dot Vect(0,0,-1);
if (DotProduct > 0.7)
{
PlayAnim('Drip', 0.66);
bDrip = true;
SetTimer(DripTime, false);
if (bOnMover)
BlowUp(Location);
}
else if (DotProduct > -0.5)
{
PlayAnim('Slide', 1.0);
if (bOnMover)
BlowUp(Location);
}
bCheckedSurface = true;
}
}
simulated function MergeWithGlob(int AdditionalGoopLevel)
{
local int NewGoopLevel, ExtraSplash;
NewGoopLevel = AdditionalGoopLevel + GoopLevel;
if (NewGoopLevel > MaxGoopLevel)
{
Rand3 = (Rand3 + 1) % 3;
ExtraSplash = Rand3;
if (Role == ROLE_Authority)
SplashGlobs(NewGoopLevel - MaxGoopLevel + ExtraSplash);
NewGoopLevel = MaxGoopLevel - ExtraSplash;
}
SetGoopLevel(NewGoopLevel);
SetCollisionSize(GoopVolume*10.0, GoopVolume*10.0);
PlaySound(ImpactSound, SLOT_Misc);
PlayAnim('hit');
bCheckedSurface = false;
SetTimer(RestTime, false);
}
}
function BlowUp(Vector HitLocation)
{
if (Role == ROLE_Authority)
{
// simulate ut99 drawscale-based calc for charged glob
if (GoopLevel > 1)
{
Damage *= 1 + (0.155 * (GoopLevel - 1));
DamageRadius = FMin(275, DamageRadius + (12.5 * (GoopLevel - 1)));
}
MomentumTransfer = MomentumTransfer * GoopVolume;
if (Physics == PHYS_Flying)
MomentumTransfer *= 0.5;
DelayedHurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation);
}
PlaySound(ExplodeSound, SLOT_Misc);
Destroy();
//GotoState('shriveling');
}
singular function SplashGlobs(int NumGloblings)
{
local int g;
local UT2341BioGlob NewGlob;
local Vector VNorm;
for (g=0; g<NumGloblings; g++)
{
NewGlob = Spawn(Class, self,, Location+GoopVolume*(CollisionHeight+4.0)*SurfaceNormal);
if (NewGlob != None)
{
NewGlob.Velocity = (GloblingSpeed + FRand()*150.0) * (SurfaceNormal + VRand()*0.8);
if (Physics == PHYS_Falling)
{
VNorm = (Velocity dot SurfaceNormal) * SurfaceNormal;
NewGlob.Velocity += (-VNorm + (Velocity - VNorm)) * 0.1;
}
NewGlob.InstigatorController = InstigatorController;
}
//else log("unable to spawn globling");
}
}
state Shriveling
{
simulated function BeginState()
{
bProjTarget = false;
PlayAnim('shrivel', 1.0);
}
simulated function AnimEnd(int Channel)
{
Destroy();
}
simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
}
}
simulated function SetGoopLevel( int NewGoopLevel )
{
GoopLevel = NewGoopLevel;
GoopVolume = sqrt(float(GoopLevel));
SetDrawScale(GoopVolume*default.DrawScale);
LightBrightness = Min(100 + 15*GoopLevel, 255);
LightRadius = 1.7 + 0.2*GoopLevel;
FluidSurfaceShootStrengthMod=5.f + 0.3 * NewGoopLevel;
}
defaultproperties
{
GloblingSpeed=200.000000
RestTime=3.800000
TouchDetonationDelay=0.150000
DripTime=1.800000
MaxGoopLevel=5
GoopLevel=1
GoopVolume=1.000000
bMergeGlobs=True
ExplodeSound=Sound'UT2341Weapons_Sounds.General.Explo1'
Speed=1500.000000
MaxSpeed=1900.000000
TossZ=140.000000
bSwitchToZeroCollision=True
Damage=60.000000
DamageRadius=165.000000
MomentumTransfer=40000.000000
MyDamageType=Class'UT2341WeaponsReducedv1a.DamType_BioGel'
ImpactSound=Sound'UT2341Weapons_Sounds.BioRifle.GelHit'
MaxEffectDistance=7000.000000
LightType=LT_Steady
LightEffect=LE_QuadraticNonIncidence
LightHue=82
LightSaturation=10
LightBrightness=190.000000
LightRadius=0.600000
bDynamicLight=True
bNetTemporary=False
bOnlyDirtyReplication=True
Physics=PHYS_Falling
LifeSpan=12.000000
Mesh=VertMesh'XWeapons_rc.GoopMesh'
DrawScale=1.100000
Skins(0)=FinalBlend'XEffectMat.goop.GoopFB'
AmbientGlow=80
SoundVolume=255
SoundRadius=100.000000
CollisionRadius=2.000000
CollisionHeight=2.000000
bUseCollisionStaticMesh=True
}