IW4-Dump-Files/maps/_mortar.gsc

1385 lines
37 KiB
Plaintext

#include common_scripts\utility;
#include maps\_utility;
main()
{
/*
mortars = getentarray ("mortar","targetname");
for (i=0;i<mortars.size;i++)
mortars[i] thread burnville_style_mortar();
if ( !(isdefined (level.mortar) ) )
error ("level.mortar not defined. define in level script");
thread generic_style_init();
*/
}
hurtgen_style()
{
// One mortar within x distance goes off every x seconds but not within x units of the player
mortars = getentarray( "mortar", "targetname" );
lastmortar = -1;
for ( i = 0;i < mortars.size;i++ )
{
mortars[ i ] setup_mortar_terrain();
}
if ( !( isdefined( level.mortar ) ) )
error( "level.mortar not defined. define in level script" );
level waittill( "start_mortars" );
while ( 1 )
{
wait( 1 + ( randomfloat( 2 ) ) );
r = randomint( mortars.size );
//println ("mortar size: ", mortars.size);
//println ("r: ", r);
for ( i = 0;i < mortars.size;i++ )
{
c = ( i + r ) % mortars.size;
//println ("current number: ", c);
d = distance( level.player getorigin(), mortars[ c ].origin );
d2 = undefined;
if ( isdefined( level.foley ) )
d2 = distance( level.foley.origin, mortars[ c ].origin );
else
d2 = 360;
if ( ( d < 1600 ) && ( d > 400 ) && ( d2 > 350 ) && ( c != lastmortar ) )
{
mortars[ c ] activate_mortar( 400, 300, 25, undefined, undefined, undefined, false );
lastmortar = c;
if ( d < 500 )
maps\_shellshock::main( 4 );
// level.player shellshock("default", 4);
break;
}
}
}
}
railyard_style( fRandomtime, iMaxRange, iMinRange, iBlastRadius, iDamageMax, iDamageMin, fQuakepower, iQuaketime, iQuakeradius, targetsUsed, seedtime )
{
// One mortar within iMaxRange distance goes off every (random + random) seconds but not within iMinRange units of the player
// Terminate on demand by setting level.iStopBarrage != 0, operates indefinitely by default
// Pass optional custom radius damage settings to activate_mortar()
// Also pass optional custom earthquake settings to mortar_boom() via activate_mortar() if you want more shaking
if ( !isdefined( fRandomtime ) )
fRandomtime = 7;
if ( !isdefined( iMaxRange ) )
iMaxRange = 2200;
if ( !isdefined( iMinRange ) )
iMinRange = 300;
if ( !isdefined( level.iStopBarrage ) )
level.iStopBarrage = 0;
if ( !isdefined( targetsUsed ) ) // this allows railyard_style to get called again and not setup any terrain related stuff
targetsUsed = 0;
mortars = getentarray( "mortar", "targetname" );
lastmortar = -1;
for ( i = 0;i < mortars.size;i++ )
{
if ( isdefined( mortars[ i ].target ) && ( targetsUsed == 0 ) ) // no target necessary, mortar will just play effect and sound
{
mortars[ i ] setup_mortar_terrain();
}
}
if ( !( isdefined( level.mortar ) ) )
error( "level.mortar not defined. define in level script" );
if ( isdefined( level.mortar_notify ) )
level waittill( level.mortar_notify );
for ( ;; )
{
if ( level.iStopBarrage != 0 )
wait 1;
while ( level.iStopBarrage == 0 )
{
if ( isdefined( seedtime ) )
{
wait( seedtime + ( randomfloat( fRandomtime ) + randomfloat( fRandomtime ) ) );
}
else
{
wait( randomfloat( fRandomtime ) + randomfloat( fRandomtime ) );
}
r = randomint( mortars.size );
//println ("mortar size: ", mortars.size);
//println ("r: ", r);
for ( i = 0;i < mortars.size;i++ )
{
c = ( i + r ) % mortars.size;
//println ("current number: ", c);
d = distance( level.player getorigin(), mortars[ c ].origin );
if ( ( d < iMaxRange ) && ( d > iMinRange ) && ( c != lastmortar ) )
{
mortars[ c ] activate_mortar( iBlastRadius, iDamageMax, iDamageMin, fQuakepower, iQuaketime, iQuakeradius, false );
lastmortar = c;
break;
}
}
}
}
//println("MORTAR BARRAGE TERMINATED");
}
script_mortargroup_style()
{
mortars = [];
mortartrigs = [];
level.mortars = [];
models = getentarray( "script_model", "classname" );
for ( i = 0;i < models.size;i++ )
if ( isdefined( models[ i ].script_mortargroup ) )
{
if ( !isdefined( level.mortars[ models[ i ].script_mortargroup ] ) )
level.mortars[ models[ i ].script_mortargroup ] = [];
mortar = spawnstruct();
mortar.origin = models[ i ].origin;
mortar.angles = models[ i ].angles;
if ( isdefined( models[ i ].targetname ) )
mortar.targetname = models[ i ].targetname;
if ( isdefined( models[ i ].target ) )
mortar.target = models[ i ].target;
level.mortars[ models[ i ].script_mortargroup ]
[ level.mortars[ models[ i ].script_mortargroup ].size ] = mortar;
models[ i ] delete();
// mortars[mortars.size] = models[i];
}
for ( i = 0;i < mortars.size;i++ )
{
mortars[ i ] hide();
// mortars[i] setup_mortar_terrain(); // this was commented out going to run it and find out just why
mortars[ i ].has_terrain = false;
}
if ( !( isdefined( level.mortar ) ) )
level.mortar = loadfx( "explosions/artilleryExp_dirt_brown" );
triggers = array_combine( getentarray( "trigger_multiple", "classname" ), getentarray( "trigger_radius", "classname" ) );
for ( i = 0;i < triggers.size;i++ )
if ( isdefined( triggers[ i ].script_mortargroup ) )
{
if ( !isdefined( level.mortars[ triggers[ i ].script_mortargroup ] ) )
level.mortars[ triggers[ i ].script_mortargroup ] = [];
mortartrigs[ mortartrigs.size ] = triggers[ i ];
}
for ( i = 0;i < mortartrigs.size;i++ )
{
mortartrigs[ i ].mortargroup = 0;
mortartrigs[ i ] thread script_mortargroup_mortar_group();
}
lasttrig = undefined;
while ( 1 )
{
level waittill( "mortarzone", mortartrig );
if ( isdefined( lasttrig ) )
lasttrig notify( "wait again" );
level.mortarzone = mortartrig.script_mortargroup;
mortartrig thread script_mortargroup_mortarzone();
lasttrig = mortartrig;
}
}
script_mortargroup_mortarzone()
{
lastblast = [];
timer = gettime();
timed = false;
if ( isdefined( self.script_timer ) )
{
level notify( "timed barrage" );
timer = gettime() + self.script_timer * 1000;
timed = true;
}
if ( isdefined( self.script_radius ) )
mortar_radius = self.script_radius;
else
mortar_radius = 0;
if ( isdefined( self.script_delay_min ) && isdefined( self.script_delay_max ) )
customdelay = true;
else
customdelay = false;
count = 0;
nonbarragesize = 2;
barragesize = 4;
barraging = false;
while ( ( level.mortars[ self.script_mortargroup ].size > 0 && ( level.mortarzone == self.script_mortargroup ) ) || timed )
{
if ( customdelay )
{
wait( randomfloat( self.script_delay_max - self.script_delay_min ) + self.script_delay_min );
}
else if ( barraging )
{
if ( count < barragesize )
{
wait( randomfloat( .5 ) );
count++ ;
}
else
{
count = 0;
barragesize = 2 + randomint( 4 );
barraging = false;
continue;
}
}
else
{
if ( count < nonbarragesize )
{
delay = randomFloat( 2 ) + 1;
wait( delay );
count++ ;
}
else
{
count = 0;
barraging = true;
nonbarragesize = randomint( 2 ) + 3;
continue;
}
}
mortarsinfront = [];
pick = randomint( level.mortars[ self.script_mortargroup ].size );
if ( randomint( 100 ) < 75 )
{
playerforward = anglestoforward( level.player.angles );
points = [];
for ( i = 0;i < level.mortars[ self.script_mortargroup ].size;i++ )
{
if ( mortar_radius > 0 && distance( level.player.origin, level.mortars[ self.script_mortargroup ][ i ].origin ) > mortar_radius )
continue;
if ( is_lastblast( level.mortars[ self.script_mortargroup ][ i ], lastblast ) )
continue;
normalvec = vectornormalize( level.mortars[ self.script_mortargroup ][ i ].origin - level.player.origin );
if ( vectordot( playerforward, normalvec ) > 0.3 )
points[ points.size ] = i;
}
if ( points.size > 0 )
pick = points[ randomint( points.size ) ];
}
if ( lastblast.size > 3 )
lastblast = [];
lastblast[ lastblast.size ] = level.mortars[ self.script_mortargroup ][ pick ];
level.mortars[ self.script_mortargroup ][ pick ] thread script_mortargroup_domortar();
// self.groupedmortars = array_remove(self.groupedmortars,self.groupedmortars[pick]);
if ( timed && gettime() > timer )
{
if ( isdefined( self.target ) )
{
target = getent( self.target, "targetname" );
if ( isdefined( target ) )
{
target notify( "trigger" );
level notify( "timed barrage finished" );
}
}
break;
}
}
}
is_lastblast( mortar, lastblast )
{
for ( i = 0;i < lastblast.size;i++ )
if ( mortar == lastblast[ i ] )
return true;
return false;
}
script_mortargroup_domortar()
{
if ( isdefined( self.targetname ) && isdefined( level.mortarthread[ self.targetname ] ) )
level thread [[ level.mortarthread[ self.targetname ] ]]( self );
else
self thread activate_mortar( undefined, undefined, undefined, undefined, undefined, undefined, true );
self waittill( "mortar" );
if ( isdefined( self.target ) )
{
targ = getent( self.target, "targetname" );
if ( isdefined( targ ) )
targ notify( "trigger" );
}
}
script_mortargroup_mortar_group()
{
while ( 1 )
{
self waittill( "trigger" );
if ( isdefined( level.mortarzone ) && level.mortarzone == self.script_mortargroup )
continue;
level notify( "mortarzone", self );
self waittill( "wait again" );
}
}
trigger_targeted()
{
//While the player is touching a trigger named "mortartrigger" a targeted script_origin mortar with a defined
//script_mortargroup value will go off every x seconds regardless of the players distance to the mortar.
level.mortartrigger = getentarray( "mortartrigger", "targetname" );
level.mortars = getentarray( "script_origin", "classname" );
for ( i = 0;i < level.mortars.size;i++ )
{
if ( isdefined( level.mortars[ i ].script_mortargroup ) )
{
level.mortars[ i ] setup_mortar_terrain();
}
}
level.lastmortar = -1;
if ( !( isdefined( level.mortar ) ) )
error( "level.mortar not defined. define in level script" );
for ( i = 0;i < level.mortartrigger.size;i++ )
{
thread trigger_targeted_mortars( i );
}
}
trigger_targeted_mortars( num )
{
targeted_mortars = getentarray( level.mortartrigger[ num ].target, "targetname" );
while ( 1 )
{
if ( level.player istouching( level.mortartrigger[ num ] ) )
{
r = randomint( targeted_mortars.size );
while ( r == level.lastmortar )
{
r = randomint( targeted_mortars.size );
wait .1;
}
targeted_mortars[ r ] activate_mortar( undefined, undefined, undefined, undefined, undefined, undefined, false );
level.lastmortar = r;
}
wait( randomfloat( 3 ) + randomfloat( 4 ) );
}
}
bunker_style_mortar()
{
// script_structs are placed in the level and grouped with script_mortargroup with targetname "mortar"
// mortar group is turned on/off in script or with triggers with targetname "mortar_on" or "mortar_off"
// mortar locations will all go simultaneously when an artillery round hits if within FOV of the player (dust falling from ceiling)
// each mortar location has script_fxid so it can play a set fx
// mortars will go forever until that group of mortars is notified to stop
mortar_bunker_array = [];
ents = undefined;
groupNum = [];
structs = getstructarray( "mortar_bunker", "targetname" );
trigs = getentarray( "mortar_bunker", "targetname" );
if ( ( isdefined( trigs ) ) && ( trigs.size > 0 ) )
ents = array_merge( structs, trigs );
else
ents = structs;
assert( isdefined( ents ) );
assert( ents.size > 0 );
for ( i = 0 ; i < ents.size ; i++ )
{
if ( !isdefined( ents[ i ].script_mortargroup ) )
continue;
index = -1;
groupNumber = int( ents[ i ].script_mortargroup );
for ( p = 0 ; p < mortar_bunker_array.size ; p++ )
{
if ( groupNumber != groupNum[ p ] )
continue;
index = p;
break;
}
if ( index == -1 )
{
// new group
mortar_bunker_array[ mortar_bunker_array.size ] = [];
groupNum[ groupNum.size ] = groupNumber;
index = mortar_bunker_array.size - 1;
}
mortar_bunker_array[ index ][ mortar_bunker_array[ index ].size ] = ents[ i ];
}
for ( i = 0 ; i < mortar_bunker_array.size ; i++ )
thread bunker_style_mortar_think( mortar_bunker_array[ i ], structs );
wait 0.05;
array_thread( getentarray( "mortar_on", "targetname" ), ::bunker_style_mortar_trigger, "on" );
array_thread( getentarray( "mortar_off", "targetname" ), ::bunker_style_mortar_trigger, "off" );
}
bunker_style_mortar_think( mortar_bunker_array, structs )
{
min = undefined;
max = undefined;
if ( isdefined( level.mortarMinInterval ) )
min = level.mortarMinInterval;
else
min = 4;
if ( isdefined( level.mortarMaxInterval ) )
max = level.mortarMaxInterval;
else
max = 6;
groupNum = int( mortar_bunker_array[ 0 ].script_mortargroup );
for ( ;; )
{
level waittill( "start_mortars " + groupNum );
thread bunker_style_mortar_activate( mortar_bunker_array, min, max, groupNum, structs );
}
}
bunker_style_mortar_activate( mortar_bunker_array, min, max, groupNum, structs )
{
level endon( "start_mortars " + groupNum );
level endon( "stop_mortars " + groupNum );
while ( true )
{
wait( 0.05 );
sound_org = getclosest( level.player.origin, structs );
if( !isdefined( level.mortarNoIncomingSound ) )
{
play_sound_in_space( "mortar_incoming_bunker", sound_org.origin );
}
sound_org = getclosest( level.player.origin, structs );
//thread play_sound_in_space( "mortar_explosion_bunker", sound_org.origin );
thread play_sound_in_space( "exp_artillery_underground", sound_org.origin );
array_thread( mortar_bunker_array,::bunker_style_mortar_explode );
if( !isdefined( level.mortarNoQuake ) )
{
if ( cointoss() )
earthquake( 0.20, 1.5, sound_org.origin, 1250 );
else
earthquake( 0.35, 2.75, sound_org.origin, 1250 );
}
level notify( "mortar_hit" );
wait( randomfloatrange( min, max ) );
mortar_bunker_array = remove_undefined_from_array( mortar_bunker_array );
}
}
bunker_style_mortar_explode( min, max )
{
if ( !isdefined( self ) )
return;
/*-----------------------
ONLY PLAY EFFECT/ACTIVATE TRIGGER IF WITHIN PLAYER FOV
-------------------------*/
if ( ( isdefined( level.mortarWithinFOV ) ) && ( self mortar_within_player_fov( level.mortarWithinFOV ) == false ) )
return;
/*-----------------------
ONLY PLAY EFFECT/ACTIVATE TRIGGER IF WITHIN RADIUS
-------------------------*/
if ( isdefined( level.mortar_min_dist ) )
min_dist = level.mortar_min_dist;
else
min_dist = 1024;
min_dist_squared = min_dist * min_dist;
distSquared = distancesquared( level.player.origin, self.origin );
if ( distSquared > min_dist_squared )
return;
/*-----------------------
IF IT'S A TRIGGER RADIUS, DO DAMAGE TO BUST UP DESTRUCTIBLES
-------------------------*/
//trigger radius are put around destructibles that you want damaged if the player is looking at it
if ( ( isdefined( self.classname ) ) && ( self.classname == "trigger_radius") )
{
if ( ( !level.player istouching( self ) ) && ( distance( level.player.origin, self.origin ) < level.mortarDamageTriggerDist ) )
{
RadiusDamage( self.origin, self.radius, 500, 500 );
self delete();
return;
}
}
/*-----------------------
OTHERWISE, PLAY CEILING DUST
-------------------------*/
else
{
playfx( level._effect[ "mortar" ][ self.script_fxid ], self.origin );
if ( distSquared < 262144 ) //only play sound when within 512
thread play_sound_in_space( "emt_single_ceiling_debris", self.origin );
}
}
bog_style_mortar()
{
// script_structs are placed in the level and grouped with script_mortargroup with targetname "mortar"
// mortar group is turned on/off in script
// mortar locations will start going off randomly and wont go off within x units of the player
// each mortar location has script_fxid so it can play a set fx ( this allows having mortars on land and water in the same group )
// mortars will go forever until that group of mortars is notified to stop
// each mortar has a cooldown time of x seconds before it can be used again
groups = [];
groupNum = [];
structs = getstructarray( "mortar", "targetname" );
assert( isdefined( structs ) );
assert( structs.size > 0 );
for ( i = 0 ; i < structs.size ; i++ )
{
if ( !isdefined( structs[ i ].script_mortargroup ) )
continue;
index = -1;
groupNumber = int( structs[ i ].script_mortargroup );
for ( p = 0 ; p < groups.size ; p++ )
{
if ( groupNumber != groupNum[ p ] )
continue;
index = p;
break;
}
if ( index == -1 )
{
// new group
groups[ groups.size ] = [];
groupNum[ groupNum.size ] = groupNumber;
index = groups.size - 1;
}
groups[ index ][ groups[ index ].size ] = structs[ i ];
}
for ( i = 0 ; i < groups.size ; i++ )
thread bog_style_mortar_think( groups[ i ] );
wait 0.05;
array_thread( getentarray( "mortar_on", "targetname" ), ::bog_style_mortar_trigger, "on" );
array_thread( getentarray( "mortar_off", "targetname" ), ::bog_style_mortar_trigger, "off" );
}
bog_style_mortar_think( mortars, groupNum )
{
min = undefined;
max = undefined;
if ( isdefined( level.mortarMinInterval ) )
min = level.mortarMinInterval;
else
min = 0.5;
if ( isdefined( level.mortarMaxInterval ) )
max = level.mortarMaxInterval;
else
max = 3;
groupNum = int( mortars[ 0 ].script_mortargroup );
for ( ;; )
{
level waittill( "start_mortars " + groupNum );
level thread bog_style_mortar_activate( mortars, groupNum, min, max );
}
}
bog_style_mortar_activate( mortars, groupNum, min, max )
{
level endon( "start_mortars " + groupNum );
level endon( "stop_mortars " + groupNum );
if ( isdefined( level.mortar_min_dist ) )
min_dist = level.mortar_min_dist;
else
min_dist = 300;
//trigger used to check if friendlies is too close (if level.mortarExcluders is defined)
mortarDistanceTrigger = spawn( "trigger_radius", ( 0, 0, 0), 0, min_dist, 256 );
thread bog_style_mortar_cleanup( mortarDistanceTrigger, groupNum );
for ( ;; )
{
for ( ;; )
{
wait 0.05;
rand = randomint( mortars.size );
if ( isdefined( mortars[ rand ].cooldown ) )
continue;
//don't trigger mortar if player too close
d = distance( level.player.origin, mortars[ rand ].origin );
if ( d < min_dist )
continue;
//don't trigger mortar in case we have friendlies we do not want to be hit by mortars
if ( ( isdefined( level.mortarExcluders ) ) && ( level.mortarExcluders.size > 0 ) )
{
mortarDistanceTrigger.origin = mortars[ rand ].origin; //trigger_radius used to determine if level.mortarExcluders are too close to detonate
if ( mortars_too_close( level.mortarExcluders, mortarDistanceTrigger ) )
continue;
}
// in case we need to see mortars in the distance
if ( !isdefined( level.noMaxMortarDist ) && ( d > 1000 ) )
continue;
if ( ( isdefined( level.mortar_max_dist ) ) && ( d > level.mortar_max_dist ) )
continue;
//if we need to check player FOV
if ( ( isdefined( level.mortarWithinFOV ) ) && ( mortars[ rand ] mortar_within_player_fov( level.mortarWithinFOV ) == false ) )
continue;
break;
}
if ( ( isdefined( level.noMortars ) ) && ( level.noMortars == true ) )
return;
mortars[ rand ] thread bog_style_mortar_explode();
wait( min + randomfloat( max - min ) );
}
}
bog_style_mortar_cleanup( mortarDistanceTrigger, groupNum )
{
level waittill( "stop_mortars " + groupNum );
mortarDistanceTrigger delete(); //delete the trigger_radius used to determine if level.mortarExcluders are too close to detonate
}
mortars_too_close( mortarExcluders, mortarDistanceTrigger )
{
foreach ( guy in level.mortarExcluders )
{
if ( !isalive( guy ) )
continue;
if ( !isdefined( guy ) )
continue;
if ( guy istouching( mortarDistanceTrigger ) )
return true;
}
return false;
}
mortar_within_player_fov( fov )
{
playerEye = level.player getEye();
playerMortarFovOffset = ( 0, 0, 0 );
if ( isdefined( level.playerMortarFovOffset ) )
playerMortarFovOffset = level.playerMortarFovOffset;
bInFOV = within_fov( playerEye, level.player getPlayerAngles() + playerMortarFovOffset, self.origin, fov );
return bInFOV;
}
bog_style_mortar_explode( instant, customExploSound )
{
if ( !isdefined( level.mortarDamageRadius ) )
level.mortarDamageRadius = 250;
if ( !isdefined( instant ) )
instant = false;
self thread bog_style_mortar_cooldown();
if ( !instant )
self play_sound_in_space( level.scr_sound[ "mortar" ][ "incomming" ] );
if ( isdefined( customExploSound ) )
self thread play_sound_in_space( customExploSound );
else
self thread play_sound_in_space( level.scr_sound[ "mortar" ][ self.script_fxid ] );
//dont play an effect if it's behind the player - trying to save on particle effects
setplayerignoreradiusdamage( true );
radiusDamage( self.origin, level.mortarDamageRadius, 150, 50 );
setplayerignoreradiusdamage( false );
playfx( level._effect[ "mortar" ][ self.script_fxid ], self.origin );
if( isdefined( level.alwaysquake ) )
{
earthquake( 0.3, 1, level.player.origin, 2000 );
}
if ( getdvarint( "bog_camerashake" ) > 0 )
{
//if player is trying to snipe dont do view shake
if ( ( level.player getCurrentWeapon() == "dragunov" ) && ( level.player playerADS() > 0.8 ) )
return;
earthquake( 0.25, 0.75, self.origin, 1250 );
}
}
bog_style_mortar_cooldown()
{
self.cooldown = true;
wait( 3 + randomfloat( 2 ) );
self.cooldown = undefined;
}
bog_style_mortar_trigger( value )
{
assert( isdefined( self.script_mortargroup ) );
self waittill( "trigger" );
if ( value == "on" )
bog_style_mortar_on( self.script_mortargroup );
else if ( value == "off" )
bog_style_mortar_off( self.script_mortargroup );
}
bog_style_mortar_on( groupNum )
{
level notify( "start_mortars " + groupNum );
}
bog_style_mortar_off( groupNum )
{
level notify( "stop_mortars " + groupNum );
}
bunker_style_mortar_on( groupNum )
{
if ( !isdefined( level.mortarDamageTriggerDist ) )
level.mortarDamageTriggerDist = 512;
if ( !isdefined( level.mortarWithinFOV ) )
level.mortarWithinFOV = cos( 35 );
level notify( "start_mortars " + groupNum );
}
bunker_style_mortar_off( groupNum )
{
level waittill( "mortar_hit" ); //don't interrupt in the middle of an incoming sound before it hits
level notify( "stop_mortars " + groupNum );
}
bunker_style_mortar_off_nowait( groupNum )
{
level notify( "stop_mortars " + groupNum );
}
bunker_style_mortar_trigger( value )
{
assert( isdefined( self.script_mortargroup ) );
self waittill( "trigger" );
if ( value == "on" )
bunker_style_mortar_on( self.script_mortargroup );
else if ( value == "off" )
bunker_style_mortar_off( self.script_mortargroup );
}
burnville_style_mortar()
{
// Mortar waits for player to come within x units. Then explodes every x seconds if player is x range away
level endon( "stop falling mortars" );
setup_mortar_terrain();
wait( randomfloat( 0.5 ) + randomfloat( 0.5 ) );
while ( 1 )
{
if ( distance( level.player getorigin(), self.origin ) < 600 )
{
activate_mortar( undefined, undefined, undefined, undefined, undefined, undefined, false );
break;
}
wait( 1 );
}
wait( 7 + randomfloat( 20 ) );
while ( 1 )
{
if ( ( distance( level.player getorigin(), self.origin ) < 1200 ) &&
( distance( level.player getorigin(), self.origin ) > 400 ) )
{
activate_mortar( undefined, undefined, undefined, undefined, undefined, undefined, false );
wait( 3 + randomfloat( 14 ) );
}
wait( 1 );
}
}
setup_mortar_terrain()
{
self.has_terrain = false;
if ( isdefined( self.target ) )
{
self.terrain = getentarray( self.target, "targetname" );
self.has_terrain = true;
}
else
{
println( "z: mortar entity has no target: ", self.origin );
}
if ( !isdefined( self.terrain ) )
println( "z: mortar entity has target, but target doesnt exist: ", self.origin );
if ( isdefined( self.script_hidden ) )
{
if ( isdefined( self.script_hidden ) )
self.hidden_terrain = getent( self.script_hidden, "targetname" );
else if ( ( isdefined( self.terrain ) ) && ( isdefined( self.terrain[ 0 ].target ) ) )
self.hidden_terrain = getent( self.terrain[ 0 ].target, "targetname" );
if ( isdefined( self.hidden_terrain ) )
self.hidden_terrain hide();
}
else if ( isdefined( self.has_terrain ) )
{
if ( ( isdefined( self.terrain ) ) && ( isdefined( self.terrain[ 0 ].target ) ) )
self.hidden_terrain = getent( self.terrain[ 0 ].target, "targetname" );
if ( isdefined( self.hidden_terrain ) )
self.hidden_terrain hide();
}
}
activate_mortar( range, max_damage, min_damage, fQuakepower, iQuaketime, iQuakeradius, bIsstruct )
{
// if(bIsstruct)
// {
// if(distance(self.origin,level.player.origin) < 1000)
// incoming_sound( undefined, bIsstruct );
// }
// else
incoming_sound( undefined, bIsstruct );
level notify( "mortar" );
self notify( "mortar" );
if ( !isdefined( range ) )
range = 256;
if ( !isdefined( max_damage ) )
max_damage = 400;
if ( !isdefined( min_damage ) )
min_damage = 25;
radiusDamage( self.origin, range, max_damage, min_damage );
if ( ( isdefined( self.has_terrain ) && self.has_terrain == true ) && ( isdefined( self.terrain ) ) )
{
for ( i = 0;i < self.terrain.size;i++ )
{
if ( isdefined( self.terrain[ i ] ) )
self.terrain[ i ] delete();
}
}
if ( isdefined( self.hidden_terrain ) )
self.hidden_terrain show();
self.has_terrain = false;
mortar_boom( self.origin, fQuakepower, iQuaketime, iQuakeradius, undefined, bIsstruct );
}
mortar_boom( origin, fPower, iTime, iRadius, effect, bIsstruct )
{
if ( !isdefined( fPower ) )
fPower = 0.15;
if ( !isdefined( iTime ) )
iTime = 2;
if ( !isdefined( iRadius ) )
iRadius = 850;
thread mortar_sound( bIsstruct );
if ( isdefined( effect ) )
playfx( effect, origin );
else
playfx( level.mortar, origin );
earthquake( fPower, iTime, origin, iRadius );
// Special Burnville Shell shocking
if ( level.script != "burnville" )
return;
if ( isdefined( level.playerMortar ) )
return;
if ( distance( level.player.origin, origin ) > 300 )
return;
if ( level.script == "carchase" || level.script == "breakout" )
return;
level.playerMortar = true;
level notify( "shell shock player", iTime * 4 );
maps\_shellshock::main( iTime * 4 );
// level.player shellshock("default", iTime*4);
// earthquake(0.15, 2, origin, 1050);
/*
earthquake(float scale, float duration, vector source, float radius)
Example:
scale = 0.15;
duration = 1;
source = (866, 2240, 0);
radius = 600;
earthquake(scale, duration, source, radius);
*/
}
mortar_sound( bIsstruct )
{
if ( !isdefined( level.mortar_last_sound ) )
level.mortar_last_sound = -1;
soundnum = randomint( 3 ) + 1;
while ( soundnum == level.mortar_last_sound )
soundnum = randomint( 3 ) + 1;
level.mortar_last_sound = soundnum;
if ( !bIsstruct )
self playsound( "mortar_explosion" + soundnum );
else
play_sound_in_space( "mortar_explosion" + soundnum, self.origin );
}
incoming_sound( soundnum, bIsstruct )
{
currenttime = gettime();
if ( !isdefined( level.lastmortarincomingtime ) )
{
level.lastmortarincomingtime = currenttime;
}
else if ( ( currenttime - level.lastmortarincomingtime ) < 1000 )
{
wait 1;
return;
}
else
{
level.lastmortarincomingtime = currenttime;
}
if ( !isdefined( soundnum ) )
soundnum = randomint( 3 ) + 1;
if ( soundnum == 1 )
{
if ( bIsstruct )
thread play_sound_in_space( "mortar_incoming1", self.origin );
else
self playsound( "mortar_incoming1" );
wait( 1.07 - 0.25 );
}
else
if ( soundnum == 2 )
{
if ( bIsstruct )
thread play_sound_in_space( "mortar_incoming2", self.origin );
else
self playsound( "mortar_incoming2" );
wait( 0.67 - 0.25 );
}
else
{
if ( bIsstruct )
thread play_sound_in_space( "mortar_incoming3", self.origin );
else
self playsound( "mortar_incoming3" );
wait( 1.55 - 0.25 );
}
}
generic_style_init()
{
level._explosion_iMaxRange = [];
level._explosion_iMinRange = [];
level._explosion_iBlastRadius = [];
level._explosion_iDamageMax = [];
level._explosion_iDamageMin = [];
level._explosion_fQuakePower = [];
level._explosion_iQuakeTime = [];
level._explosion_iQuakeRadius = [];
}
generic_style_setradius( strExplosion, iMinRange, iMaxRange )
{
level._explosion_iMinRange[ strExplosion ] = iMinRange;
level._explosion_iMaxRange[ strExplosion ] = iMaxRange;
}
generic_style_setdamage( strExplosion, iBlastRadius, iDamageMin, iDamageMax )
{
level._explosion_iBlastRadius[ strExplosion ] = iBlastRadius;
level._explosion_iDamageMin[ strExplosion ] = iDamageMin;
level._explosion_iDamageMax[ strExplosion ] = iDamageMax;
}
generic_style_setquake( strExplosion, fQuakePower, iQuakeTime, iQuakeRadius )
{
level._explosion_fQuakePower[ strExplosion ] = fQuakePower;
level._explosion_iQuakeTime[ strExplosion ] = iQuakeTime;
level._explosion_iQuakeRadius[ strExplosion ] = iQuakeRadius;
}
// REQUIRED: level._effect[strExplosion] = loadfx(...);
// REQUIRED: level._effectType[strExplosion] = strType ("mortar", "bomb" or "artillery")
// Allows for multiple sets of explosions in a single level
// One explosion within iMaxRange distance goes off every (random + random) seconds but not within iMinRange units of the player
// Starts on notify specified by level.explosion_start[strExplosion]
// Terminates on notify specified by level.explosion_stop[strExplosion]
// Terminate on demand by setting level.bStopBarrage[strExplosion] == true, operates indefinitely by default
generic_style( strExplosion, fDelay, iBarrageSize, fBarrageDelay, iMinRange, iMaxRange, bTargetsUsed )
{
//// Safety checks
assertex( ( isdefined( strExplosion ) && ( strExplosion != "" ) ), "strExplosion not passed. pass in level script" );
assertex( ( isdefined( level._effect ) && isdefined( level._effect[ strExplosion ] ) ), "level._effect[strMortars] not defined. define in level script" );
//// Initialize Defaults
iLastExplosion = -1;
iMaxRangeLocal = iMaxRange;
iMinRangeLocal = iMinRange;
generic_style_setradius( strExplosion, 300, 2200 );
if ( !isdefined( fDelay ) )
fDelay = 7;
if ( !isdefined( iBarrageSize ) )
iBarrageSize = 1;
if ( !isdefined( fBarrageDelay ) )
fBarrageDelay = 0;
if ( !isdefined( bTargetsUsed ) ) // this allows generic_style to get called again and not setup any terrain related stuff
bTargetsUsed = false;
if ( isdefined( level.explosion_stopNotify ) && isdefined( level.explosion_stopNotify[ strExplosion ] ) )
level endon( level.explosion_stopNotify[ strExplosion ] );
// for backwards compatibility
if ( !isdefined( level.bStopBarrage ) || !isdefined( level.bStopBarrage[ strExplosion ] ) )
level.bStopBarrage[ strExplosion ] = false;
//// Explosion Points
aeExplosions = getentarray( strExplosion, "targetname" );
//// Terrain Setup
for ( i = 0; i < aeExplosions.size; i++ )
{
if ( isdefined( aeExplosions[ i ].target ) && ( !bTargetsUsed ) ) // no target necessary, mortar will just play effect and sound
aeExplosions[ i ] setup_mortar_terrain();
}
//// Start Wait
if ( isdefined( level.explosion_startNotify ) && isdefined( level.explosion_startNotify[ strExplosion ] ) )
level waittill( level.explosion_startNotify[ strExplosion ] );
//// Main Loop
while ( true )
{
while ( !level.bStopBarrage[ strExplosion ] )
{
for ( j = 0; j < iBarrageSize; j++ )
{
// putting this here allows for updates during barrage
if ( !isdefined( iMaxRange ) )
iMaxRangeLocal = level._explosion_iMaxRange[ strExplosion ];
if ( !isdefined( iMinRange ) )
iMinRangeLocal = level._explosion_iMinRange[ strExplosion ];
iRand = randomint( aeExplosions.size );
for ( i = 0; i < aeExplosions.size; i++ )
{
iCur = ( i + iRand ) % aeExplosions.size;
fDist = distance( level.player getorigin(), aeExplosions[ iCur ].origin );
if ( ( fDist < iMaxRangeLocal ) && ( fDist > iMinRangeLocal ) && ( iCur != iLastExplosion ) )
// if ( (fDist < iMaxRangeLocal) && (fDist > iMinRangeLocal))
{
aeExplosions[ iCur ].iMinRange = iMinRangeLocal;
aeExplosions[ iCur ] explosion_activate( strExplosion );
iLastExplosion = iCur;
break;
}
}
iLastExplosion = -1;
if ( isdefined( level.explosion_delay ) && isdefined( level.explosion_delay[ strExplosion ] ) )
wait( level.explosion_delay[ strExplosion ] );
else
wait( randomfloat( fDelay ) + randomFloat( fDelay ) );
}
if ( isdefined( level.explosion_barrage_delay ) && isdefined( level.explosion_barrage_delay[ strExplosion ] ) )
wait( level.explosion_barrage_delay[ strExplosion ] );
else
wait( randomfloat( fBarrageDelay ) + randomFloat( fBarrageDelay ) );
}
wait( 0.05 );
}
}
explosion_activate( strExplosion, iBlastRadius, iDamageMin, iDamageMax, fQuakePower, iQuakeTime, iQuakeRadius )
{
//// Initialize Defaults
generic_style_setdamage( strExplosion, 256, 25, 400 );
generic_style_setquake( strExplosion, 0.15, 2, 850 );
if ( !isdefined( iBlastRadius ) )
iBlastRadius = level._explosion_iBlastRadius[ strExplosion ];
if ( !isdefined( iDamageMin ) )
iDamageMin = level._explosion_iDamageMin[ strExplosion ];
if ( !isdefined( iDamageMax ) )
iDamageMax = level._explosion_iDamageMax[ strExplosion ];
if ( !isdefined( fQuakePower ) )
fQuakePower = level._explosion_fQuakePower[ strExplosion ];
if ( !isdefined( iQuakeTime ) )
iQuakeTime = level._explosion_iQuakeTime[ strExplosion ];
if ( !isdefined( iQuakeRadius ) )
iQuakeRadius = level._explosion_iQuakeRadius[ strExplosion ];
//// Incoming Sound
explosion_incoming( strExplosion );
level notify( "explosion", strExplosion );
bDoDamage = true;
fPreDist = undefined;
eLocation = self;
if ( isdefined( self.iMinRange ) && distance( level.player.origin, self.origin ) < self.iMinRange )
{
// get closest location outside iMinRange
aeExplosions = getentarray( strExplosion, "targetname" );
for ( iCur = 0; iCur < aeExplosions.size; iCur++ )
{
fDist = distance( level.player getorigin(), aeExplosions[ iCur ].origin );
if ( fDist > self.iMinRange )
{
if ( !isdefined( fPreDist ) || fDist < fPreDist )
{
fPreDist = fDist;
eLocation = aeExplosions[ iCur ];
}
}
}
if ( !isdefined( fPreDist ) )
{
bDoDamage = false;
}
}
if ( bDoDamage )
radiusDamage( eLocation.origin, iBlastRadius, iDamageMax, iDamageMin );
//// Process Terrain
if ( ( isdefined( eLocation.has_terrain ) && eLocation.has_terrain == true ) && ( isdefined( eLocation.terrain ) ) )
{
for ( i = 0;i < eLocation.terrain.size;i++ )
{
if ( isdefined( eLocation.terrain[ i ] ) )
eLocation.terrain[ i ] delete();
}
}
if ( isdefined( eLocation.hidden_terrain ) )
eLocation.hidden_terrain show();
eLocation.has_terrain = false;
//// Explosion Effects
eLocation explosion_boom( strExplosion, fQuakePower, iQuakeTime, iQuakeRadius );
}
explosion_boom( strExplosion, fPower, iTime, iRadius )
{
if ( !isdefined( fPower ) )
fPower = 0.15;
if ( !isdefined( iTime ) )
iTime = 2;
if ( !isdefined( iRadius ) )
iRadius = 850;
explosion_sound( strExplosion );
explosion_origin = self.origin;
playfx( level._effect[ strExplosion ], explosion_origin );
earthquake( fPower, iTime, explosion_origin, iRadius );
if ( distance( level.player.origin, explosion_origin ) > 300 )
return;
if ( level.script == "carchase" || level.script == "breakout" )
return;
level.playerMortar = true;
level notify( "shell shock player", iTime * 4 );
maps\_shellshock::main( iTime * 4 );
}
explosion_sound( strExplosion )
{
if ( !isdefined( level._explosion_last_sound ) )
level._explosion_last_sound = 0;
soundnum = randomint( 3 ) + 1;
while ( soundnum == level._explosion_last_sound )
soundnum = randomint( 3 ) + 1;
level._explosion_last_sound = soundnum;
if ( level._effectType[ strExplosion ] == "mortar" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_explosion1" );
break;
case 2:
self playsound( "mortar_explosion2" );
break;
case 3:
self playsound( "mortar_explosion3" );
break;
}
}
else if ( level._effectType[ strExplosion ] == "artillery" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_explosion4" );
break;
case 2:
self playsound( "mortar_explosion5" );
break;
case 3:
self playsound( "mortar_explosion1" );
break;
}
}
else if ( level._effectType[ strExplosion ] == "bomb" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_explosion1" );
break;
case 2:
self playsound( "mortar_explosion4" );
break;
case 3:
self playsound( "mortar_explosion5" );
break;
}
}
}
explosion_incoming( strExplosion, soundnum )
{
if ( !isdefined( level._explosion_last_incoming ) )
level._explosion_last_incoming = -1;
soundnum = randomint( 4 ) + 1;
while ( soundnum == level._explosion_last_incoming )
soundnum = randomint( 4 ) + 1;
level._explosion_last_incoming = soundnum;
if ( level._effectType[ strExplosion ] == "mortar" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_incoming1" );
wait( 1.07 - 0.25 );
break;
case 2:
self playsound( "mortar_incoming2" );
wait( 0.67 - 0.25 );
break;
case 3:
self playsound( "mortar_incoming3" );
wait( 1.55 - 0.25 );
break;
default:
wait( 1.75 );
break;
}
}
else if ( level._effectType[ strExplosion ] == "artillery" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_incoming4" );
wait( 1.07 - 0.25 );
break;
case 2:
self playsound( "mortar_incoming4_new" );
wait( 0.67 - 0.25 );
break;
case 3:
self playsound( "mortar_incoming1_new" );
wait( 1.55 - 0.25 );
break;
default:
wait( 1.75 );
break;
}
}
else if ( level._effectType[ strExplosion ] == "bomb" )
{
switch( soundnum )
{
case 1:
self playsound( "mortar_incoming2_new" );
wait( 1.75 );
break;
case 2:
self playsound( "mortar_incoming3_new" );
wait( 1.75 );
break;
case 3:
self playsound( "mortar_incoming4_new" );
wait( 1.75 );
break;
default:
wait( 1.75 );
break;
}
}
}