What I want to do:
- Tweak fcas3t's Dynamic Enemy Reinforcement mod to make the spawns FRIENDLY instead of the default (HOSTILE).
Here's his code (and please, tell me if this is not proper to do here). I'd ask him, but he doesn't appear to exist on the forum anymore. Also, this is my first ever thread so be kind. I look up to all of you.
Thanks in advance for reading, and any help you can provide.
Code: Select all
version 4.2
class derSP : Actor // spawn point
{
Default { +NOINTERACTION }
}
class DER_EventHandler : EventHandler
{
private Array< derSP > AllStaticSPs;
private Array< string > EnemyRoster;
private int LastRosterIdx;
private int timer;
private bool retrying;
private bool SpawnOneAt( derSP spawnPoint )
{
Actor m = Actor.Spawn( EnemyRoster[ random( 0, LastRosterIdx ) ],
spawnPoint.pos, ALLOW_REPLACE );
if ( !m )
{
return false;
}
Vector2 offset = ( random(-2, 2) * 2, random(-2, 2) * 2 );
offset *= m.radius;
Vector3 offsetpos = ( m.pos.xy + offset, m.pos.z );
Vector2 lineVector = offsetpos.xy - m.pos.xy;
FLineTraceData ltdata;
m.LineTrace( VectorAngle( lineVector.x, lineVector.y ),
lineVector.length(), 0, TRF_THRUACTORS, data: ltdata );
m.SetOrigin( m.pos + (ltdata.HitDir).unit() * (ltdata.distance - 8.0), false );
double nudge = m.radius * 2.0;
for ( double a = 0.1; a < 359.0; a += 22.5 )
{
m.LineTrace( a, nudge, 0, data: ltdata );
if ( ltdata.distance < nudge )
{
m.SetOrigin( m.pos - ltdata.HitDir * (nudge - ltdata.distance), false );
break;
}
}
m.SetOrigin(( m.pos.xy, m.floorz ), false );
if ( m.height > ( m.ceilingz - m.floorz )
|| !m.TestMobjLocation() || !m.CheckMove( m.pos.xy ))
{
m.ClearCounters();
m.Destroy();
return false;
}
m.angle = spawnPoint.angle + frandom( -45, 45 );
Actor.Spawn( "TeleportFog", m.pos );
return true;
}
/* This function is invoked both at the start of each map and when loading a
save file. Because of the second case, LastRosterIdx must not be set here,
which is fine, since the proper value from the 3rd tick is in the save file.
*/
override void OnRegister()
{
timer = 35 * random( der_min_seconds, der_max_seconds );
retrying = false;
}
override void WorldTick()
{
if ( level.time == 2 )
{
let iterator = ThinkerIterator.Create( "Actor" );
Actor m;
while ( m = Actor( iterator.Next() ))
{
if ( GetDefaultByType( Actor.GetReplacee( m.GetClassName() )).bIsMonster
&& !m.bBoss && !m.bBossDeath )
{
derSP sp = derSP( Actor.Spawn( "derSP", m.pos ));
sp.angle = m.angle;
AllStaticSPs.push( sp );
string cName = m.GetClassName();
/* Barons, Cyberdemons, Masterminds, Arachnotrons, and Mancubi
are already excluded because of their boss flags.
*/
if ( cName != "EVPSpectre" &&
cName != "EVPRevenant" &&
cName != "EVPArchvile" &&
cName != "EVPPainElemental" )
{
EnemyRoster.push( cName );
}
}
}
for ( int j = der_dilute; j > 0; j -= 1 )
{
EnemyRoster.push( "Zombieman" );
EnemyRoster.push( "DoomImp" );
EnemyRoster.push( "ShotgunGuy" );
}
LastRosterIdx = EnemyRoster.size() - 1;
}
timer -= 1;
if ( timer > 0 || LastRosterIdx == -1 )
{
return;
}
if ( !retrying && random( 0, 99 ) >= der_chance )
{
timer = 35 * random( der_min_seconds, der_max_seconds );
return;
}
let player = players[ 0 ].mo;
Array< derSP > validSPs;
for ( int j = AllStaticSPs.size() - 1;
j >= 0; j -= 1 )
{
double dist = player.Distance2D( AllStaticSPs[ j ] );
if ( dist >= der_min_distance && dist <= der_max_distance )
{
validSPs.push( AllStaticSPs[ j ] );
}
}
if ( validSPs.size() == 0 )
{
timer = 3 * 35;
retrying = true;
return;
}
timer = 35 * random( der_min_seconds, der_max_seconds );
retrying = false;
int lastVspIdx = validSPs.size() - 1;
for ( int j = random( der_min_groups, der_max_groups );
j > 0; j -= 1 )
{
derSP sp = validSPs[ random( 0, lastVspIdx ) ];
int numFails = 0;
for ( int k = random( der_min_pergroup, der_max_pergroup );
k > 0; k -= 1 )
{
if ( SpawnOneAt( sp ) == false )
{
numFails += 1;
if ( numFails == 10 )
{
break;
}
// try again
k += 1;
}
}
}
}
}