1483 lines
46 KiB
Plaintext
1483 lines
46 KiB
Plaintext
#include maps\_utility;
|
|
#include common_scripts\utility;
|
|
main()
|
|
{
|
|
// -- -- -- -- -- -- -- -- --
|
|
// EFECTS DEFINITIONS
|
|
// -- -- -- -- -- -- -- -- --
|
|
|
|
flag_init( "no_ai_tv_damage" );
|
|
qBarrels = false;
|
|
|
|
barrels = getentarray( "explodable_barrel", "targetname" );
|
|
if ( barrels.size )
|
|
qBarrels = true;
|
|
|
|
barrels = getentarray( "explodable_barrel", "script_noteworthy" );
|
|
if ( barrels.size > 0 )
|
|
qBarrels = true;
|
|
|
|
if ( qBarrels )
|
|
{
|
|
level.breakables_fx[ "barrel" ][ "explode" ] = loadfx( "props/barrelExp" );
|
|
level.breakables_fx[ "barrel" ][ "burn_start" ] = loadfx( "props/barrel_ignite" );
|
|
level.breakables_fx[ "barrel" ][ "burn" ] = loadfx( "props/barrel_fire_top" );
|
|
}
|
|
|
|
oilspill = getentarray( "oil_spill", "targetname" );
|
|
if ( oilspill.size )
|
|
{
|
|
level.breakables_fx[ "oilspill" ][ "burn" ] = loadfx( "props/barrel_fire" );
|
|
level.breakables_fx[ "oilspill" ][ "spark" ] = loadfx( "impacts/small_metalhit_1" );
|
|
}
|
|
|
|
tincans = getentarray( "tincan", "targetname" );
|
|
if ( tincans.size )
|
|
level.breakables_fx[ "tincan" ] = loadfx( "props/tincan_bounce" );
|
|
|
|
qBreakables = false;
|
|
breakables = getentarray( "breakable", "targetname" );
|
|
if ( breakables.size )
|
|
qBreakables = true;
|
|
|
|
breakables = getentarray( "breakable_vase", "targetname" );
|
|
if ( breakables.size )
|
|
qBreakables = true;
|
|
|
|
breakables = getentarray( "breakable box", "targetname" );
|
|
if ( barrels.size )
|
|
qBreakables = true;
|
|
|
|
breakables = getentarray( "breakable box", "script_noteworthy" );
|
|
if ( barrels.size )
|
|
qBreakables = true;
|
|
|
|
if ( qBreakables )
|
|
{
|
|
level.breakables_fx[ "vase" ] = loadfx( "props/vase_water" );
|
|
level.breakables_fx[ "bottle" ] = loadfx( "props/wine_bottle" );
|
|
level.breakables_fx[ "box" ][ 0 ] = loadfx( "props/crateExp_dust" );
|
|
level.breakables_fx[ "box" ][ 1 ] = loadfx( "props/crateExp_dust" );
|
|
level.breakables_fx[ "box" ][ 2 ] = loadfx( "props/crateExp_dust" );
|
|
level.breakables_fx[ "box" ][ 3 ] = loadfx( "props/crateExp_ammo" );
|
|
}
|
|
|
|
glassarray = getentarray( "glass", "targetname" );
|
|
glassarray = array_combine( glassarray, getentarray( "glass", "script_noteworthy" ) );
|
|
if ( glassarray.size )
|
|
{
|
|
level._glass_info = [];
|
|
|
|
level._glass_info[ "glass_large" ][ "breakfx" ] = loadfx( "props/car_glass_large" );
|
|
level._glass_info[ "glass_large" ][ "breaksnd" ] = "veh_glass_break_large";
|
|
|
|
level._glass_info[ "glass_med" ][ "breakfx" ] = loadfx( "props/car_glass_med" );
|
|
level._glass_info[ "glass_med" ][ "breaksnd" ] = "veh_glass_break_small";
|
|
|
|
level._glass_info[ "glass_small" ][ "breakfx" ] = loadfx( "props/car_glass_headlight" );
|
|
level._glass_info[ "glass_small" ][ "breaksnd" ] = "veh_glass_break_small";
|
|
}
|
|
|
|
tv_array = getentarray( "interactive_tv", "targetname" );
|
|
if ( tv_array.size )
|
|
{
|
|
precachemodel( "com_tv2_d" );
|
|
precachemodel( "com_tv1" );
|
|
precachemodel( "com_tv2" );
|
|
precachemodel( "com_tv1_testpattern" );
|
|
precachemodel( "com_tv2_testpattern" );
|
|
|
|
level.breakables_fx[ "tv_explode" ] = loadfx( "explosions/tv_explosion" );
|
|
}
|
|
level.tv_lite_array = getentarray( "interactive_tv_light", "targetname" );
|
|
|
|
security_camera_array = getentarray( "destroyable_security_camera", "script_noteworthy" );
|
|
if ( security_camera_array.size )
|
|
{
|
|
precachemodel( "com_security_camera" );
|
|
precachemodel( "com_security_camera_destroyed" );
|
|
|
|
level.breakables_fx[ "security_camera_explode" ] = loadfx( "props/securitycamera_explosion" );
|
|
}
|
|
|
|
// -- -- -- -- -- -- -- -- --
|
|
// -- -- -- -- -- -- -- -- --
|
|
|
|
|
|
// -- -- -- -- -- -- -- -- -
|
|
// SOUND DEFINITIONS
|
|
// -- -- -- -- -- -- -- -- -
|
|
level.barrelExpSound = "barrel_mtl_explode";
|
|
// -- -- -- -- -- -- -- -- -
|
|
// -- -- -- -- -- -- -- -- -
|
|
|
|
// -- -- -- -- -- -- -
|
|
// MISC SETTINGS
|
|
// -- -- -- -- -- -- -
|
|
maxBrokenPieces = 25;
|
|
level.breakables_peicesCollide[ "orange vase" ] = true;
|
|
level.breakables_peicesCollide[ "green vase" ] = true;
|
|
level.breakables_peicesCollide[ "bottle" ] = true;
|
|
//* * * * * * * * * * * * * IF YOU PUT THIS BACK IN - SEARCH FOR "PLATE WAIT" AND PUT THAT BACK IN TOO * * * * * * * * * * * * *
|
|
// level.breakables_peicesCollide[ "plate" ] = true;
|
|
//* * * * * * * * * * * * * IF YOU PUT THIS BACK IN - SEARCH FOR "PLATE WAIT" AND PUT THAT BACK IN TOO * * * * * * * * * * * * *
|
|
|
|
|
|
level.barrelHealth = 150;
|
|
// -- -- -- -- -- -- -
|
|
// -- -- -- -- -- -- -
|
|
|
|
level.precachemodeltype = [];
|
|
level.barrelExplodingThisFrame = false;
|
|
level.breakables_clip = [];
|
|
level.breakables_clip = getentarray( "vase_break_remove", "targetname" );
|
|
level.console_auto_aim = [];
|
|
|
|
|
|
level.console_auto_aim = getentarray( "xenon_auto_aim", "targetname" );
|
|
level.console_auto_aim_2nd = getentarray( "xenon_auto_aim_secondary", "targetname" );
|
|
|
|
for ( i = 0;i < level.console_auto_aim.size;i++ )
|
|
level.console_auto_aim[ i ] notsolid();
|
|
|
|
for ( i = 0;i < level.console_auto_aim_2nd.size;i++ )
|
|
level.console_auto_aim_2nd[ i ] notsolid();
|
|
|
|
maps\_utility::set_console_status();
|
|
if ( level.console )
|
|
{
|
|
level.console_auto_aim = undefined;
|
|
level.console_auto_aim_2nd = undefined;
|
|
}
|
|
|
|
temp = getentarray( "breakable clip", "targetname" );
|
|
for ( i = 0;i < temp.size;i++ )
|
|
level.breakables_clip[ level.breakables_clip.size ] = temp[ i ];
|
|
|
|
level._breakable_utility_modelarray = [];
|
|
level._breakable_utility_modelindex = 0;
|
|
level._breakable_utility_maxnum = maxBrokenPieces;
|
|
|
|
array_thread( getentarray( "tincan", "targetname" ), ::tincan_think );
|
|
array_thread( getentarray( "helmet_pop", "targetname" ), ::helmet_pop );
|
|
array_thread( getentarray( "explodable_barrel", "targetname" ), ::explodable_barrel_think );
|
|
array_thread( getentarray( "explodable_barrel", "script_noteworthy" ), ::explodable_barrel_think );
|
|
array_thread( getentarray( "shuddering_entity", "targetname" ), ::shuddering_entity_think );
|
|
array_thread( getentarray( "breakable box", "targetname" ), ::breakable_think );
|
|
array_thread( getentarray( "breakable box", "script_noteworthy" ), ::breakable_think );
|
|
array_thread( getentarray( "breakable", "targetname" ), ::breakable_think );
|
|
array_thread( getentarray( "breakable_vase", "targetname" ), ::breakable_think );
|
|
array_thread( getentarray( "oil_spill", "targetname" ), ::oil_spill_think );
|
|
array_thread( getentarray( "glass", "targetname" ), ::glass_logic );
|
|
array_thread( getentarray( "interactive_tv", "targetname" ), ::tv_logic );
|
|
array_thread( getentarray( "destroyable_security_camera", "script_noteworthy" ), ::security_camera_logic );
|
|
}
|
|
|
|
security_camera_logic()
|
|
{
|
|
self setcandamage( true );
|
|
damagemodel = undefined;
|
|
|
|
switch( self.model )
|
|
{
|
|
case "com_security_camera":
|
|
damagemodel = "com_security_camera_destroyed";
|
|
break;
|
|
}
|
|
|
|
self waittill( "damage", damage, other, direction_vec, P, type );
|
|
|
|
self setmodel( damagemodel );
|
|
|
|
// nice to play a sound here to acompany the effect
|
|
|
|
playfxontag( level.breakables_fx[ "security_camera_explode" ], self, "tag_deathfx" );
|
|
|
|
}
|
|
|
|
tv_logic()
|
|
{
|
|
self setcandamage( true );
|
|
self.damagemodel = undefined;
|
|
self.offmodel = undefined;
|
|
|
|
self.damagemodel = "com_tv2_d";
|
|
self.offmodel = "com_tv2";
|
|
self.onmodel = "com_tv2_testpattern";
|
|
if ( issubstr( self.model, "1" ) )
|
|
{
|
|
self.offmodel = "com_tv1";
|
|
self.onmodel = "com_tv1_testpattern";
|
|
}
|
|
|
|
if ( isdefined( self.target ) )
|
|
{
|
|
if ( isdefined( level.disable_interactive_tv_use_triggers ) )
|
|
{
|
|
usetrig = getent( self.target, "targetname" );
|
|
if ( isdefined( usetrig ) )
|
|
usetrig delete();
|
|
}
|
|
else
|
|
{
|
|
self.usetrig = getent( self.target, "targetname" );
|
|
self.usetrig usetriggerrequirelookat();
|
|
self.usetrig setcursorhint( "HINT_NOICON" );
|
|
}
|
|
}
|
|
|
|
array = get_array_of_closest( self.origin, level.tv_lite_array, undefined, undefined, 64 );
|
|
|
|
if ( array.size )
|
|
{
|
|
self.lite = array[ 0 ];
|
|
level.tv_lite_array = array_remove( level.tv_lite_array, self.lite );
|
|
self.liteintensity = self.lite getLightIntensity();
|
|
}
|
|
|
|
self thread tv_damage();
|
|
|
|
if ( isdefined( self.usetrig ) )
|
|
self thread tv_off();
|
|
}
|
|
|
|
tv_off()
|
|
{
|
|
self.usetrig endon( "death" );
|
|
|
|
while ( 1 )
|
|
{
|
|
wait .2;
|
|
self.usetrig waittill( "trigger" );
|
|
// it would be nice to play a sound here
|
|
|
|
self notify( "off" );
|
|
|
|
if ( self.model == self.offmodel )
|
|
{
|
|
self setmodel( self.onmodel );
|
|
if ( isdefined( self.lite ) )
|
|
self.lite setLightIntensity( self.liteintensity );
|
|
}
|
|
else
|
|
{
|
|
self setmodel( self.offmodel );
|
|
if ( isdefined( self.lite ) )
|
|
self.lite setLightIntensity( 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
tv_damage()
|
|
{
|
|
for ( ;; )
|
|
{
|
|
self waittill( "damage", damage, other, direction_vec, P, type );
|
|
|
|
if ( flag( "no_ai_tv_damage" ) )
|
|
{
|
|
if ( !isalive( other ) )
|
|
continue;
|
|
|
|
if ( !isplayer( other ) )
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if ( isdefined( level.tvhook ) )
|
|
[[ level.tvhook ]]();
|
|
|
|
self notify( "off" );
|
|
if ( isdefined( self.usetrig ) )
|
|
self.usetrig notify( "death" );
|
|
|
|
|
|
self setmodel( self.damagemodel );
|
|
|
|
if ( isdefined( self.lite ) )
|
|
self.lite setLightIntensity( 0 );
|
|
|
|
playfxontag( level.breakables_fx[ "tv_explode" ], self, "tag_fx" );
|
|
self playsound( "tv_shot_burst" );
|
|
|
|
if ( isdefined( self.usetrig ) )
|
|
self.usetrig delete();
|
|
}
|
|
|
|
glass_logic()
|
|
{
|
|
direction_vec = undefined;
|
|
crackedContents = undefined;
|
|
cracked = undefined;
|
|
glasshealth = 0;
|
|
|
|
// setup
|
|
if ( isdefined( self.target ) )
|
|
{
|
|
cracked = getent( self.target, "targetname" );
|
|
assertex( isdefined( cracked ), "Destructible glass at origin( " + self.origin + " ) has a target but the cracked version doesn't exist" );
|
|
}
|
|
|
|
if ( isdefined( self.script_linkTo ) )
|
|
{
|
|
links = self get_links();
|
|
assert( isdefined( links ) );
|
|
object = getent( links[ 0 ], "script_linkname" );
|
|
self linkto( object );
|
|
}
|
|
|
|
assertex( isdefined( self.destructible_type ), "Destructible glass at origin( " + self.origin + " ) doesnt have a destructible_type" );
|
|
switch( self.destructible_type )
|
|
{
|
|
case "glass_large":
|
|
|
|
break;
|
|
case "glass_med":
|
|
|
|
break;
|
|
case "glass_small":
|
|
|
|
break;
|
|
default:
|
|
assertMsg( "Destructible glass 'destructible_type' key / value of '" + self.destructible_type + "' is not valid" );
|
|
break;
|
|
}
|
|
|
|
if ( isdefined( cracked ) )
|
|
{
|
|
glasshealth = 99;
|
|
cracked linkto( self );
|
|
cracked hide();
|
|
// Set the contents to 0 to make it non - solid.
|
|
// Note "notSolid()" won't work since it forgets the contents.
|
|
crackedContents = cracked setContents( 0 );
|
|
}
|
|
|
|
if ( isdefined( self.script_health ) )
|
|
glasshealth = self.script_health;
|
|
else if ( isdefined( cracked ) )
|
|
glasshealth = 99;
|
|
else
|
|
glasshealth = 250;
|
|
|
|
// break
|
|
self setcandamage( true );
|
|
while ( glasshealth > 0 )
|
|
{
|
|
self waittill( "damage", damage, attacker, direction_vec, point, damageType );
|
|
|
|
if ( !isdefined( direction_vec ) )
|
|
direction_vec = ( 0, 0, 1 );
|
|
if ( !isdefined( damageType ) )
|
|
damage = 100000;// scripted calls to break the glass
|
|
else if ( damageType == "MOD_GRENADE_SPLASH" )
|
|
damage = damage * 1.75;
|
|
else if ( damageType == "MOD_IMPACT" )
|
|
damage = 100000;
|
|
|
|
glasshealth -= damage;
|
|
}
|
|
|
|
prevdamage = glasshealth * - 1;
|
|
|
|
self hide();
|
|
self notsolid();
|
|
|
|
if ( isdefined( cracked ) )
|
|
{
|
|
cracked show();
|
|
cracked setcandamage( true );
|
|
|
|
glasshealth = ( 200 ) - prevdamage;
|
|
|
|
// Set the contents back so that it's solid
|
|
cracked setContents( crackedContents );
|
|
|
|
while ( glasshealth > 0 )
|
|
{
|
|
cracked waittill( "damage", damage, other, direction_vec, point, damageType );
|
|
|
|
if ( !isdefined( direction_vec ) )
|
|
direction_vec = ( 0, 0, 1 );
|
|
if ( !isdefined( damageType ) )
|
|
damage = 100000;// scripted calls to break the glass
|
|
else if ( damageType == "MOD_GRENADE_SPLASH" )
|
|
damage = damage * 1.75;
|
|
else if ( damageType == "MOD_IMPACT" )
|
|
break;
|
|
|
|
glasshealth -= damage;
|
|
}
|
|
|
|
cracked delete();
|
|
}
|
|
|
|
glass_play_break_fx( self getorigin(), self.destructible_type, direction_vec );
|
|
|
|
self delete();
|
|
}
|
|
|
|
glass_play_break_fx( origin, info, direction_vec )
|
|
{
|
|
|
|
thread play_sound_in_space( level._glass_info[ info ][ "breaksnd" ], origin );
|
|
playfx( level._glass_info[ info ][ "breakfx" ], origin, direction_vec );
|
|
level notify( "glass_shatter" );
|
|
}
|
|
|
|
oil_spill_think()
|
|
{
|
|
self.end = getstruct( self.target, "targetname" );
|
|
self.start = getstruct( self.end.target, "targetname" );
|
|
self.barrel = getClosestEnt( self.start.origin, getentarray( "explodable_barrel", "targetname" ) );
|
|
|
|
if ( isdefined( self.barrel ) )
|
|
{
|
|
self.barrel.oilspill = true;
|
|
self thread oil_spill_burn_after();
|
|
}
|
|
|
|
self.extra = getent( self.target, "targetname" );
|
|
self setcandamage( true );
|
|
|
|
while ( 1 )
|
|
{
|
|
self waittill( "damage", amount, attacker, direction_vec, P, type );
|
|
if ( type == "MOD_MELEE" || type == "MOD_IMPACT" )
|
|
continue;
|
|
|
|
self.damageOwner = attacker;
|
|
|
|
playfx( level.breakables_fx[ "oilspill" ][ "spark" ], P, direction_vec );
|
|
P = pointOnSegmentNearestToPoint( self.start.origin, self.end.origin, P );
|
|
thread oil_spill_burn_section( P );
|
|
self thread oil_spill_burn( P, self.start.origin );
|
|
self thread oil_spill_burn( P, self.end.origin );
|
|
break;
|
|
}
|
|
if ( isdefined( self.barrel ) )
|
|
self.barrel waittill( "exploding" );
|
|
|
|
self.extra delete();
|
|
self hide();
|
|
|
|
wait 10;
|
|
self delete();
|
|
}
|
|
|
|
oil_spill_burn_after()
|
|
{
|
|
while ( 1 )
|
|
{
|
|
self.barrel waittill( "damage", amount, attacker, direction_vec, P, type );
|
|
if ( type == "MOD_MELEE" || type == "MOD_IMPACT" )
|
|
continue;
|
|
self.damageOwner = attacker;
|
|
break;
|
|
}
|
|
self radiusdamage( self.start.origin, 4, 10, 10, self.damageOwner );
|
|
}
|
|
|
|
|
|
OIL_SPILL_COUNT = 4;
|
|
OIL_SPILL_WAIT_TIME = 0.1;
|
|
OIL_SPILL_BAD_PLACE_DURATION = 0.5;
|
|
|
|
oil_spill_burn( P, dest )
|
|
{
|
|
forward = vectornormalize( dest - P );
|
|
dist = distance( p, dest );
|
|
range = 8;
|
|
interval = vector_multiply( forward, range );
|
|
angle = vectortoangles( forward );
|
|
right = anglestoright( angle );
|
|
|
|
barrels = getentarray( "explodable_barrel", "targetname" );
|
|
distsqr = 22 * 22;
|
|
|
|
test = spawn( "script_origin", P );
|
|
|
|
assert( OIL_SPILL_BAD_PLACE_DURATION > OIL_SPILL_COUNT * OIL_SPILL_WAIT_TIME );
|
|
|
|
num = 0;
|
|
while ( 1 )
|
|
{
|
|
dist -= range;
|
|
if ( dist < range * .1 )
|
|
break;
|
|
|
|
p += ( interval + vector_multiply( right, randomfloatrange( -6, 6 ) ) );
|
|
|
|
thread oil_spill_burn_section( P );
|
|
num++ ;
|
|
if ( num == OIL_SPILL_COUNT )
|
|
{
|
|
badplace_cylinder( "", OIL_SPILL_BAD_PLACE_DURATION, P, 64, 64 );
|
|
num = 0;
|
|
}
|
|
|
|
test.origin = P;
|
|
|
|
remove = [];
|
|
barrels = array_removeUndefined( barrels );
|
|
for ( i = 0; i < barrels.size; i++ )
|
|
{
|
|
vec = anglestoup( barrels[ i ].angles );
|
|
start = barrels[ i ].origin + ( vector_multiply( vec, 22 ) );
|
|
pos = physicstrace( start, start + ( 0, 0, -64 ) );
|
|
|
|
if ( distancesquared( P, pos ) < distsqr )
|
|
{
|
|
remove[ remove.size ] = barrels[ i ];
|
|
barrels[ i ] dodamage( ( 80 + randomfloat( 10 ) ), P );
|
|
}
|
|
}
|
|
for ( i = 0; i < remove.size; i++ )
|
|
barrels = array_remove( barrels, remove[ i ] );
|
|
wait OIL_SPILL_WAIT_TIME;
|
|
}
|
|
|
|
if ( !isdefined( self.barrel ) )
|
|
return;
|
|
if ( distance( P, self.start.origin ) < 32 )
|
|
self.barrel dodamage( ( 80 + randomfloat( 10 ) ), P );
|
|
}
|
|
|
|
oil_spill_burn_section( P )
|
|
{
|
|
count = 0;
|
|
time = 0;
|
|
playfx( level.breakables_fx[ "oilspill" ][ "burn" ], P );
|
|
/*
|
|
while ( time < 5 )
|
|
{
|
|
attacker = undefined;
|
|
if ( isdefined( self.damageOwner ) )
|
|
attacker = self.damageOwner;
|
|
|
|
self radiusdamage( P, 32, 5, 1, attacker );
|
|
time += 1;
|
|
wait 1;
|
|
}*/
|
|
}
|
|
|
|
explodable_barrel_think()
|
|
{
|
|
if ( self.classname != "script_model" )
|
|
return;
|
|
// if ( ( self.model != "com_barrel_benzin" ) && ( self.model != "com_barrel_benzin_snow" ) )
|
|
// return;
|
|
if ( !isdefined( level.precachemodeltype[ "com_barrel_benzin" ] ) )
|
|
{
|
|
level.precachemodeltype[ "com_barrel_benzin" ] = true;
|
|
precacheModel( "com_barrel_piece" );
|
|
precacheModel( "com_barrel_piece2" );
|
|
}
|
|
self endon( "exploding" );
|
|
|
|
self breakable_clip();
|
|
self xenon_auto_aim();
|
|
self.damageTaken = 0;
|
|
self setcandamage( true );
|
|
for ( ;; )
|
|
{
|
|
self waittill( "damage", amount, attacker, direction_vec, P, type );
|
|
if ( type == "MOD_MELEE" || type == "MOD_IMPACT" )
|
|
continue;
|
|
|
|
self.damageOwner = attacker;
|
|
|
|
if ( level.barrelExplodingThisFrame )
|
|
wait randomfloat( 1 );
|
|
self.damageTaken += amount;
|
|
if ( self.damageTaken == amount )
|
|
self thread explodable_barrel_burn();
|
|
}
|
|
}
|
|
|
|
MAX_COUNT = 19;
|
|
WAIT_TIME = 0.05;
|
|
BAD_PLACE_DURATION = 1;
|
|
|
|
explodable_barrel_burn()
|
|
{
|
|
count = 0;
|
|
startedfx = false;
|
|
|
|
up = anglestoup( self.angles );
|
|
worldup = anglestoup( ( 0, 90, 0 ) );
|
|
dot = vectordot( up, worldup );
|
|
|
|
offset1 = ( 0, 0, 0 );
|
|
offset2 = vector_multiply( up, 44 );
|
|
|
|
// if this isn't true, bad place will turn on and off on the barrel
|
|
assert( BAD_PLACE_DURATION > MAX_COUNT * WAIT_TIME );
|
|
|
|
if ( dot < .5 )
|
|
{
|
|
offset1 = vector_multiply( up, 22 ) - ( 0, 0, 30 );
|
|
offset2 = vector_multiply( up, 22 ) + ( 0, 0, 14 );
|
|
}
|
|
while ( self.damageTaken < level.barrelHealth )
|
|
{
|
|
if ( !startedfx )
|
|
{
|
|
playfx( level.breakables_fx[ "barrel" ][ "burn_start" ], self.origin + offset1 );
|
|
startedfx = true;
|
|
}
|
|
if ( count > MAX_COUNT )
|
|
count = 0;
|
|
|
|
playfx( level.breakables_fx[ "barrel" ][ "burn" ], self.origin + offset2 );
|
|
|
|
if ( count == 0 )
|
|
{
|
|
self.damageTaken += ( 10 + randomfloat( 10 ) );
|
|
badplace_cylinder( "", BAD_PLACE_DURATION, self.origin, 128, 250 );
|
|
}
|
|
count++;
|
|
wait WAIT_TIME;
|
|
|
|
if( !isdefined( self ) )
|
|
return; // support deleting explodable barrels.
|
|
}
|
|
self thread explodable_barrel_explode();
|
|
}
|
|
|
|
explodable_barrel_explode()
|
|
{
|
|
self notify( "exploding" );
|
|
self notify( "death" );
|
|
|
|
up = anglestoup( self.angles );
|
|
worldup = anglestoup( ( 0, 90, 0 ) );
|
|
dot = vectordot( up, worldup );
|
|
|
|
offset = ( 0, 0, 0 );
|
|
if ( dot < .5 )
|
|
{
|
|
start = ( self.origin + vector_multiply( up, 22 ) );
|
|
end = physicstrace( start, ( start + ( 0, 0, -64 ) ) );
|
|
offset = end - self.origin;
|
|
}
|
|
offset += ( 0, 0, 4 );
|
|
|
|
level thread play_sound_in_space( level.barrelExpSound, self.origin );
|
|
playfx( level.breakables_fx[ "barrel" ][ "explode" ], self.origin + offset );
|
|
physicsexplosionsphere( self.origin + offset, 100, 80, 1 );
|
|
|
|
level.barrelExplodingThisFrame = true;
|
|
|
|
if ( isdefined( self.remove ) )
|
|
{
|
|
self.remove connectpaths();
|
|
self.remove delete();
|
|
}
|
|
|
|
minDamage = 1;
|
|
maxDamage = 250;
|
|
blastRadius = 250;
|
|
if ( isdefined( self.radius ) )
|
|
blastRadius = self.radius;
|
|
// radiusDamage( self.origin + ( 0, 0, 56 ), blastRadius, maxDamage, minDamage );
|
|
|
|
attacker = undefined;
|
|
|
|
if ( isdefined( self.damageOwner ) )
|
|
{
|
|
attacker = self.damageOwner;
|
|
if ( isplayer( attacker ) )
|
|
arcadeMode_kill( self.origin, "rifle", 150 );
|
|
}
|
|
|
|
level.lastExplodingBarrel[ "time" ] = getTime();
|
|
level.lastExplodingBarrel[ "origin" ] = self.origin + ( 0, 0, 30 );
|
|
level.lastExplodingBarrel[ "radius" ] = blastRadius;
|
|
self radiusDamage( self.origin + ( 0, 0, 30 ), blastRadius, maxDamage, minDamage, attacker );
|
|
|
|
if ( randomint( 2 ) == 0 )
|
|
self setModel( "com_barrel_piece" );
|
|
else
|
|
self setModel( "com_barrel_piece2" );
|
|
|
|
|
|
if ( dot < .5 )
|
|
{
|
|
start = ( self.origin + vector_multiply( up, 22 ) );
|
|
pos = physicstrace( start, ( start + ( 0, 0, -64 ) ) );
|
|
|
|
self.origin = pos;
|
|
self.angles += ( 0, 0, 90 );
|
|
|
|
}
|
|
wait 0.05;
|
|
level.barrelExplodingThisFrame = false;
|
|
}
|
|
|
|
shuddering_entity_think()
|
|
{
|
|
assert( self.classname == "script_model" );
|
|
helmet = false;
|
|
if ( self.model == "prop_helmet_german_normandy" )
|
|
helmet = true;
|
|
self setcandamage( true );
|
|
for ( ;; )
|
|
{
|
|
self waittill( "damage", other, damage, direction_vec, point );
|
|
if ( helmet )
|
|
self vibrate( direction_vec, 20, 0.6, 0.75 );
|
|
else
|
|
self vibrate( direction_vec, 0.4, 0.4, 0.4 );
|
|
self waittill( "rotatedone" );
|
|
}
|
|
}
|
|
|
|
tincan_think()
|
|
{
|
|
if ( self.classname != "script_model" )
|
|
return;
|
|
|
|
self setcandamage( true );
|
|
self waittill( "damage", damage, ent );
|
|
|
|
if ( isAI( ent ) || isPlayer( ent ) )
|
|
direction_org = ( ( ent getEye() ) - ( 0, 0, ( randomint( 50 ) + 50 ) ) );
|
|
else
|
|
direction_org = ent.origin;
|
|
|
|
direction_vec = vectornormalize( self.origin - direction_org );
|
|
direction_vec = vector_multiply( direction_vec, .5 + randomfloat( 1 ) );
|
|
|
|
self notify( "death" );
|
|
playfx( level.breakables_fx[ "tincan" ], self.origin, direction_vec );
|
|
self delete();
|
|
}
|
|
|
|
helmet_pop()
|
|
{
|
|
if ( self.classname != "script_model" )
|
|
return;
|
|
self xenon_auto_aim();
|
|
|
|
self setcandamage( true );
|
|
self thread helmet_logic();
|
|
}
|
|
|
|
helmet_logic()
|
|
{
|
|
self waittill( "damage", damage, ent );
|
|
|
|
if ( isAI( ent ) )
|
|
direction_org = ent getEye();
|
|
else
|
|
direction_org = ent.origin;
|
|
|
|
direction_vec = vectornormalize( self.origin - direction_org );
|
|
|
|
if ( !isdefined( self.dontremove ) && isplayer( ent ) )
|
|
{
|
|
self thread animscripts\death::helmetLaunch( direction_vec );
|
|
return;
|
|
}
|
|
|
|
self notsolid();
|
|
self hide();
|
|
model = spawn( "script_model", self.origin + ( 0, 0, 5 ) );
|
|
model.angles = self.angles;
|
|
model setmodel( self.model );
|
|
model thread animscripts\death::helmetLaunch( direction_vec );
|
|
|
|
self.dontremove = false;
|
|
self notify( "ok_remove" );
|
|
}
|
|
|
|
allowBreak( ent )
|
|
{
|
|
if ( !isdefined( level.breakingEnts ) )
|
|
return true;
|
|
|
|
if ( level.breakingEnts.size == 0 )
|
|
return false;
|
|
else
|
|
{
|
|
for ( i = 0;i < level.breakingEnts.size;i++ )
|
|
{
|
|
if ( ent == level.breakingEnts[ i ] )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
breakable_think_triggered( eBreakable )
|
|
{
|
|
for ( ;; )
|
|
{
|
|
self waittill( "trigger", other );
|
|
eBreakable notify( "damage", 100, other );
|
|
}
|
|
}
|
|
|
|
breakable_think()
|
|
{
|
|
if ( self.classname != "script_model" )
|
|
return;
|
|
if ( !isdefined( self.model ) )
|
|
return;
|
|
|
|
type = undefined;
|
|
|
|
if ( self.model == "egypt_prop_vase1" || self.model == "egypt_prop_vase3" || self.model == "egypt_prop_vase4" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "egypt_prop_vase_o" ] ) )
|
|
{
|
|
level.precachemodeltype[ "egypt_prop_vase_o" ] = true;
|
|
precacheModel( "egypt_prop_vase_br2" );
|
|
precacheModel( "egypt_prop_vase_br5" );
|
|
precacheModel( "egypt_prop_vase_br7" );
|
|
}
|
|
type = "orange vase";
|
|
self breakable_clip();
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "egypt_prop_vase2" || self.model == "egypt_prop_vase5" || self.model == "egypt_prop_vase6" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "egypt_prop_vase_g" ] ) )
|
|
{
|
|
level.precachemodeltype[ "egypt_prop_vase_g" ] = true;
|
|
precacheModel( "egypt_prop_vase_br1" );
|
|
precacheModel( "egypt_prop_vase_br3" );
|
|
precacheModel( "egypt_prop_vase_br4" );
|
|
precacheModel( "egypt_prop_vase_br6" );
|
|
}
|
|
type = "green vase";
|
|
self breakable_clip();
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_crate_dak1" || self.model == "prop_crate_dak2" || self.model == "prop_crate_dak3" || self.model == "prop_crate_dak4" || self.model == "prop_crate_dak5" || self.model == "prop_crate_dak6" || self.model == "prop_crate_dak7" || self.model == "prop_crate_dak8" || self.model == "prop_crate_dak9" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_crate_dak_shard" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_crate_dak_shard" ] = true;
|
|
precacheModel( "prop_crate_dak_shard" );
|
|
}
|
|
type = "wood box";
|
|
self breakable_clip();
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_winebottle_breakable" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_winebottle" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_winebottle" ] = true;
|
|
precacheModel( "prop_winebottle_broken_top" );
|
|
precacheModel( "prop_winebottle_broken_bot" );
|
|
}
|
|
type = "bottle";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_roundfloral" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenfloral" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenfloral" ] = true;
|
|
precacheModel( "prop_diningplate_brokenfloral1" );
|
|
precacheModel( "prop_diningplate_brokenfloral2" );
|
|
precacheModel( "prop_diningplate_brokenfloral3" );
|
|
precacheModel( "prop_diningplate_brokenfloral4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "round_floral";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_roundplain" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenplain" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenplain" ] = true;
|
|
precacheModel( "prop_diningplate_brokenplain1" );
|
|
precacheModel( "prop_diningplate_brokenplain2" );
|
|
precacheModel( "prop_diningplate_brokenplain3" );
|
|
precacheModel( "prop_diningplate_brokenplain4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "round_plain";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_roundstack" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenplain" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenplain" ] = true;
|
|
precacheModel( "prop_diningplate_brokenplain1" );
|
|
precacheModel( "prop_diningplate_brokenplain2" );
|
|
precacheModel( "prop_diningplate_brokenplain3" );
|
|
precacheModel( "prop_diningplate_brokenplain4" );
|
|
}
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenfloral" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenfloral" ] = true;
|
|
precacheModel( "prop_diningplate_brokenfloral1" );
|
|
precacheModel( "prop_diningplate_brokenfloral2" );
|
|
precacheModel( "prop_diningplate_brokenfloral3" );
|
|
precacheModel( "prop_diningplate_brokenfloral4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "round_stack";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_ovalfloral" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenfloral" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenfloral" ] = true;
|
|
precacheModel( "prop_diningplate_brokenfloral1" );
|
|
precacheModel( "prop_diningplate_brokenfloral2" );
|
|
precacheModel( "prop_diningplate_brokenfloral3" );
|
|
precacheModel( "prop_diningplate_brokenfloral4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "oval_floral";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_ovalplain" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenplain" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenplain" ] = true;
|
|
precacheModel( "prop_diningplate_brokenplain1" );
|
|
precacheModel( "prop_diningplate_brokenplain2" );
|
|
precacheModel( "prop_diningplate_brokenplain3" );
|
|
precacheModel( "prop_diningplate_brokenplain4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "oval_plain";
|
|
self xenon_auto_aim();
|
|
}
|
|
else if ( self.model == "prop_diningplate_ovalstack" )
|
|
{
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenplain" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenplain" ] = true;
|
|
precacheModel( "prop_diningplate_brokenplain1" );
|
|
precacheModel( "prop_diningplate_brokenplain2" );
|
|
precacheModel( "prop_diningplate_brokenplain3" );
|
|
precacheModel( "prop_diningplate_brokenplain4" );
|
|
}
|
|
if ( !isdefined( level.precachemodeltype[ "prop_diningplate_brokenfloral" ] ) )
|
|
{
|
|
level.precachemodeltype[ "prop_diningplate_brokenfloral" ] = true;
|
|
precacheModel( "prop_diningplate_brokenfloral1" );
|
|
precacheModel( "prop_diningplate_brokenfloral2" );
|
|
precacheModel( "prop_diningplate_brokenfloral3" );
|
|
precacheModel( "prop_diningplate_brokenfloral4" );
|
|
}
|
|
type = "plate";
|
|
self.plate = "oval_stack";
|
|
self xenon_auto_aim();
|
|
}
|
|
if ( !isdefined( type ) )
|
|
{
|
|
println( "Entity ", self.targetname, " at ", self.origin, " is not a valid breakable object." );
|
|
return;
|
|
}
|
|
|
|
if ( isdefined( self.target ) )
|
|
{
|
|
trig = getent( self.target, "targetname" );
|
|
if ( ( isdefined( trig ) ) && ( trig.classname == "trigger_multiple" ) )
|
|
trig thread breakable_think_triggered( self );
|
|
}
|
|
|
|
self setcandamage( true );
|
|
self thread breakable_logic( type );
|
|
}
|
|
|
|
breakable_logic( type )
|
|
{
|
|
ent = undefined;
|
|
for ( ;; )
|
|
{
|
|
self waittill( "damage", amount, ent );
|
|
if ( isdefined( ent ) && ent.code_classname == "script_vehicle" )
|
|
ent joltbody( self.origin + ( 0, 0, -90 ), .2 );
|
|
if ( type == "wood box" )
|
|
{
|
|
if ( !allowBreak( ent ) )
|
|
continue;
|
|
if ( ( !isdefined( level.flags ) ) || ( !isdefined( level.flags[ "Breakable Boxes" ] ) ) )
|
|
break;
|
|
if ( ( isdefined( level.flags[ "Breakable Boxes" ] ) ) && ( level.flags[ "Breakable Boxes" ] == true ) )
|
|
break;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
self notify( "death" );
|
|
|
|
soundAlias = undefined;
|
|
fx = undefined;
|
|
hasDependant = false;
|
|
switch( type )
|
|
{
|
|
case "orange vase":
|
|
case "green vase":
|
|
soundAlias = "bullet_large_vase";
|
|
fx = level.breakables_fx[ "vase" ];
|
|
break;
|
|
case "wood box":
|
|
if ( isdefined( level.crateImpactSound ) )
|
|
soundAlias = level.crateImpactSound;
|
|
else
|
|
soundAlias = "bullet_large_vase";
|
|
fx = level.breakables_fx[ "box" ][ randomint( level.breakables_fx[ "box" ].size ) ];
|
|
hasDependant = true;
|
|
break;
|
|
case "bottle":
|
|
soundAlias = "bullet_small_bottle";
|
|
fx = level.breakables_fx[ "bottle" ];
|
|
break;
|
|
case "plate":
|
|
soundAlias = "bullet_small_plate";
|
|
break;
|
|
}
|
|
thread play_sound_in_space( soundAlias, self.origin );
|
|
self thread make_broken_peices( self, type );
|
|
if ( isdefined( fx ) )
|
|
playfx( fx, self.origin );
|
|
|
|
// certain types should destroy objects sitting on top of them
|
|
if ( hasDependant )
|
|
{
|
|
others = getentarray( "breakable", "targetname" );
|
|
for ( i = 0;i < others.size;i++ )
|
|
{
|
|
other = others[ i ];
|
|
// see if it's within 40 units from this box on X or Y
|
|
diffX = abs( self.origin[ 0 ] - other.origin[ 0 ] );
|
|
diffY = abs( self.origin[ 1 ] - other.origin[ 1 ] );
|
|
|
|
if ( ( diffX <= 20 ) && ( diffY <= 20 ) )
|
|
{
|
|
// see if it's above the box( would probably be resting on it )
|
|
diffZ = ( self.origin[ 2 ] - other.origin[ 2 ] );
|
|
if ( diffZ <= 0 )
|
|
other notify( "damage", amount, ent );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isdefined( self.remove ) )
|
|
{
|
|
self.remove connectpaths();
|
|
self.remove delete();
|
|
}
|
|
|
|
if ( !isdefined( self.dontremove ) )
|
|
self delete();
|
|
|
|
else
|
|
self.dontremove = false;
|
|
self notify( "ok_remove" );
|
|
}
|
|
|
|
xenon_auto_aim()
|
|
{
|
|
if ( ( isdefined( level.console_auto_aim ) ) && ( level.console_auto_aim.size > 0 ) )
|
|
self.autoaim = getClosestAccurantEnt( self.origin, level.console_auto_aim );
|
|
|
|
if ( isdefined( self.autoaim ) )
|
|
{
|
|
level.console_auto_aim = array_remove( level.console_auto_aim, self.autoaim );
|
|
self thread xenon_remove_auto_aim();
|
|
}
|
|
}
|
|
|
|
xenon_auto_aim_stop_logic()
|
|
{
|
|
self notify( "entered_xenon_auto_aim_stop_logic" );
|
|
self endon( "entered_xenon_auto_aim_stop_logic" );
|
|
|
|
self.autoaim waittill( "xenon_auto_aim_stop_logic" );
|
|
self.dontremove = undefined;
|
|
}
|
|
|
|
xenon_remove_auto_aim( wait_message )
|
|
{
|
|
self thread xenon_auto_aim_stop_logic();
|
|
self endon( "xenon_auto_aim_stop_logic" );
|
|
self.autoaim endon( "xenon_auto_aim_stop_logic" );
|
|
|
|
self notify( "xenon_remove_auto_aim" );
|
|
self.autoaim thread xenon_enable_auto_aim( wait_message );
|
|
self.dontremove = true;
|
|
self waittill( "damage", amount, ent );
|
|
|
|
|
|
self.autoaim disableAimAssist();
|
|
|
|
self.autoaim delete();
|
|
if ( self.dontremove )
|
|
self waittill( "ok_remove" );
|
|
self delete();
|
|
|
|
}
|
|
|
|
xenon_enable_auto_aim( wait_message )
|
|
{
|
|
self endon( "xenon_auto_aim_stop_logic" );
|
|
self endon( "death" );
|
|
if ( !isdefined( wait_message ) )
|
|
wait_message = true;
|
|
|
|
if ( isdefined( self.script_noteworthy ) && wait_message )
|
|
{
|
|
string = "enable_xenon_autoaim_" + self.script_noteworthy;
|
|
level waittill( string );
|
|
}
|
|
|
|
self.wait_message = false;
|
|
if ( isdefined( self.recreate ) && self.recreate == true )
|
|
self waittill( "recreate" );
|
|
self enableAimAssist();
|
|
}
|
|
|
|
breakable_clip()
|
|
{
|
|
// targeted brushmodels take priority over proximity based breakables - nate
|
|
if ( isdefined( self.target ) )
|
|
{
|
|
targ = getent( self.target, "targetname" );
|
|
if ( targ.classname == "script_brushmodel" )
|
|
{
|
|
self.remove = targ;
|
|
return;
|
|
}
|
|
}
|
|
// setup it's removable clip part
|
|
if ( ( isdefined( level.breakables_clip ) ) && ( level.breakables_clip.size > 0 ) )
|
|
self.remove = getClosestEnt( self.origin, level.breakables_clip );
|
|
if ( isdefined( self.remove ) )
|
|
level.breakables_clip = array_remove( level.breakables_clip, self.remove );
|
|
}
|
|
|
|
make_broken_peices( wholepiece, type )
|
|
{
|
|
rt = anglesToRight( wholepiece.angles );
|
|
fw = anglesToForward( wholepiece.angles );
|
|
up = anglesToUp( wholepiece.angles );
|
|
|
|
piece = [];
|
|
switch( type )
|
|
{
|
|
case "orange vase":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -7, 0, 22, wholepiece, ( 0, 0, 0 ), "egypt_prop_vase_br2" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 13, -6, 28, wholepiece, ( 0, 245.1, 0 ), "egypt_prop_vase_br7" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 12, 10, 27, wholepiece, ( 0, 180, 0 ), "egypt_prop_vase_br7" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, 2, 0, wholepiece, ( 0, 0, 0 ), "egypt_prop_vase_br5" );
|
|
break;
|
|
case "green vase":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -6, -1, 26, wholepiece, ( 0, 0, 0 ), "egypt_prop_vase_br1" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 12, 1, 31, wholepiece, ( 0, 348.5, 0 ), "egypt_prop_vase_br3" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 6, 13, 29, wholepiece, ( 0, 153.5, 0 ), "egypt_prop_vase_br6" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, 1, 0, wholepiece, ( 0, 0, 0 ), "egypt_prop_vase_br4" );
|
|
break;
|
|
case "wood box":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -10, 10, 25, wholepiece, ( 0, 0, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 10, 10, 25, wholepiece, ( 0, 90, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 10, -10, 25, wholepiece, ( 0, 180, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -10, -10, 25, wholepiece, ( 0, 270, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 10, 10, 5, wholepiece, ( 180, 0, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 10, -10, 5, wholepiece, ( 180, 90, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -10, -10, 5, wholepiece, ( 180, 180, 0 ), "prop_crate_dak_shard" );
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -10, 10, 5, wholepiece, ( 180, 270, 0 ), "prop_crate_dak_shard" );
|
|
break;
|
|
case "bottle":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 0, 0, 10, wholepiece, ( 0, 0, 0 ), "prop_winebottle_broken_top" ); piece[ piece.size - 1 ].type = "bottle_top";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 0, 0, 0, wholepiece, ( 0, 0, 0 ), "prop_winebottle_broken_bot" ); piece[ piece.size - 1 ].type = "bottle_bot";
|
|
break;
|
|
case "plate":
|
|
{
|
|
switch( wholepiece.plate )
|
|
{
|
|
case "round_floral":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -4, .5, wholepiece, ( 0, 150, 0 ), "prop_diningplate_brokenfloral1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, -2, .5, wholepiece, ( 0, 149.8, 0 ), "prop_diningplate_brokenfloral2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 1, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenfloral3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 2, .5, wholepiece, ( 0, 146.8, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
case "round_plain":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -4, .5, wholepiece, ( 0, 150, 0 ), "prop_diningplate_brokenplain1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, -2, .5, wholepiece, ( 0, 149.8, 0 ), "prop_diningplate_brokenplain2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 1, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenplain3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 2, .5, wholepiece, ( 0, 146.8, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
case "round_stack":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -4, .5, wholepiece, ( 0, 150, 0 ), "prop_diningplate_brokenfloral1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, -2, .5, wholepiece, ( 0, 149.8, 0 ), "prop_diningplate_brokenfloral2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 1, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenfloral3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 2, .5, wholepiece, ( 0, 146.8, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 3, 2.5, wholepiece, ( 0, 60, 0 ), "prop_diningplate_brokenplain1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -1, -3, 2.5, wholepiece, ( 0, 59.8, 0 ), "prop_diningplate_brokenplain2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 2, -1, 2.5, wholepiece, ( 0, 60.2, 0 ), "prop_diningplate_brokenplain3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 2, 4, 2.5, wholepiece, ( 0, 56.8, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -4, 4.5, wholepiece, ( 0, 150, 0 ), "prop_diningplate_brokenfloral1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, -2, 4.5, wholepiece, ( 0, 149.8, 0 ), "prop_diningplate_brokenfloral2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 1, 2, 4.5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenfloral3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 2, 4.5, wholepiece, ( 0, 146.8, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
case "oval_floral":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, -4, .5, wholepiece, ( 0, 205.9, 0 ), "prop_diningplate_brokenfloral1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -6, 1, .5, wholepiece, ( 0, 352.2, 0 ), "prop_diningplate_brokenfloral2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenfloral3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -2, 5, .5, wholepiece, ( 0, 102.3, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -3, .5, wholepiece, ( 0, 246.7, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
case "oval_plain":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, -4, .5, wholepiece, ( 0, 205.9, 0 ), "prop_diningplate_brokenplain1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -6, 1, .5, wholepiece, ( 0, 352.2, 0 ), "prop_diningplate_brokenplain2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenplain3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -2, 5, .5, wholepiece, ( 0, 102.3, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -3, .5, wholepiece, ( 0, 246.7, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
case "oval_stack":
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, -4, .5, wholepiece, ( 0, 205.9, 0 ), "prop_diningplate_brokenfloral1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -6, 1, .5, wholepiece, ( 0, 352.2, 0 ), "prop_diningplate_brokenfloral2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 4, 2, .5, wholepiece, ( 0, 150.2, 0 ), "prop_diningplate_brokenfloral3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -2, 5, .5, wholepiece, ( 0, 102.3, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -3, -3, .5, wholepiece, ( 0, 246.7, 0 ), "prop_diningplate_brokenfloral4" ); piece[ piece.size - 1 ].type = "plate";
|
|
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, 5, 2.5, wholepiece, ( 0, 25.9, 0 ), "prop_diningplate_brokenplain1" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 6, 0, 2.5, wholepiece, ( 0, 172.2, 0 ), "prop_diningplate_brokenplain2" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, -4, -1, 2.5, wholepiece, ( 0, 330.2, 0 ), "prop_diningplate_brokenplain3" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 2, -4, 2.5, wholepiece, ( 0, 282.3, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
piece[ piece.size ] = addpiece( rt, fw, up, 3, 4, 2.5, wholepiece, ( 0, 66.7, 0 ), "prop_diningplate_brokenplain4" ); piece[ piece.size - 1 ].type = "plate";
|
|
break;
|
|
}
|
|
}break;
|
|
default:
|
|
return;
|
|
}
|
|
array_thread( piece, ::pieces_move, wholepiece.origin );
|
|
|
|
if ( ( isdefined( level.breakables_peicesCollide[ type ] ) ) && ( level.breakables_peicesCollide[ type ] == true ) )
|
|
{
|
|
height = piece[ 0 ].origin[ 2 ];
|
|
for ( i = 0; i < piece.size; i++ )
|
|
{
|
|
if ( height > piece[ i ].origin[ 2 ] )
|
|
height = piece[ i ].origin[ 2 ];
|
|
}
|
|
array_thread( piece, ::pieces_collision, height );
|
|
}
|
|
else
|
|
{
|
|
wait 2;
|
|
for ( i = 0;i < piece.size;i++ )
|
|
{
|
|
if ( isdefined( piece[ i ] ) )
|
|
piece[ i ] delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
list_add( model )
|
|
{
|
|
if ( isdefined( level._breakable_utility_modelarray[ level._breakable_utility_modelindex ] ) )
|
|
level._breakable_utility_modelarray[ level._breakable_utility_modelindex ] delete();
|
|
level._breakable_utility_modelarray[ level._breakable_utility_modelindex ] = model;
|
|
level._breakable_utility_modelindex++ ;
|
|
|
|
if ( !( level._breakable_utility_modelindex < level._breakable_utility_maxnum ) )
|
|
level._breakable_utility_modelindex = 0;
|
|
}
|
|
|
|
pieces_move( origin )
|
|
{
|
|
self endon( "do not kill" );
|
|
if ( isdefined( self.type ) && self.type == "bottle_bot" )
|
|
return;
|
|
|
|
org = spawn( "script_origin", self.origin );
|
|
self linkto( org );
|
|
end = self.origin + ( randomfloat( 10 ) - 5, randomfloat( 10 ) - 5, randomfloat( 10 ) + 5 );
|
|
// end = self.origin + ( randomfloat( 50 ) - 25, randomfloat( 50 ) - 25, randomfloat( 50 ) + 25 );
|
|
|
|
vec = undefined;
|
|
if ( isdefined( self.type ) && self.type == "bottle_top" )
|
|
{
|
|
vec = ( randomfloat( 40 ) - 20, randomfloat( 40 ) - 20, 70 + randomfloat( 15 ) );
|
|
x = 1;
|
|
y = 1;
|
|
z = 1;
|
|
if ( randomint( 100 ) > 50 )
|
|
x = -1;
|
|
if ( randomint( 100 ) > 50 )
|
|
y = -1;
|
|
if ( randomint( 100 ) > 50 )
|
|
z = -1;
|
|
|
|
org rotatevelocity( ( 250 * x, 250 * y, randomfloat( 100 ) * z ), 2, 0, .5 );
|
|
}
|
|
else if ( isdefined( self.type ) && self.type == "plate" )
|
|
{
|
|
vec = vectornormalize( end - origin );
|
|
vec = vector_multiply( vec, 125 + randomfloat( 25 ) );
|
|
if ( randomint( 100 ) > 50 )
|
|
org rotateroll( ( 800 + randomfloat( 4000 ) ) * - 1, 5, 0, 0 );
|
|
else
|
|
org rotateroll( 800 + randomfloat( 4000 ), 5, 0, 0 );
|
|
}
|
|
else
|
|
{
|
|
vec = vectornormalize( end - origin );
|
|
vec = vector_multiply( vec, 60 + randomfloat( 50 ) );
|
|
if ( randomint( 100 ) > 50 )
|
|
org rotateroll( ( 800 + randomfloat( 1000 ) ) * - 1, 5, 0, 0 );
|
|
else
|
|
org rotateroll( 800 + randomfloat( 1000 ), 5, 0, 0 );
|
|
}
|
|
|
|
|
|
|
|
org moveGravity( vec, 5 );
|
|
|
|
wait 5;
|
|
if ( isdefined( self ) )
|
|
self unlink();
|
|
org delete();
|
|
}
|
|
|
|
pieces_collision( height )
|
|
{
|
|
self endon( "death" );
|
|
|
|
//* * * * * * * * * * * * * IF YOU PUT THIS BACK IN - SEARCH FOR "PLATE WAIT" AND PUT THAT BACK IN TOO * * * * * * * * * * * * *
|
|
// if ( isdefined( self.type ) && self.type == "plate" )
|
|
// wait .35;
|
|
// else
|
|
//* * * * * * * * * * * * * IF YOU PUT THIS BACK IN - SEARCH FOR "PLATE WAIT" AND PUT THAT BACK IN TOO * * * * * * * * * * * * *
|
|
wait .1;
|
|
trace = bullettrace( self.origin, self.origin - ( 0, 0, 50000 ), false, undefined );
|
|
vec = trace[ "position" ];
|
|
|
|
while ( self.origin[ 2 ] > vec[ 2 ] )
|
|
wait .05;
|
|
|
|
self unlink();
|
|
|
|
self.origin = ( self.origin[ 0 ], self.origin[ 1 ], vec[ 2 ] );
|
|
|
|
self notify( "do not kill" );
|
|
self unlink();
|
|
}
|
|
|
|
addpiece( rt, fw, up, xs, ys, zs, wholepiece, angles, model )
|
|
{
|
|
scale = 1;
|
|
// if ( isdefined( wholepiece.modelscale ) )
|
|
// scale = wholepiece.modelscale;
|
|
|
|
x = rt;
|
|
y = fw;
|
|
z = up;
|
|
x = vector_multiply( x, ys * scale );
|
|
y = vector_multiply( y, xs * scale );
|
|
z = vector_multiply( z, zs * scale );
|
|
origin = wholepiece.origin + x + y + z;
|
|
part = spawn( "script_model", origin );
|
|
part setmodel( model );
|
|
part.modelscale = scale;
|
|
part.angles = wholepiece.angles + angles;
|
|
|
|
list_add( part );
|
|
|
|
return part;
|
|
}
|
|
|
|
getFurthestEnt( org, array )
|
|
{
|
|
if ( array.size < 1 )
|
|
return;
|
|
|
|
dist = distance( array[ 0 ] getorigin(), org );
|
|
ent = array[ 0 ];
|
|
// dist = 256;
|
|
// ent = undefined;
|
|
for ( i = 0;i < array.size;i++ )
|
|
{
|
|
newdist = distance( array[ i ] getorigin(), org );
|
|
if ( newdist < dist )
|
|
continue;
|
|
dist = newdist;
|
|
ent = array[ i ];
|
|
}
|
|
return ent;
|
|
}
|
|
|
|
getClosestEnt( org, array )
|
|
{
|
|
if ( array.size < 1 )
|
|
return;
|
|
|
|
// dist = distance( array[ 0 ] getorigin(), org );
|
|
// ent = array[ 0 ];
|
|
dist = 256;
|
|
ent = undefined;
|
|
for ( i = 0;i < array.size;i++ )
|
|
{
|
|
newdist = distance( array[ i ] getorigin(), org );
|
|
if ( newdist >= dist )
|
|
continue;
|
|
dist = newdist;
|
|
ent = array[ i ];
|
|
}
|
|
return ent;
|
|
}
|
|
|
|
getClosestAccurantEnt( org, array )
|
|
{
|
|
if ( array.size < 1 )
|
|
return;
|
|
|
|
// dist = distance( array[ 0 ] getorigin(), org );
|
|
// ent = array[ 0 ];
|
|
dist = 8;
|
|
ent = undefined;
|
|
for ( i = 0;i < array.size;i++ )
|
|
{
|
|
newdist = distance( array[ i ] getorigin(), org );
|
|
if ( newdist >= dist )
|
|
continue;
|
|
dist = newdist;
|
|
ent = array[ i ];
|
|
}
|
|
return ent;
|
|
}
|
|
|
|
getClosestAimEnt( org, array )
|
|
{
|
|
if ( array.size < 1 )
|
|
return;
|
|
|
|
// dist = distance( array[ 0 ] getorigin(), org );
|
|
// ent = array[ 0 ];
|
|
dist = 1000000;
|
|
ent = undefined;
|
|
for ( i = 0;i < array.size;i++ )
|
|
{
|
|
newdist = distance( array[ i ] getorigin(), org );
|
|
if ( newdist >= dist )
|
|
continue;
|
|
dist = newdist;
|
|
ent = array[ i ];
|
|
}
|
|
return ent;
|
|
} |