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

223 lines
4.8 KiB
Ucode

//-----------------------------------------------------------
//
//-----------------------------------------------------------
class KFRandomSpawn extends xPickUpBase abstract;
var() class<Pickup> PickupClasses[11];
var() int PickupWeight[11];
var() array<float> OddsOfAppearing;
var() bool bSequential;
var() bool bForceDefault;
var int NumClasses;
var int CurrentClass;
var bool bIsEnabledNow;
var int WeightTotal;
var float InitialWaitTime;
var float ReTryWaitTime;
simulated function PostBeginPlay()
{
local int i;
if ( Level.NetMode!=NM_Client )
{
NumClasses = 0;
if(bForceDefault)
{
for(i=0; i<ArrayCount(PickupClasses); ++i)
{
PickupClasses[i] = default.PickupClasses[i];
PickupWeight[i] = default.PickupWeight[i];
}
}
for(i=0; i<ArrayCount(PickupClasses) && PickupClasses[NumClasses] != none; ++i)
{
NumClasses++;
if( PickupWeight[i]==0 )
PickupWeight[i]=1;
WeightTotal+=PickupWeight[i];
}
CurrentClass=GetWeightedRandClass();
PowerUp = PickupClasses[CurrentClass];
}
if ( Level.NetMode != NM_DedicatedServer )
{
for ( i=0; i< NumClasses; i++ )
PickupClasses[i].static.StaticPrecache(Level);
}
Super.PostBeginPlay();
SetLocation(Location - vect(0,0,1)); // adjust because reduced drawscale
}
function int GetWeightedRandClass()
{
local int RandIndex;
local int Tally;
local int i;
RandIndex = rand(WeightTotal+1); // rand always returns a value between 0 and max-1
Tally = PickupWeight[0];
while(Tally<RandIndex)
{
++i;
Tally+=PickupWeight[i];
}
return i;
}
function TurnOn()
{
CurrentClass=GetWeightedRandClass();
PowerUp = PickupClasses[CurrentClass];
if( myPickup != none )
myPickup.Destroy();
SpawnPickup();
SetTimer(InitialWaitTime+InitialWaitTime*FRand(), false);
}
function SpawnPickup()
{
local Rotator AdjustedRotation;
AdjustedRotation = self.Rotation;
AdjustedRotation.Pitch = rand(10000) + 1000;
if( PowerUp == None )
return;
myPickUp = Spawn(PowerUp,,,Location + SpawnHeight * vect(0,0,1), AdjustedRotation);
if (myPickUp != None)
{
myPickUp.PickUpBase = self;
myPickup.Event = event;
myPickup.RespawnTime = 0;
}
if (myMarker != None)
{
myMarker.markedItem = myPickUp;
myMarker.ExtraCost = ExtraPathCost;
if (myPickUp != None)
myPickup.MyMarker = MyMarker;
}
SetTimer(InitialWaitTime+InitialWaitTime*FRand(), false);
}
function timer()
{
if( !bIsEnabledNow )
{
if( myPickup!=none )
{
if( !myPickup.IsInState('Sleeping') && PlayersCanSeeMe() )
{
SetTimer(1+FRand(), false);
return;
}
myPickup.Destroy();
}
SetTimer(0,False);
}
if( myPickup!=none && myPickup.IsInState('Sleeping') )
return;
if(!PlayersCanSeeMe())
TurnOn();
else SetTimer(ReTryWaitTime+ReTryWaitTime*FRand(), false);
}
function bool PlayersCanSeeMe()
{
local controller C;
for( C=level.ControllerList; C!=none; C=C.nextController)
{
if( C.bIsPlayer && C.Pawn!=none && VSize(C.Pawn.Location-Location)<2000 && FastTrace(C.Pawn.Location+C.Pawn.EyePosition(),Location) )
return true;
}
return false;
}
function NotifyNewWave( int CurrentWave, int FinalWave )
{
if( RandomEnabled(CurrentWave,FinalWave) )
{
if( !bIsEnabledNow )
EnableMe();
}
else if( bIsEnabledNow )
DisableMe();
}
function bool RandomEnabled( int CurrentWave, int FinalWave )
{
local float OddScale;
local int IScale,OScale;
if( OddsOfAppearing.Length==0 )
return true;
OddScale = float(OddsOfAppearing.Length-1)*(float(CurrentWave)/float(FinalWave));
IScale = Min(int(OddScale),OddsOfAppearing.Length-1);
OddScale-=IScale;
if( OddScale==0 )
return (FRand()<OddsOfAppearing[IScale]);
else if( OddScale<0 )
{
OScale = Max(IScale-1,0);
if( OScale==IScale )
return (FRand()<OddsOfAppearing[IScale]);
OddScale*=-1.f;
return (FRand() < (OddsOfAppearing[IScale]*OddScale+OddsOfAppearing[OScale]*(1.f-OddScale)));
}
else
{
OScale = Max(IScale+1,OddsOfAppearing.Length-1);
if( OScale==IScale )
return (FRand()<OddsOfAppearing[IScale]);
return (FRand() < (OddsOfAppearing[OScale]*OddScale+OddsOfAppearing[IScale]*(1.f-OddScale)));
}
}
function DisableMe()
{
bIsEnabledNow = False;
if( myPickup==None || myPickup.IsInState('Sleeping') || !PlayersCanSeeMe() )
{
if( myPickup!=None )
myPickup.Destroy();
SetTimer(0,False);
}
else SetTimer(1+FRand()*5,False);
}
function EnableMe()
{
bIsEnabledNow = True;
SetTimer(1+ReTryWaitTime*FRand(), false);
}
defaultproperties
{
bForceDefault=True
InitialWaitTime=20.000000
ReTryWaitTime=5.000000
SpawnHeight=0.000000
DrawType=DT_Sprite
bStatic=False
bHidden=True
DrawScale=0.500000
CollisionRadius=60.000000
CollisionHeight=6.000000
bIsEnabledNow=True
}