This commit is contained in:
6arelyFuture 2024-12-11 11:28:08 +01:00
commit 12ac62a956
Signed by: Future
GPG Key ID: F2000F181A4F7C85
444 changed files with 303964 additions and 0 deletions

270
codescripts/character.gsc Normal file
View File

@ -0,0 +1,270 @@
setModelFromArray( a )
{
self setModel( a[ randomint( a.size ) ] );
}
precacheModelArray( a )
{
for ( i = 0; i < a.size; i++ )
precacheModel( a[ i ] );
}
attachHead( headAlias, headArray )
{
/#
// For test map purposes only!! - IW5_Characters uses this.
if ( IsDefined( level.store_characterinfo ) )
{
if ( !IsDefined( self.characterinfo ) )
{
self.characterinfo = SpawnStruct();
self.characterinfo.headalias = headAlias;
self.characterinfo.headarray = headarray;
}
}
#/
if ( !isdefined( level.character_head_index ) )
level.character_head_index = [];
if ( !isdefined( level.character_head_index[ headAlias ] ) )
level.character_head_index[ headAlias ] = randomint( headArray.size );
assert( level.character_head_index[ headAlias ] < headArray.size );
index = ( level.character_head_index[ headAlias ] + 1 ) % headArray.size;
// the designer can overwrite the character
if ( isdefined( self.script_char_index ) )
{
index = self.script_char_index % headArray.size;
}
level.character_head_index[ headAlias ] = index;
self attach( headArray[ index ], "", true );
self.headModel = headArray[ index ];
}
attachHat( hatAlias, hatArray )
{
if ( !isdefined( level.character_hat_index ) )
level.character_hat_index = [];
if ( !isdefined( level.character_hat_index[ hatAlias ] ) )
level.character_hat_index[ hatAlias ] = randomint( hatArray.size );
assert( level.character_hat_index[ hatAlias ] < hatArray.size );
index = ( level.character_hat_index[ hatAlias ] + 1 ) % hatArray.size;
level.character_hat_index[ hatAlias ] = index;
self attach( hatArray[ index ] );
self.hatModel = hatArray[ index ];
}
new()
{
self detachAll();
oldGunHand = self.anim_gunHand;
if ( !isdefined( oldGunHand ) )
return;
self.anim_gunHand = "none";
self [[ anim.PutGunInHand ]]( oldGunHand );
}
save()
{
info[ "gunHand" ] = self.anim_gunHand;
info[ "gunInHand" ] = self.anim_gunInHand;
info[ "model" ] = self.model;
info[ "hatModel" ] = self.hatModel;
if ( isdefined( self.name ) )
{
info[ "name" ] = self.name;
println( "Save: Guy has name ", self.name );
}
else
println( "save: Guy had no name!" );
attachSize = self getAttachSize();
for ( i = 0; i < attachSize; i++ )
{
info[ "attach" ][ i ][ "model" ] = self getAttachModelName( i );
info[ "attach" ][ i ][ "tag" ] = self getAttachTagName( i );
}
return info;
}
load( info )
{
self detachAll();
self.anim_gunHand = info[ "gunHand" ];
self.anim_gunInHand = info[ "gunInHand" ];
self setModel( info[ "model" ] );
self.hatModel = info[ "hatModel" ];
if ( isdefined( info[ "name" ] ) )
{
self.name = info[ "name" ];
println( "Load: Guy has name ", self.name );
}
else
println( "Load: Guy had no name!" );
attachInfo = info[ "attach" ];
attachSize = attachInfo.size;
for ( i = 0; i < attachSize; i++ )
self attach( attachInfo[ i ][ "model" ], attachInfo[ i ][ "tag" ] );
}
precache( info )
{
if ( isdefined( info[ "name" ] ) )
println( "Precache: Guy has name ", info[ "name" ] );
else
println( "Precache: Guy had no name!" );
precacheModel( info[ "model" ] );
attachInfo = info[ "attach" ];
attachSize = attachInfo.size;
for ( i = 0; i < attachSize; i++ )
precacheModel( attachInfo[ i ][ "model" ] );
}
/*
sample save / precache / load usage( precache is only required if there are any waits in the level script before load ):
save:
info = foley codescripts\character::save();
game[ "foley" ] = info;
changelevel( "burnville", 0, true );
precache:
codescripts\character::precache( game[ "foley" ] );
load:
foley codescripts\character::load( game[ "foley" ] );
*/
get_random_character( amount )
{
self_info = strtok( self.classname, "_" );
if ( !common_scripts\utility::isSP() )
{
if ( isDefined( self.pers["modelIndex"] ) && self.pers["modelIndex"] < amount )
return self.pers["modelIndex"];
index = randomInt( amount );
self.pers["modelIndex"] = index;
return index;
}
else if ( self_info.size <= 2 )
{
// some custom guy that doesn't use standard naming convention
return randomint( amount );
}
group = "auto"; // by default the type is an auto-selected character
index = undefined;
prefix = self_info[ 2 ]; // merc, marine, etc
// the designer can overwrite the character
if ( isdefined( self.script_char_index ) )
{
index = self.script_char_index;
}
// the designer can hint that this guy is a member of a group of like - spawned guys, so he should use a different index
if ( isdefined( self.script_char_group ) )
{
type = "grouped";
group = "group_" + self.script_char_group;
}
if ( !isdefined( level.character_index_cache ) )
{
// separately store script grouped guys and auto guys so that they dont influence each other
level.character_index_cache = [];
}
if ( !isdefined( level.character_index_cache[ prefix ] ) )
{
// separately store script grouped guys and auto guys so that they dont influence each other
level.character_index_cache[ prefix ] = [];
}
if ( !isdefined( level.character_index_cache[ prefix ][ group ] ) )
{
initialize_character_group( prefix, group, amount );
}
if ( !isdefined( index ) )
{
index = get_least_used_index( prefix, group );
if ( !isdefined( index ) )
{
// fail safe
index = randomint( 5000 );
}
}
while ( index >= amount )
{
index -= amount;
}
level.character_index_cache[ prefix ][ group ][ index ]++;
return index;
}
get_least_used_index( prefix, group )
{
lowest_indices = [];
lowest_use = level.character_index_cache[ prefix ][ group ][ 0 ];
lowest_indices[ 0 ] = 0;
for ( i = 1; i < level.character_index_cache[ prefix ][ group ].size; i++ )
{
if ( level.character_index_cache[ prefix ][ group ][ i ] > lowest_use )
{
continue;
}
if ( level.character_index_cache[ prefix ][ group ][ i ] < lowest_use )
{
// if its the new lowest, start over on the array
lowest_indices = [];
lowest_use = level.character_index_cache[ prefix ][ group ][ i ];
}
// the equal amounts end up in the array
lowest_indices[ lowest_indices.size ] = i;
}
assertex( lowest_indices.size, "Tried to spawn a character but the lowest indices didn't exist" );
return random( lowest_indices );
}
initialize_character_group( prefix, group, amount )
{
for ( i = 0; i < amount; i++ )
{
level.character_index_cache[ prefix ][ group ][ i ] = 0;
}
}
get_random_weapon( amount )
{
return randomint( amount );
}
random( array )
{
return array [ randomint( array.size ) ];
}

7
codescripts/delete.gsc Normal file
View File

@ -0,0 +1,7 @@
main()
{
assert(isdefined(self));
wait 0;
if (isdefined(self))
self delete();
}

11
codescripts/struct.gsc Normal file
View File

@ -0,0 +1,11 @@
InitStructs()
{
level.struct = [];
}
CreateStruct()
{
struct = spawnstruct();
level.struct[level.struct.size] = struct;
return struct;
}

View File

@ -0,0 +1,286 @@
#include common_scripts\utility;
setfogsliders()
{
/#
// The read-only vars are set each time a call to SetExpFog is made, so they should contain the 'fog dest' params
SetDevDvar( "scr_fog_exp_halfplane", GetDvar( "g_fogHalfDistReadOnly", 0.0 ) );
SetDevDvar( "scr_fog_nearplane", GetDvar( "g_fogStartDistReadOnly", 0.1 ) );
SetDevDvar( "scr_fog_color", GetDvarVector( "g_fogColorReadOnly", ( 1, 0, 0 ) ) );
SetDevDvar( "scr_fog_color_intensity", GetDvar( "g_fogColorIntensityReadOnly", 1.0 ) );
SetDevDvar( "scr_fog_max_opacity", GetDvar( "g_fogMaxOpacityReadOnly", 1.0 ) );
SetDevDvar( "scr_sunFogEnabled", GetDvar( "g_sunFogEnabledReadOnly", 0 ) );
SetDevDvar( "scr_sunFogColor", GetDvarVector( "g_sunFogColorReadOnly", ( 1, 0, 0 ) ) );
SetDevDvar( "scr_sunfogColorIntensity", GetDvar( "g_sunFogColorIntensityReadOnly", 1.0 ) );
SetDevDvar( "scr_sunFogDir", GetDvarVector( "g_sunFogDirReadOnly", ( 1, 0, 0 ) ) );
SetDevDvar( "scr_sunFogBeginFadeAngle", GetDvar( "g_sunFogBeginFadeAngleReadOnly", 0.0 ) );
SetDevDvar( "scr_sunFogEndFadeAngle", GetDvar( "g_sunFogEndFadeAngleReadOnly", 180.0 ) );
SetDevDvar( "scr_sunFogScale", GetDvar( "g_sunFogScaleReadOnly", 1.0 ) );
// The r_sky_fog vars are only active if tweaks on them are enabled, which is a little strange...
SetDevDvar( "scr_skyFogIntensity", GetDvar( "r_sky_fog_intensity" ), 0.0 );
SetDevDvar( "scr_skyFogMinAngle", GetDvar( "r_sky_fog_min_angle" ), 0.0 );
SetDevDvar( "scr_skyFogMaxAngle", GetDvar( "r_sky_fog_max_angle" ), 90.0 );
#/
}
/#
translateFogSlidersToScript()
{
level.fogexphalfplane = limit( GetDvarFloat( "scr_fog_exp_halfplane" ) );
level.fognearplane = limit( GetDvarFloat( "scr_fog_nearplane" ) );
level.fogHDRColorIntensity = limit( GetDvarFloat( "scr_fog_color_intensity" ) );
level.fogmaxopacity = limit( GetDvarFloat( "scr_fog_max_opacity" ) );
level.sunFogEnabled = GetDvarInt( "scr_sunFogEnabled" );
level.sunFogHDRColorIntensity = limit( GetDvarFloat( "scr_sunFogColorIntensity" ) );
level.sunFogBeginFadeAngle = limit( GetDvarFloat( "scr_sunFogBeginFadeAngle" ) );
level.sunFogEndFadeAngle = limit( GetDvarFloat( "scr_sunFogEndFadeAngle" ) );
level.sunFogScale = limit( GetDvarFloat( "scr_sunFogScale" ) );
level.skyFogIntensity = limit( GetDvarFloat( "scr_skyFogIntensity" ) );
level.skyFogMinAngle = limit( GetDvarFloat( "scr_skyFogMinAngle" ) );
level.skyFogMaxAngle = limit( GetDvarFloat( "scr_skyFogMaxAngle" ) );
fogColor = GetDvarVector( "scr_fog_color" );
r = limit( fogColor[0] );
g = limit( fogColor[1] );
b = limit( fogColor[2] );
level.fogcolor = ( r, g , b );
sunFogColor = GetDvarVector( "scr_sunFogColor" );
r = limit( sunFogColor[0] );
g = limit( sunFogColor[1] );
b = limit( sunFogColor[2] );
level.sunFogColor =( r, g , b );
sunFogDir = GetDvarVector( "scr_sunFogDir" );
x = limit( sunFogDir[0]);
y = limit( sunFogDir[1]);
z = limit( sunFogDir[2]);
level.sunFogDir = ( x, y, z );
}
limit( i )
{
limit = 0.001;
if ( ( i < limit ) && ( i > ( limit * -1 ) ) )
i = 0;
return i;
}
fogslidercheck()
{
// catch all those cases where a slider can be pushed to a place of conflict
if ( level.sunFogBeginFadeAngle >= level.sunFogEndFadeAngle )
{
level.sunFogBeginFadeAngle = level.sunFogEndFadeAngle - 1;
SetDvar( "scr_sunFogBeginFadeAngle", level.sunFogBeginFadeAngle );
}
if ( level.sunFogEndFadeAngle <= level.sunFogBeginFadeAngle )
{
level.sunFogEndFadeAngle = level.sunFogBeginFadeAngle + 1;
SetDvar( "scr_sunFogEndFadeAngle", level.sunFogEndFadeAngle );
}
}
add_vision_set_to_list( vision_set_name )
{
assert( IsDefined( level.vision_set_names ) );
found = array_find( level.vision_set_names, vision_set_name );
if ( IsDefined( found ) )
return;
level.vision_set_names = array_add( level.vision_set_names, vision_set_name );
}
print_vision( vision_set )
{
found = array_find( level.vision_set_names, vision_set );
if ( !IsDefined( found ) )
return;
fileprint_launcher_start_file();
// Glow
fileprint_launcher( "r_glow \"" + GetDvar( "r_glowTweakEnable" ) + "\"" );
fileprint_launcher( "r_glowRadius0 \"" + GetDvar( "r_glowTweakRadius0" ) + "\"" );
fileprint_launcher( "r_glowBloomPinch \"" + GetDvar( "r_glowTweakBloomPinch" ) + "\"" );
fileprint_launcher( "r_glowBloomCutoff \"" + GetDvar( "r_glowTweakBloomCutoff" ) + "\"" );
fileprint_launcher( "r_glowBloomDesaturation \"" + GetDvar( "r_glowTweakBloomDesaturation" ) + "\"" );
fileprint_launcher( "r_glowBloomIntensity0 \"" + GetDvar( "r_glowTweakBloomIntensity0" ) + "\"" );
fileprint_launcher( "r_glowUseAltCutoff \"" + GetDvar( "r_glowTweakUseAltCutoff" ) + "\"" );
fileprint_launcher( " " );
// Film
fileprint_launcher( "r_filmEnable \"" + GetDvar( "r_filmTweakEnable" ) + "\"" );
fileprint_launcher( "r_filmContrast \"" + GetDvar( "r_filmTweakContrast" ) + "\"" );
fileprint_launcher( "r_filmBrightness \"" + GetDvar( "r_filmTweakBrightness" ) + "\"" );
fileprint_launcher( "r_filmDesaturation \"" + GetDvar( "r_filmTweakDesaturation" ) + "\"" );
fileprint_launcher( "r_filmDesaturationDark \"" + GetDvar( "r_filmTweakDesaturationDark" ) + "\"" );
fileprint_launcher( "r_filmInvert \"" + GetDvar( "r_filmTweakInvert" ) + "\"" );
fileprint_launcher( "r_filmLightTint \"" + GetDvar( "r_filmTweakLightTint" ) + "\"" );
fileprint_launcher( "r_filmMediumTint \"" + GetDvar( "r_filmTweakMediumTint" ) + "\"" );
fileprint_launcher( "r_filmDarkTint \"" + GetDvar( "r_filmTweakDarkTint" ) + "\"" );
fileprint_launcher( " " );
// Character Light
fileprint_launcher( "r_primaryLightUseTweaks \"" + GetDvar( "r_primaryLightUseTweaks" ) + "\"" );
fileprint_launcher( "r_primaryLightTweakDiffuseStrength \"" + GetDvar( "r_primaryLightTweakDiffuseStrength" ) + "\"" );
fileprint_launcher( "r_primaryLightTweakSpecularStrength \"" + GetDvar( "r_primaryLightTweakSpecularStrength" ) + "\"" );
fileprint_launcher( "r_charLightAmbient \"" + GetDvar( "r_charLightAmbient" ) + "\"" );
fileprint_launcher( "r_primaryLightUseTweaks_NG \"" + GetDvar( "r_primaryLightUseTweaks_NG" ) + "\"" );
fileprint_launcher( "r_primaryLightTweakDiffuseStrength_NG \"" + GetDvar( "r_primaryLightTweakDiffuseStrength_NG" ) + "\"" );
fileprint_launcher( "r_primaryLightTweakSpecularStrength_NG \"" + GetDvar( "r_primaryLightTweakSpecularStrength_NG" ) + "\"" );
fileprint_launcher( "r_charLightAmbient_NG \"" + GetDvar( "r_charLightAmbient_NG" ) + "\"" );
fileprint_launcher( " " );
// Viewmodel Light
fileprint_launcher( "r_viewModelPrimaryLightUseTweaks \"" + GetDvar( "r_viewModelPrimaryLightUseTweaks" ) + "\"" );
fileprint_launcher( "r_viewModelPrimaryLightTweakDiffuseStrength \"" + GetDvar( "r_viewModelPrimaryLightTweakDiffuseStrength" ) + "\"" );
fileprint_launcher( "r_viewModelPrimaryLightTweakSpecularStrength \"" + GetDvar( "r_viewModelPrimaryLightTweakSpecularStrength" ) + "\"" );
fileprint_launcher( "r_viewModelLightAmbient \"" + GetDvar( "r_viewModelLightAmbient" ) + "\"" );
fileprint_launcher( "r_viewModelPrimaryLightUseTweaks_NG \"" + GetDvar( "r_viewModelPrimaryLightUseTweaks_NG" ) + "\"" );
fileprint_launcher( "r_viewModelPrimaryLightTweakDiffuseStrength_NG \"" + GetDvar( "r_viewModelPrimaryLightTweakDiffuseStrength_NG" ) + "\"" );
fileprint_launcher( "r_viewModelPrimaryLightTweakSpecularStrength_NG \"" + GetDvar( "r_viewModelPrimaryLightTweakSpecularStrength_NG" ) + "\"" );
fileprint_launcher( "r_viewModelLightAmbient_NG \"" + GetDvar( "r_viewModelLightAmbient_NG" ) + "\"" );
fileprint_launcher( " " );
// Material Bloom
fileprint_launcher( "r_materialBloomRadius \"" + GetDvar( "r_materialBloomRadius" ) + "\"" );
fileprint_launcher( "r_materialBloomPinch \"" + GetDvar( "r_materialBloomPinch" ) + "\"" );
fileprint_launcher( "r_materialBloomIntensity \"" + GetDvar( "r_materialBloomIntensity" ) + "\"" );
fileprint_launcher( "r_materialBloomLuminanceCutoff \"" + GetDvar( "r_materialBloomLuminanceCutoff" ) + "\"" );
fileprint_launcher( "r_materialBloomDesaturation \"" + GetDvar( "r_materialBloomDesaturation" ) + "\"" );
fileprint_launcher( " " );
// Volume Light Scatter
fileprint_launcher( "r_volumeLightScatter \"" + GetDvar( "r_volumeLightScatterUseTweaks" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterLinearAtten \"" + GetDvar( "r_volumeLightScatterLinearAtten" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterQuadraticAtten \"" + GetDvar( "r_volumeLightScatterQuadraticAtten" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterAngularAtten \"" + GetDvar( "r_volumeLightScatterAngularAtten" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterDepthAttenNear \"" + GetDvar( "r_volumeLightScatterDepthAttenNear" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterDepthAttenFar \"" + GetDvar( "r_volumeLightScatterDepthAttenFar" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterBackgroundDistance \"" + GetDvar( "r_volumeLightScatterBackgroundDistance" ) + "\"" );
fileprint_launcher( "r_volumeLightScatterColor \"" + GetDvar( "r_volumeLightScatterColor" ) + "\"" );
fileprint_launcher( " " );
// SSAO
fileprint_launcher( "r_ssaoStrength \"" + GetDvar( "r_ssaoStrength" ) + "\"" );
fileprint_launcher( "r_ssaoPower \"" + GetDvar( "r_ssaoPower" ) + "\"" );
fileprint_launcher( " " );
// Rim Light
fileprint_launcher( "r_rimLight0Pitch \"" + GetDvar( "r_rimLight0Pitch" ) + "\"" );
fileprint_launcher( "r_rimLight0Heading \"" + GetDvar( "r_rimLight0Heading" ) + "\"" );
fileprint_launcher( "r_rimLightDiffuseIntensity \"" + GetDvar( "r_rimLightDiffuseIntensity" ) + "\"" );
fileprint_launcher( "r_rimLightSpecIntensity \"" + GetDvar( "r_rimLightSpecIntensity" ) + "\"" );
fileprint_launcher( "r_rimLightBias \"" + GetDvar( "r_rimLightBias" ) + "\"" );
fileprint_launcher( "r_rimLightPower \"" + GetDvar( "r_rimLightPower" ) + "\"" );
fileprint_launcher( "r_rimLight0Color \"" + GetDvar( "r_rimLight0Color" ) + "\"" );
fileprint_launcher( "r_rimLight0Pitch_NG \"" + GetDvar( "r_rimLight0Pitch_NG" ) + "\"" );
fileprint_launcher( "r_rimLight0Heading_NG \"" + GetDvar( "r_rimLight0Heading_NG" ) + "\"" );
fileprint_launcher( "r_rimLightDiffuseIntensity_NG \"" + GetDvar( "r_rimLightDiffuseIntensity_NG" ) + "\"" );
fileprint_launcher( "r_rimLightSpecIntensity_NG \"" + GetDvar( "r_rimLightSpecIntensity_NG" ) + "\"" );
fileprint_launcher( "r_rimLightBias_NG \"" + GetDvar( "r_rimLightBias_NG" ) + "\"" );
fileprint_launcher( "r_rimLightPower_NG \"" + GetDvar( "r_rimLightPower_NG" ) + "\"" );
fileprint_launcher( "r_rimLight0Color_NG \"" + GetDvar( "r_rimLight0Color_NG" ) + "\"" );
fileprint_launcher( " " );
// Unlit Surface
fileprint_launcher( "r_unlitSurfaceHDRScalar \"" + GetDvar( "r_unlitSurfaceHDRScalar" ) + "\"" );
fileprint_launcher( " " );
// Colorization
colorizationName = GetDvar( "r_colorizationTweakName" );
toneMappingName = GetDvar( "r_toneMappingTweakName" );
clutMaterialName = GetDvar( "r_clutMaterialTweakName" );
if ( colorizationName != "" )
fileprint_launcher( "colorizationSet \"" + colorizationName + "\"" );
if ( toneMappingName != "" )
fileprint_launcher( "toneMapping \"" + toneMappingName + "\"" );
if ( clutMaterialName != "" )
fileprint_launcher( "clutMaterial \"" + clutMaterialName + "\"" );
return fileprint_launcher_end_file( "\\share\\raw\\vision\\" + vision_set + ".vision", true );
}
print_fog_ents( forMP )
{
foreach( ent in level.vision_set_fog )
{
if( !isdefined( ent.name ) )
continue;
if ( forMP )
fileprint_launcher( "\tent = maps\\mp\\_art::create_vision_set_fog( \"" + ent.name + "\" );");
else
fileprint_launcher( "\tent = maps\\_utility::create_vision_set_fog( \"" + ent.name + "\" );");
fileprint_launcher( "\tent.startDist = " + ent.startDist + ";" );
fileprint_launcher( "\tent.halfwayDist = " + ent.halfwayDist + ";" );
fileprint_launcher( "\tent.red = " + ent.red + ";" );
fileprint_launcher( "\tent.green = " + ent.green + ";" );
fileprint_launcher( "\tent.blue = " + ent.blue + ";" );
fileprint_launcher( "\tent.HDRColorIntensity = " + ent.HDRColorIntensity + ";" );
fileprint_launcher( "\tent.maxOpacity = " + ent.maxOpacity + ";" );
fileprint_launcher( "\tent.transitionTime = " + ent.transitionTime + ";" );
fileprint_launcher( "\tent.sunFogEnabled = " + ent.sunFogEnabled + ";" );
fileprint_launcher( "\tent.sunRed = " + ent.sunRed + ";" );
fileprint_launcher( "\tent.sunGreen = " + ent.sunGreen + ";" );
fileprint_launcher( "\tent.sunBlue = " + ent.sunBlue + ";" );
fileprint_launcher( "\tent.HDRSunColorIntensity = " + ent.HDRSunColorIntensity + ";" );
fileprint_launcher( "\tent.sunDir = " + ent.sunDir + ";" );
fileprint_launcher( "\tent.sunBeginFadeAngle = " + ent.sunBeginFadeAngle + ";" );
fileprint_launcher( "\tent.sunEndFadeAngle = " + ent.sunEndFadeAngle + ";" );
fileprint_launcher( "\tent.normalFogScale = " + ent.normalFogScale + ";" );
fileprint_launcher( "\tent.skyFogIntensity = " + ent.skyFogIntensity + ";" );
fileprint_launcher( "\tent.skyFogMinAngle = " + ent.skyFogMinAngle + ";" );
fileprint_launcher( "\tent.skyFogMaxAngle = " + ent.skyFogMaxAngle + ";" );
if ( IsDefined( ent.HDROverride ) )
fileprint_launcher( "\tent.HDROverride = \"" + ent.HDROverride + "\";" );
if( isDefined( ent.stagedVisionSets ) )
{
string = " ";
for( i = 0; i < ent.stagedVisionSets.size; i++ )
{
string = string + "\""+ ent.stagedVisionSets[i] + "\"";
if ( i < ent.stagedVisionSets.size - 1 )
string = string + ",";
string = string + " ";
}
fileprint_launcher( "\tent.stagedVisionSets = [" + string + "];" );
}
fileprint_launcher ( " " );
}
}
print_fog_ents_csv()
{
foreach( ent in level.vision_set_fog )
{
if( !isdefined( ent.name ) )
continue;
targettedByHDROverride = false;
foreach( ent2 in level.vision_set_fog )
{
if ( isdefined(ent2.HDROverride) && ent2.HDROverride == ent.name )
{
targettedByHDROverride = true;
break;
}
}
if ( !targettedByHDROverride )
fileprint_launcher( "rawfile,vision/"+ent.name+".vision");
}
}
#/

File diff suppressed because it is too large Load Diff

2578
common_scripts/_createfx.gsc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,755 @@
#include common_scripts\utility;
#include common_scripts\_createfx;
//---------------------------------------------------------
// Menu init/loop section
//---------------------------------------------------------
init_menu()
{
level._createfx.options = [];
// each option has a type, a name its stored under, a description, a default, and a mask it uses to determine
// which types of fx can have this option
addOption( "string", "fxid", "FX id", "nil", "fx" );
addOption( "float", "delay", "Repeat rate/start delay", 0.5, "fx" );
addOption( "string", "flag", "Flag", "nil", "exploder" );
if( !level.mp_createfx )
{
addOption( "string", "firefx", "2nd FX id", "nil", "exploder" );
addOption( "float", "firefxdelay", "2nd FX id repeat rate", 0.5, "exploder" );
addOption( "float", "firefxtimeout", "2nd FX timeout", 5, "exploder" );
addOption( "string", "firefxsound", "2nd FX soundalias", "nil", "exploder" );
addOption( "float", "damage", "Radius damage", 150, "exploder" );
addOption( "float", "damage_radius", "Radius of radius damage", 250, "exploder" );
addOption( "string", "earthquake", "Earthquake", "nil", "exploder" );
addOption( "string", "ender", "Level notify for ending 2nd FX", "nil", "exploder" );
}
addOption( "float", "delay_min", "Minimimum time between repeats", 1, "soundfx_interval" );
addOption( "float", "delay_max", "Maximum time between repeats", 2, "soundfx_interval" );
addOption( "int", "repeat", "Number of times to repeat", 5, "exploder" );
addOption( "string", "exploder", "Exploder", "1", "exploder" );
addOption( "string", "soundalias", "Soundalias", "nil", "all" );
addOption( "string", "loopsound", "Loopsound", "nil", "exploder" );
addOption( "int", "reactive_radius", "Reactive Radius", 100, "reactive_fx", ::input_reactive_radius );
if( !level.mp_createfx )
{
addOption( "string", "rumble", "Rumble", "nil", "exploder" );
addOption( "int", "stoppable", "Can be stopped from script", "1", "all" );
}
level.effect_list_offset = 0;
level.effect_list_offset_max = 10;
// creates mask groups. For example if the above says its mask is "fx", then all the types under "fx" can use the option
level.createfxMasks = [];
level.createfxMasks[ "all" ] = [];
level.createfxMasks[ "all" ][ "exploder" ] = true;
level.createfxMasks[ "all" ][ "oneshotfx" ] = true;
level.createfxMasks[ "all" ][ "loopfx" ] = true;
level.createfxMasks[ "all" ][ "soundfx" ] = true;
level.createfxMasks[ "all" ][ "soundfx_interval" ] = true;
level.createfxMasks[ "all" ][ "reactive_fx" ] = true;
level.createfxMasks[ "fx" ] = [];
level.createfxMasks[ "fx" ][ "exploder" ] = true;
level.createfxMasks[ "fx" ][ "oneshotfx" ] = true;
level.createfxMasks[ "fx" ][ "loopfx" ] = true;
level.createfxMasks[ "exploder" ] = [];
level.createfxMasks[ "exploder" ][ "exploder" ] = true;
level.createfxMasks[ "loopfx" ] = [];
level.createfxMasks[ "loopfx" ][ "loopfx" ] = true;
level.createfxMasks[ "oneshotfx" ] = [];
level.createfxMasks[ "oneshotfx" ][ "oneshotfx" ] = true;
level.createfxMasks[ "soundfx" ] = [];
level.createfxMasks[ "soundfx" ][ "soundalias" ] = true;
level.createfxMasks[ "soundfx_interval" ] = [];
level.createfxMasks[ "soundfx_interval" ][ "soundfx_interval" ] = true;
level.createfxMasks[ "reactive_fx" ] = [];
level.createfxMasks[ "reactive_fx" ][ "reactive_fx" ] = true;
// Mainly used for input of a menu
menus = [];
menus[ "creation" ] = ::menu_create_select;
menus[ "create_oneshot" ] = ::menu_create;
menus[ "create_loopfx" ] = ::menu_create;
menus[ "change_fxid" ] = ::menu_create;
menus[ "none" ] = ::menu_none;
menus[ "add_options" ] = ::menu_add_options;
menus[ "select_by_name" ] = ::menu_select_by_name;
level._createfx.menus = menus;
}
menu( name )
{
return level.create_fx_menu == name;
}
setmenu( name )
{
level.create_fx_menu = name;
}
create_fx_menu()
{
if ( button_is_clicked( "escape", "x" ) )
{
_exit_menu();
return;
}
if ( IsDefined( level._createfx.menus[ level.create_fx_menu ] ) )
{
[[ level._createfx.menus[ level.create_fx_menu ] ]]();
}
}
menu_create_select()
{
if ( button_is_clicked( "1" ) )
{
setmenu( "create_oneshot" );
draw_effects_list();
return;
}
else if ( button_is_clicked( "2" ) )
{
setmenu( "create_loopsound" );
ent = createLoopSound();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "3" ) )
{
setmenu( "create_exploder" );
ent = createNewExploder();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "4" ) )
{
setmenu( "create_interval_sound" );
ent = createIntervalSound();
finish_creating_entity( ent );
return;
}
else if ( button_is_clicked( "5" ) )
{
ent = createReactiveEnt();
finish_creating_entity( ent );
return;
}
}
menu_create()
{
if ( next_button() )
{
increment_list_offset();
draw_effects_list();
}
else if ( previous_button() )
{
decrement_list_offset();
draw_effects_list();
}
menu_fx_creation();
}
menu_none()
{
if ( button_is_clicked( "m" ) )
increment_list_offset();
// change selected entities
menu_change_selected_fx();
// if there's a selected ent then display the info on the last one to be selected
if ( entities_are_selected() )
{
last_selected_ent = get_last_selected_ent();
// only update hudelems when we have new info
if ( !IsDefined( level.last_displayed_ent ) || last_selected_ent != level.last_displayed_ent )
{
display_fx_info( last_selected_ent );
level.last_displayed_ent = last_selected_ent;
}
if ( button_is_clicked( "a" ) )
{
clear_settable_fx();
setMenu( "add_options" );
}
}
else
{
level.last_displayed_ent = undefined;
}
}
menu_add_options()
{
if ( !entities_are_selected() )
{
clear_fx_hudElements();
setMenu( "none" );
return;
}
display_fx_add_options( get_last_selected_ent() );
if ( next_button() )
{
increment_list_offset();
// draw_effects_list();
}
}
menu_select_by_name()
{
if ( next_button() )
{
increment_list_offset();
draw_effects_list( "Select by name" );
}
else if ( previous_button() )
{
decrement_list_offset();
draw_effects_list( "Select by name" );
}
select_by_name();
}
next_button()
{
return button_is_clicked( "rightarrow" );
}
previous_button()
{
return button_is_clicked( "leftarrow" );
}
_exit_menu()
{
clear_fx_hudElements();
clear_entity_selection();
update_selected_entities();
setmenu( "none" );
}
//---------------------------------------------------------
// Create FX Section (button presses)
//---------------------------------------------------------
menu_fx_creation()
{
count = 0;
picked_fx = undefined;
keys = func_get_level_fx();
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
button_to_check = count;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
picked_fx = keys[ i ];
break;
}
if ( count > level.effect_list_offset_max )
break;
}
if ( !isdefined( picked_fx ) )
return;
if ( menu( "change_fxid" ) )
{
apply_option_to_selected_fx( get_option( "fxid" ), picked_fx );
level.effect_list_offset = 0;
clear_fx_hudElements();
setMenu( "none" );
return;
}
ent = undefined;
if ( menu( "create_loopfx" ) )
ent = createLoopEffect( picked_fx );
if ( menu( "create_oneshot" ) )
ent = createOneshotEffect( picked_fx );
finish_creating_entity( ent );
}
finish_creating_entity( ent )
{
assert( isdefined( ent ) );
ent.v[ "angles" ] = vectortoangles( ( ent.v[ "origin" ] + ( 0, 0, 100 ) ) - ent.v[ "origin" ] );
ent post_entity_creation_function();// for createfx dev purposes
clear_entity_selection();
select_last_entity();
move_selection_to_cursor();
update_selected_entities();
setMenu( "none" );
}
entities_are_selected()
{
return level._createfx.selected_fx_ents.size > 0;
}
menu_change_selected_fx()
{
if ( !level._createfx.selected_fx_ents.size )
{
return;
}
count = 0;
drawnCount = 0;
ent = get_last_selected_ent();
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
drawnCount++ ;
button_to_check = drawnCount;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
prepare_option_for_change( option, drawnCount );
break;
}
if ( drawnCount > level.effect_list_offset_max )
{
more = true;
break;
}
}
}
prepare_option_for_change( option, drawnCount )
{
if ( option[ "name" ] == "fxid" )
{
setMenu( "change_fxid" );
draw_effects_list();
return;
}
level.createfx_inputlocked = true;
level._createfx.hudelems[ drawnCount + 3 ][ 0 ].color = ( 1, 1, 0 );
if ( IsDefined( option[ "input_func" ] ) )
{
thread [[ option[ "input_func" ] ]]( drawnCount + 3 );
}
else
{
createfx_centerprint( "To change " + option[ "description" ] + " on selected entities, type /fx newvalue" );
}
set_option_index( option[ "name" ] );
setdvar( "fx", "nil" );
}
menu_fx_option_set()
{
if ( getdvar( "fx" ) == "nil" )
return;
option = get_selected_option();
setting = undefined;
if ( option[ "type" ] == "string" )
setting = getdvar( "fx" );
if ( option[ "type" ] == "int" )
setting = getdvarint( "fx" );
if ( option[ "type" ] == "float" )
setting = getdvarfloat( "fx" );
apply_option_to_selected_fx( option, setting );
}
apply_option_to_selected_fx( option, setting )
{
for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
{
ent = level._createfx.selected_fx_ents[ i ];
if ( mask( option[ "mask" ], ent.v[ "type" ] ) )
ent.v[ option[ "name" ] ] = setting;
}
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
update_selected_entities();
clear_settable_fx();
}
set_option_index( name )
{
for ( i = 0; i < level._createfx.options.size; i++ )
{
if ( level._createfx.options[ i ][ "name" ] != name )
continue;
level._createfx.selected_fx_option_index = i;
return;
}
}
get_selected_option()
{
return level._createfx.options[ level._createfx.selected_fx_option_index ];
}
mask( type, name )
{
return isdefined( level.createfxMasks[ type ][ name ] );
}
addOption( type, name, description, defaultSetting, mask, input_func )
{
option = [];
option[ "type" ] = type;
option[ "name" ] = name;
option[ "description" ] = description;
option[ "default" ] = defaultSetting;
option[ "mask" ] = mask;
if ( IsDefined( input_func ) )
{
option[ "input_func" ] = input_func;
}
level._createfx.options[ level._createfx.options.size ] = option;
}
get_option( name )
{
for ( i = 0; i < level._createfx.options.size; i++ )
{
if ( level._createfx.options[ i ][ "name" ] == name )
return level._createfx.options[ i ];
}
}
//---------------------------------------------------------
// Reactive Radius
//---------------------------------------------------------
input_reactive_radius( menu_index )
{
level._createfx.hudelems[ menu_index ][ 0 ] SetDevText( "Reactive Radius, Press: + OR -" );
while ( 1 )
{
wait( 0.05 );
if ( level.player ButtonPressed( "escape" ) || level.player ButtonPressed( "x" ) )
break;
val = 0;
if ( level.player ButtonPressed( "-" ) )
val = -10;
else if ( level.player ButtonPressed( "=" ) )
val = 10;
if ( val != 0 )
{
foreach ( ent in level._createfx.selected_fx_ents )
{
if ( IsDefined( ent.v[ "reactive_radius" ] ) )
{
ent.v[ "reactive_radius" ] += val;
ent.v[ "reactive_radius" ] = Clamp( ent.v[ "reactive_radius" ], 10, 1000 );
}
}
}
}
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
update_selected_entities();
clear_settable_fx();
}
//---------------------------------------------------------
// Display FX Add Options
//---------------------------------------------------------
display_fx_add_options( ent )
{
// are we doing the create fx menu right now?
assert( menu( "add_options" ) );
assert( entities_are_selected() );
clear_fx_hudElements();
set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
set_fx_hudElement( "Type: " + ent.v[ "type" ] );
set_fx_hudElement( "Origin: " + ent.v[ "origin" ] );
set_fx_hudElement( "Angles: " + ent.v[ "angles" ] );
// if entities are selected then we make the entity stats modifiable
count = 0;
drawnCount = 0;
more = false;
if ( level.effect_list_offset >= level._createfx.options.size )
level.effect_list_offset = 0;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( isdefined( ent.v[ option[ "name" ] ] ) )
continue;
// does this type of effect get this kind of option?
if ( !mask( option[ "mask" ], ent.v[ "type" ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
if ( drawnCount >= level.effect_list_offset_max )
continue;
drawnCount++ ;
button_to_check = drawnCount;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
add_option_to_selected_entities( option );
// prepare_option_for_change( option, drawnCount );
menuNone();
level.last_displayed_ent = undefined; // needed to force a redraw of the last display ent
return;
}
set_fx_hudElement( button_to_check + ". " + option[ "description" ] );
}
if ( count > level.effect_list_offset_max )
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(x) Exit >" );
}
add_option_to_selected_entities( option )
{
setting = undefined;
for ( i = 0; i < level._createfx.selected_fx_ents.size; i++ )
{
ent = level._createfx.selected_fx_ents[ i ];
if ( mask( option[ "mask" ], ent.v[ "type" ] ) )
ent.v[ option[ "name" ] ] = option[ "default" ];
}
}
menuNone()
{
level.effect_list_offset = 0;
clear_fx_hudElements();
setMenu( "none" );
}
//---------------------------------------------------------
// Display FX info
//---------------------------------------------------------
display_fx_info( ent )
{
// are we doing the create fx menu right now?
if ( !menu( "none" ) )
return;
clear_fx_hudElements();
set_fx_hudElement( "Name: " + ent.v[ "fxid" ] );
set_fx_hudElement( "Type: " + ent.v[ "type" ] );
set_fx_hudElement( "Origin: " + ent.v[ "origin" ] );
set_fx_hudElement( "Angles: " + ent.v[ "angles" ] );
if ( entities_are_selected() )
{
// if entities are selected then we make the entity stats modifiable
count = 0;
drawnCount = 0;
more = false;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
if ( count < level.effect_list_offset )
continue;
drawnCount++ ;
set_fx_hudElement( drawnCount + ". " + option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
if ( drawnCount > level.effect_list_offset_max )
{
more = true;
break;
}
}
if ( count > level.effect_list_offset_max )
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(a) Add >" );
set_fx_hudElement( "(x) Exit >" );
}
else
{
count = 0;
more = false;
for ( i = 0; i < level._createfx.options.size; i++ )
{
option = level._createfx.options[ i ];
if ( !isdefined( ent.v[ option[ "name" ] ] ) )
continue;
count++ ;
set_fx_hudElement( option[ "description" ] + ": " + ent.v[ option[ "name" ] ] );
if ( count > level._createfx.hudelem_count )
break;
}
}
}
//---------------------------------------------------------
// Draw Effects Section
//---------------------------------------------------------
draw_effects_list( title )
{
clear_fx_hudElements();
count = 0;
more = false;
keys = func_get_level_fx();
if( !IsDefined( title ) )
{
title = "Pick an effect";
}
set_fx_hudElement( title + " [" + level.effect_list_offset + " - " + keys.size + "]:" );
// if ( level.effect_list_offset >= keys.size )
// level.effect_list_offset = 0;
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
set_fx_hudElement( count + ". " + keys[ i ] );
if ( count >= level.effect_list_offset_max )
{
more = true;
break;
}
}
if ( keys.size > level.effect_list_offset_max )
{
set_fx_hudElement( "(->) More >" );
set_fx_hudElement( "(<-) Previous >" );
}
}
increment_list_offset()
{
keys = func_get_level_fx();
if ( level.effect_list_offset >= keys.size - level.effect_list_offset_max )
{
level.effect_list_offset = 0;
}
else
{
level.effect_list_offset += level.effect_list_offset_max;
}
}
decrement_list_offset()
{
level.effect_list_offset -= level.effect_list_offset_max;
if ( level.effect_list_offset < 0 )
{
keys = func_get_level_fx();
level.effect_list_offset = keys.size - level.effect_list_offset_max;
}
}
//---------------------------------------------------------
// Select by Name Section
//---------------------------------------------------------
select_by_name()
{
count = 0;
picked_fx = undefined;
keys = func_get_level_fx();
for ( i = level.effect_list_offset; i < keys.size; i++ )
{
count = count + 1;
button_to_check = count;
if ( button_to_check == 10 )
button_to_check = 0;
if ( button_is_clicked( button_to_check + "" ) )
{
picked_fx = keys[ i ];
break;
}
if ( count > level.effect_list_offset_max )
break;
}
if ( !IsDefined( picked_fx ) )
return;
index_array = [];
foreach ( i, ent in level.createFXent )
{
if ( IsSubStr( ent.v[ "fxid" ], picked_fx ) )
{
index_array[ index_array.size ] = i;
}
}
deselect_all_ents();
select_index_array( index_array );
level._createfx.select_by_name = true;
}
//---------------------------------------------------------
// Utility Section
//---------------------------------------------------------
get_last_selected_ent()
{
return level._createfx.selected_fx_ents[ level._createfx.selected_fx_ents.size - 1 ];
}

1226
common_scripts/_csplines.gsc Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1286
common_scripts/_elevator.gsc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,987 @@
#include common_scripts\utility;
/*
Handles Old-School exploders. This is coupled with _createfx and _fx since a Radiant Created "exploder" can trigger a createfx created effect.
This Script is legacy, tried and true, It eats up entites when using script_brushmodel swapping and a lot of script_models and the damage triggers.
We should in a future game consider some entiity optimization in code. A way to Join models and brushes as one entity would be key.
*/
setup_individual_exploder( ent )
{
exploder_num = ent.script_exploder;
if ( !IsDefined( level.exploders[ exploder_num ] ) )
{
level.exploders[ exploder_num ] = [];
}
targetname = ent.targetname;
if ( !IsDefined( targetname ) )
targetname = "";
level.exploders[ exploder_num ][ level.exploders[ exploder_num ].size ] = ent;
if ( exploder_model_starts_hidden( ent ) )
{
ent Hide();
return;
}
if ( exploder_model_is_damaged_model( ent ) )
{
ent Hide();
ent NotSolid();
if ( IsDefined( ent.spawnflags ) && ( ent.spawnflags & 1 ) )
{
if ( IsDefined( ent.script_disconnectpaths ) )
{
ent ConnectPaths();
}
}
return;
}
if ( exploder_model_is_chunk( ent ) )
{
ent Hide();
ent NotSolid();
if ( IsDefined( ent.spawnflags ) && ( ent.spawnflags & 1 ) )
ent ConnectPaths();
return;
}
}
setupExploders()
{
level.exploders = [];
// Hide exploder models.
ents = GetEntArray( "script_brushmodel", "classname" );
smodels = GetEntArray( "script_model", "classname" );
for ( i = 0; i < smodels.size; i++ )
ents[ ents.size ] = smodels[ i ];
foreach ( ent in ents )
{
if ( IsDefined( ent.script_prefab_exploder ) )
ent.script_exploder = ent.script_prefab_exploder;
if ( IsDefined( ent.masked_exploder ) )
continue;
if ( IsDefined( ent.script_exploder ) )
{
setup_individual_exploder( ent );
}
}
script_exploders = [];
potentialExploders = GetEntArray( "script_brushmodel", "classname" );
for ( i = 0; i < potentialExploders.size; i++ )
{
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
}
potentialExploders = GetEntArray( "script_model", "classname" );
for ( i = 0; i < potentialExploders.size; i++ )
{
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
}
potentialExploders = GetEntArray( "item_health", "classname" );
for ( i = 0; i < potentialExploders.size; i++ )
{
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
}
potentialExploders = level.struct;
for ( i = 0; i < potentialExploders.size; i++ )
{
if ( !IsDefined( potentialExploders[ i ] ) )
continue; // these must be getting deleted somewhere else?
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
{
if ( !IsDefined( potentialExploders[ i ].angles ) )
potentialExploders[ i ].angles = ( 0, 0, 0 );
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
}
}
if ( !IsDefined( level.createFXent ) )
level.createFXent = [];
acceptableTargetnames = [];
acceptableTargetnames[ "exploderchunk visible" ] = true;
acceptableTargetnames[ "exploderchunk" ] = true;
acceptableTargetnames[ "exploder" ] = true;
thread setup_flag_exploders();
for ( i = 0; i < script_exploders.size; i++ )
{
exploder = script_exploders[ i ];
ent = createExploder( exploder.script_fxid );
ent.v = [];
ent.v[ "origin" ] = exploder.origin;
ent.v[ "angles" ] = exploder.angles;
ent.v[ "delay" ] = exploder.script_delay;
ent.v[ "delay_post" ] = exploder.script_delay_post;
ent.v[ "firefx" ] = exploder.script_firefx;
ent.v[ "firefxdelay" ] = exploder.script_firefxdelay;
ent.v[ "firefxsound" ] = exploder.script_firefxsound;
ent.v[ "earthquake" ] = exploder.script_earthquake;
ent.v[ "rumble" ] = exploder.script_rumble;
ent.v[ "damage" ] = exploder.script_damage;
ent.v[ "damage_radius" ] = exploder.script_radius;
ent.v[ "soundalias" ] = exploder.script_soundalias;
ent.v[ "repeat" ] = exploder.script_repeat;
ent.v[ "delay_min" ] = exploder.script_delay_min;
ent.v[ "delay_max" ] = exploder.script_delay_max;
ent.v[ "target" ] = exploder.target;
ent.v[ "ender" ] = exploder.script_ender;
ent.v[ "physics" ] = exploder.script_physics;
ent.v[ "type" ] = "exploder";
// ent.v[ "worldfx" ] = true;
if ( !IsDefined( exploder.script_fxid ) )
ent.v[ "fxid" ] = "No FX";
else
ent.v[ "fxid" ] = exploder.script_fxid;
ent.v [ "exploder" ] = exploder.script_exploder;
AssertEx( IsDefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" );
if ( IsDefined( level.createFXexploders ) )
{ // if we're using the optimized lookup, add it in the proper place
ary = level.createFXexploders[ ent.v[ "exploder" ] ];
if ( !IsDefined( ary ) )
ary = [];
ary[ ary.size ] = ent;
level.createFXexploders[ ent.v[ "exploder" ] ] = ary;
}
if ( !IsDefined( ent.v[ "delay" ] ) )
ent.v[ "delay" ] = 0;
if ( IsDefined( exploder.target ) )
{
get_ent = GetEntArray( ent.v[ "target" ], "targetname" )[ 0 ];
if ( IsDefined( get_ent ) )
{
org = get_ent.origin;
ent.v[ "angles" ] = VectorToAngles( org - ent.v[ "origin" ] );
}
else
{
get_ent = get_target_ent( ent.v[ "target" ] );
if ( IsDefined( get_ent ) )
{
org = get_ent.origin;
ent.v[ "angles" ] = VectorToAngles( org - ent.v[ "origin" ] );
}
}
}
// this basically determines if its a brush / model exploder or not
if ( !IsDefined( exploder.code_classname ) )
{
//I assume everything that doesn't have a code_classname is a struct that needs a script_modelname to make its way into the game
ent.model = exploder;
if ( IsDefined( ent.model.script_modelname ) )
{
PreCacheModel( ent.model.script_modelname );
}
}
else if ( exploder.code_classname == "script_brushmodel" || IsDefined( exploder.model ) )
{
ent.model = exploder;
ent.model.disconnect_paths = exploder.script_disconnectpaths;
}
if ( IsDefined( exploder.targetname ) && IsDefined( acceptableTargetnames[ exploder.targetname ] ) )
ent.v[ "exploder_type" ] = exploder.targetname;
else
ent.v[ "exploder_type" ] = "normal";
if ( IsDefined( exploder.masked_exploder ) )
{
ent.v[ "masked_exploder" ] = exploder.model;
ent.v[ "masked_exploder_spawnflags" ] = exploder.spawnflags;
ent.v[ "masked_exploder_script_disconnectpaths" ] = exploder.script_disconnectpaths;
exploder Delete();
}
ent common_scripts\_createfx::post_entity_creation_function();
}
}
setup_flag_exploders()
{
// createfx has to do 2 waittillframeends so we have to do 3 to make sure this comes after
// createfx is all done setting up. Who will raise the gambit to 4?
waittillframeend;
waittillframeend;
waittillframeend;
exploder_flags = [];
foreach ( ent in level.createFXent )
{
if ( ent.v[ "type" ] != "exploder" )
continue;
theFlag = ent.v[ "flag" ];
if ( !IsDefined( theFlag ) )
{
continue;
}
if ( theFlag == "nil" )
{
ent.v[ "flag" ] = undefined;
}
exploder_flags[ theFlag ] = true;
}
foreach ( msg, _ in exploder_flags )
{
thread exploder_flag_wait( msg );
}
}
exploder_flag_wait( msg )
{
if ( !flag_exist( msg ) )
flag_init( msg );
flag_wait( msg );
foreach ( ent in level.createFXent )
{
if ( ent.v[ "type" ] != "exploder" )
continue;
theFlag = ent.v[ "flag" ];
if ( !IsDefined( theFlag ) )
{
continue;
}
if ( theFlag != msg )
continue;
ent activate_individual_exploder();
}
}
exploder_model_is_damaged_model( ent )
{
return( IsDefined( ent.targetname ) ) && ( ent.targetname == "exploder" );
}
exploder_model_starts_hidden( ent )
{
return( ent.model == "fx" ) && ( ( !IsDefined( ent.targetname ) ) || ( ent.targetname != "exploderchunk" ) );
}
exploder_model_is_chunk( ent )
{
return( IsDefined( ent.targetname ) ) && ( ent.targetname == "exploderchunk" );
}
show_exploder_models_proc( num )
{
num += "";
//prof_begin( "hide_exploder" );
if ( IsDefined( level.createFXexploders ) )
{ // do optimized flavor if available
exploders = level.createFXexploders[ num ];
if ( IsDefined( exploders ) )
{
foreach ( ent in exploders )
{
//pre exploded geo. don't worry about deleted exploder geo..
if ( ! exploder_model_starts_hidden( ent.model )
&& ! exploder_model_is_damaged_model( ent.model )
&& !exploder_model_is_chunk( ent.model ) )
{
ent.model Show();
}
//exploded geo and should be shown
if ( IsDefined( ent.brush_shown ) )
ent.model Show();
}
}
}
else
{
for ( i = 0; i < level.createFXent.size; i++ )
{
ent = level.createFXent[ i ];
if ( !IsDefined( ent ) )
continue;
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != num )
continue;
if ( IsDefined( ent.model ) )
{
//pre exploded geo. don't worry about deleted exploder geo..
if ( ! exploder_model_starts_hidden( ent.model ) && ! exploder_model_is_damaged_model( ent.model ) && !exploder_model_is_chunk( ent.model ) )
{
ent.model Show();
}
//exploded geo and should be shown
if ( IsDefined( ent.brush_shown ) )
ent.model Show();
}
}
}
//prof_end( "hide_exploder" );
}
stop_exploder_proc( num )
{
num += "";
if ( IsDefined( level.createFXexploders ) )
{ // do optimized flavor if available
exploders = level.createFXexploders[ num ];
if ( IsDefined( exploders ) )
{
foreach ( ent in exploders )
{
if ( !IsDefined( ent.looper ) )
continue;
ent.looper Delete();
}
}
}
else
{
for ( i = 0; i < level.createFXent.size; i++ )
{
ent = level.createFXent[ i ];
if ( !IsDefined( ent ) )
continue;
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != num )
continue;
if ( !IsDefined( ent.looper ) )
continue;
ent.looper Delete();
}
}
}
get_exploder_array_proc( msg )
{
msg += "";
array = [];
if ( IsDefined( level.createFXexploders ) )
{ // do optimized flavor if available
exploders = level.createFXexploders[ msg ];
if ( IsDefined( exploders ) )
{
array = exploders;
}
}
else
{
foreach ( ent in level.createFXent )
{
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != msg )
continue;
array[ array.size ] = ent;
}
}
return array;
}
hide_exploder_models_proc( num )
{
num += "";
//prof_begin( "hide_exploder" );
if ( IsDefined( level.createFXexploders ) )
{ // do optimized flavor if available
exploders = level.createFXexploders[ num ];
if ( IsDefined( exploders ) )
{
foreach ( ent in exploders )
{
if ( IsDefined( ent.model ) )
ent.model Hide();
}
}
}
else
{
for ( i = 0; i < level.createFXent.size; i++ )
{
ent = level.createFXent[ i ];
if ( !IsDefined( ent ) )
continue;
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != num )
continue;
if ( IsDefined( ent.model ) )
ent.model Hide();
}
}
//prof_end( "hide_exploder" );
}
delete_exploder_proc( num )
{
num += "";
//prof_begin( "delete_exploder" );
if ( IsDefined( level.createFXexploders ) )
{ // do optimized flavor if available
exploders = level.createFXexploders[ num ];
if ( IsDefined( exploders ) )
{
foreach ( ent in exploders )
{
if ( IsDefined( ent.model ) )
ent.model Delete();
}
}
}
else
{
for ( i = 0; i < level.createFXent.size; i++ )
{
ent = level.createFXent[ i ];
if ( !IsDefined( ent ) )
continue;
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != num )
continue;
if ( IsDefined( ent.model ) )
ent.model Delete();
}
}
//ends trigger threads.
level notify( "killexplodertridgers" + num );
//prof_end( "delete_exploder" );
}
exploder_damage()
{
if ( IsDefined( self.v[ "delay" ] ) )
delay = self.v[ "delay" ];
else
delay = 0;
if ( IsDefined( self.v[ "damage_radius" ] ) )
radius = self.v[ "damage_radius" ];
else
radius = 128;
damage = self.v[ "damage" ];
origin = self.v[ "origin" ];
wait( delay );
if ( IsDefined( level.custom_radius_damage_for_exploders ) )
[[ level.custom_radius_damage_for_exploders ]]( origin, radius, damage );
else
// Range, max damage, min damage
RadiusDamage( origin, radius, damage, damage );
}
activate_individual_exploder_proc()
{
if ( IsDefined( self.v[ "firefx" ] ) )
self thread fire_effect();
if ( IsDefined( self.v[ "fxid" ] ) && self.v[ "fxid" ] != "No FX" )
self thread cannon_effect();
else
if ( IsDefined( self.v[ "soundalias" ] ) && self.v[ "soundalias" ] != "nil" )
self thread sound_effect();
if ( IsDefined( self.v[ "loopsound" ] ) && self.v[ "loopsound" ] != "nil" )
self thread effect_loopsound();
if ( IsDefined( self.v[ "damage" ] ) )
self thread exploder_damage();
if ( IsDefined( self.v[ "earthquake" ] ) )
self thread exploder_earthquake();
if ( IsDefined( self.v[ "rumble" ] ) )
self thread exploder_rumble();
if ( self.v[ "exploder_type" ] == "exploder" )
self thread brush_show();
else
if ( ( self.v[ "exploder_type" ] == "exploderchunk" ) || ( self.v[ "exploder_type" ] == "exploderchunk visible" ) )
self thread brush_throw();
else
self thread brush_delete();
}
brush_delete()
{
// if( ent.v[ "exploder_type" ] != "normal" && !isdefined( ent.v[ "fxid" ] ) && !isdefined( ent.v[ "soundalias" ] ) )
// if( !isdefined( ent.script_fxid ) )
num = self.v[ "exploder" ];
if ( IsDefined( self.v[ "delay" ] ) )
wait( self.v[ "delay" ] );
else
wait( 0.05 ); // so it disappears after the replacement appears
if ( !IsDefined( self.model ) )
return;
Assert( IsDefined( self.model ) );
if ( IsDefined( self.model.classname ) ) // script_struct support - Nate -- self is always a struct so it will never have a classname, using self.model instead -Carlos
if ( isSP() && ( self.model.spawnflags & 1 ) )
self.model call [[ level.connectPathsFunction ]]();
if ( level.createFX_enabled )
{
if ( IsDefined( self.exploded ) )
return;
self.exploded = true;
self.model Hide();
self.model NotSolid();
wait( 3 );
self.exploded = undefined;
self.model Show();
self.model Solid();
return;
}
if ( !IsDefined( self.v[ "fxid" ] ) || self.v[ "fxid" ] == "No FX" )
self.v[ "exploder" ] = undefined;
waittillframeend;// so it hides stuff after it shows the new stuff
// if ( IsDefined( self.classname ) ) // script_struct support nate --- self is always a struct so it will never have a classname, using self.model instead -Carlos
if ( IsDefined( self.model ) && IsDefined( self.model.classname ) )
{
self.model Delete();
}
}
brush_throw()
{
if ( IsDefined( self.v[ "delay" ] ) )
wait( self.v[ "delay" ] );
ent = undefined;
if ( IsDefined( self.v[ "target" ] ) )
ent = get_target_ent( self.v[ "target" ] );
if ( !IsDefined( ent ) )
{
self.model Delete();
return;
}
self.model Show();
if ( IsDefined( self.v[ "delay_post" ] ) )
wait( self.v[ "delay_post" ] );
startorg = self.v[ "origin" ];
startang = self.v[ "angles" ];
org = ent.origin;
temp_vec = ( org - self.v[ "origin" ] );
x = temp_vec[ 0 ];
y = temp_vec[ 1 ];
z = temp_vec[ 2 ];
physics = IsDefined( self.v[ "physics" ] );
if ( physics )
{
target = undefined;
if ( IsDefined( ent.target ) )
target = ent get_target_ent();
if ( !IsDefined( target ) )
{
contact_point = startorg; // no spin just push it.
throw_vec = ent.origin;
}
else
{
contact_point = ent.origin;
throw_vec = ( ( target.origin - ent.origin ) * self.v[ "physics" ] );
}
self.model PhysicsLaunchClient( contact_point, throw_vec );
return;
}
else
{
self.model RotateVelocity( ( x, y, z ), 12 );
self.model MoveGravity( ( x, y, z ), 12 );
}
if ( level.createFX_enabled )
{
if ( IsDefined( self.exploded ) )
return;
self.exploded = true;
wait( 3 );
self.exploded = undefined;
self.v[ "origin" ] = startorg;
self.v[ "angles" ] = startang;
self.model Hide();
return;
}
self.v[ "exploder" ] = undefined;
wait( 6 );
self.model Delete();
}
brush_show()
{
if ( IsDefined( self.v[ "delay" ] ) )
wait( self.v[ "delay" ] );
Assert( IsDefined( self.model ) );
if ( !IsDefined( self.model.script_modelname ) )
{
self.model Show();
self.model Solid();
}
else // script_structs don't pass in their .model value SO use script_modelname on them saves an entity.
{
model = self.model spawn_tag_origin();
if ( IsDefined( self.model.script_linkname ) )
model.script_linkname = self.model.script_linkname;
model SetModel( self.model.script_modelname );
model Show();
}
self.brush_shown = true; // used for hiding an exploder.
if ( isSP() && !IsDefined( self.model.script_modelname ) && ( self.model.spawnflags & 1 ) )
{
if ( !IsDefined( self.model.disconnect_paths ) )
self.model call [[ level.connectPathsFunction ]]();
else
self.model call [[ level.disconnectPathsFunction ]]();
}
if ( level.createFX_enabled )
{
if ( IsDefined( self.exploded ) )
return;
self.exploded = true;
wait( 3 );
self.exploded = undefined;
if ( !IsDefined( self.model.script_modelname ) )
{
self.model Hide();
self.model NotSolid();
}
}
}
exploder_rumble()
{
if ( !isSP() )
return;
self exploder_delay();
level.player PlayRumbleOnEntity( self.v[ "rumble" ] );
}
exploder_delay()
{
if ( !IsDefined( self.v[ "delay" ] ) )
self.v[ "delay" ] = 0;
min_delay = self.v[ "delay" ];
max_delay = self.v[ "delay" ] + 0.001; // cant randomfloatrange on the same #
if ( IsDefined( self.v[ "delay_min" ] ) )
min_delay = self.v[ "delay_min" ];
if ( IsDefined( self.v[ "delay_max" ] ) )
max_delay = self.v[ "delay_max" ];
if ( min_delay > 0 )
wait( RandomFloatRange( min_delay, max_delay ) );
}
effect_loopsound()
{
if ( IsDefined( self.loopsound_ent ) )
{
self.loopsound_ent Delete();
}
// save off this info in case we delete the effect
origin = self.v[ "origin" ];
alias = self.v[ "loopsound" ];
self exploder_delay();
self.loopsound_ent = play_loopsound_in_space( alias, origin );
}
sound_effect()
{
self effect_soundalias();
}
effect_soundalias()
{
// save off this info in case we delete the effect
origin = self.v[ "origin" ];
alias = self.v[ "soundalias" ];
self exploder_delay();
play_sound_in_space( alias, origin );
}
exploder_earthquake()
{
self exploder_delay();
do_earthquake( self.v[ "earthquake" ], self.v[ "origin" ] );
}
exploder_playSound()
{
if ( !IsDefined( self.v[ "soundalias" ] ) || self.v[ "soundalias" ] == "nil" )
return;
play_sound_in_space( self.v[ "soundalias" ], self.v[ "origin" ] );
}
fire_effect()
{
forward = self.v[ "forward" ];
up = self.v[ "up" ];
org = undefined;
firefxSound = self.v[ "firefxsound" ];
origin = self.v[ "origin" ];
firefx = self.v[ "firefx" ];
ender = self.v[ "ender" ];
if ( !IsDefined( ender ) )
ender = "createfx_effectStopper";
fireFxDelay = 0.5;
if ( IsDefined( self.v[ "firefxdelay" ] ) )
fireFxDelay = self.v[ "firefxdelay" ];
self exploder_delay();
if ( IsDefined( firefxSound ) )
loop_fx_sound( firefxSound, origin, 1, ender );
PlayFX( level._effect[ firefx ], self.v[ "origin" ], forward, up );
}
cannon_effect()
{
if ( IsDefined( self.v[ "repeat" ] ) )
{
thread exploder_playSound();
for ( i = 0; i < self.v[ "repeat" ]; i++ )
{
PlayFX( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
self exploder_delay();
}
return;
}
self exploder_delay();
if ( IsDefined( self.looper ) )
self.looper Delete();
self.looper = SpawnFx( getfx( self.v[ "fxid" ] ), self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
TriggerFX( self.looper );
exploder_playSound();
}
activate_exploder( num, players, startTime )
{
num += "";
//prof_begin( "activate_exploder" );
//here's a hook so you can know when a certain number of an exploder is going off
level notify( "exploding_" + num );
found_server_exploder = false;
if ( IsDefined( level.createFXexploders ) && !level.createFX_enabled )
{ // do optimized form if available
exploders = level.createFXexploders[ num ];
if ( IsDefined( exploders ) )
{
foreach ( ent in exploders )
{
ent activate_individual_exploder();
found_server_exploder = true;
}
}
}
else
{
for ( i = 0;i < level.createFXent.size;i++ )
{
ent = level.createFXent[ i ];
if ( !IsDefined( ent ) )
continue;
if ( ent.v[ "type" ] != "exploder" )
continue;
// make the exploder actually removed the array instead?
if ( !IsDefined( ent.v[ "exploder" ] ) )
continue;
if ( ent.v[ "exploder" ] + "" != num )
continue;
ent activate_individual_exploder();
found_server_exploder = true;
}
}
if ( !shouldRunServerSideEffects() && !found_server_exploder )
activate_clientside_exploder( num, players, startTime );
//prof_end( "activate_exploder" );
}
activate_clientside_exploder( exploderName, players, startTime )
{
if ( !is_valid_clientside_exploder_name( exploderName ) )
{
PrintLn( "^1ERROR: Exploder Index '" + exploderName + "' is not a valid exploder index >= 0" );
return;
}
exploder_num = Int( exploderName );
ActivateClientExploder( exploder_num, players, startTime );
}
is_valid_clientside_exploder_name( exploderName )
{
if ( !IsDefined( exploderName ) )
return false;
exploder_num = exploderName;
if ( IsString( exploderName ) )
{
exploder_num = Int( exploderName );
if ( exploder_num == 0 && exploderName != "0" )
return false;
}
return exploder_num >= 0;
}
shouldRunServerSideEffects()
{
if ( isSP() )
return true;
if ( !IsDefined( level.createFX_enabled ) )
level.createFX_enabled = ( GetDvar( "createfx" ) != "" );
if ( level.createFX_enabled )
return true;
else
return GetDvar( "clientSideEffects" ) != "1";
}
exploder_before_load( num, players, startTime )
{
// gotta wait twice because the createfx_init function waits once then inits all exploders. This guarentees
// that if an exploder is run on the first frame, it happens after the fx are init.
waittillframeend;
waittillframeend;
activate_exploder( num, players, startTime );
}
exploder_after_load( num, players, startTime )
{
activate_exploder( num, players, startTime );
}

871
common_scripts/_fx.gsc Normal file
View File

@ -0,0 +1,871 @@
#include common_scripts\utility;
#include common_scripts\_createfx;
CONST_MAX_SP_CREATEFX = 1500;
CONST_MAX_SP_CREATESOUND = 384;
initFX()
{
if ( !isdefined( level.func ) )
level.func = [];
if ( !isdefined( level.func[ "create_triggerfx" ] ) )
level.func[ "create_triggerfx" ] = ::create_triggerfx;
if ( !IsDefined( level._fx ) )
level._fx = SpawnStruct();
create_lock( "createfx_looper", 20 );
level.fxfireloopmod = 1;
// wrapper for the exploder function so we dont have to use flags and do ifs/waittills on every exploder call
level._fx.exploderFunction = common_scripts\_exploder::exploder_before_load;
waittillframeend;// Wait one frame so the effects get setup by the maps fx thread
waittillframeend;// Wait another frame so effects can be loaded based on start functions. Without this FX are initialiazed before they are defined by start functions.
level._fx.exploderFunction = common_scripts\_exploder::exploder_after_load;
level._fx.server_culled_sounds = false;
if ( GetDvarInt( "serverCulledSounds" ) == 1 )
level._fx.server_culled_sounds = true;
if ( level.createFX_enabled )
level._fx.server_culled_sounds = false;
/#
SetDevDvarIfUninitialized( "scr_map_exploder_dump", 0 );
SetDevDvarIfUninitialized( "createfx_removedupes", 0 );
if ( GetDvarInt( "r_reflectionProbeGenerate" ) == 1 )
level._fx.server_culled_sounds = true;
#/
// Give createfx_common time to delete triggers to free up entity slots.
if ( level.createFX_enabled )
{
level waittill( "createfx_common_done" );
}
/#
remove_dupes();
#/
for ( i = 0; i < level.createFXent.size; i++ )
{
ent = level.createFXent[ i ];
ent set_forward_and_up_vectors();
switch ( ent.v[ "type" ] )
{
case "loopfx":
ent thread loopfxthread();
break;
case "oneshotfx":
ent thread oneshotfxthread();
break;
case "soundfx":
ent thread create_loopsound();
break;
case "soundfx_interval":
ent thread create_interval_sound();
break;
case "reactive_fx":
ent add_reactive_fx();
break;
}
}
check_createfx_limit();
}
remove_dupes()
{
/#
if ( GetDvarInt( "createfx_removedupes" ) == 0 )
return;
new_ents = [];
for ( i = 0; i < level.createFXent.size; i++ )
{
add_ent = true;
i_ent = level.createFXent[ i ];
for ( j = i + 1; j < level.createFXent.size; j++ )
{
j_ent = level.createFXent[ j ];
if ( j_ent.v[ "type" ] == i_ent.v[ "type" ] )
{
if ( j_ent.v[ "origin" ] == i_ent.v[ "origin" ] )
{
println( "^3--REMOVING DUPE'D " + j_ent.v[ "type" ] + " AT " + j_ent.v[ "origin" ] );
add_ent = false;
}
}
}
if ( add_ent )
new_ents[ new_ents.size ] = i_ent;
}
level.createFXent = new_ents;
#/
}
check_createfx_limit()
{
/#
if ( !isSP() )
{
return;
}
fx_count = 0;
sound_count = 0;
foreach ( ent in level.createFXent )
{
if ( is_createfx_type( ent, "fx" ) )
fx_count++;
else if ( is_createfx_type( ent, "sound" ) )
sound_count++;
}
println( "^5Total CreateFX FX Ents: " + fx_count );
println( "^5Total CreateFX SOUND Ents: " + sound_count );
check_limit_type( "fx", fx_count );
check_limit_type( "sound", sound_count );
#/
}
check_limit_type( type, count )
{
/#
limit = undefined;
if ( type == "fx" )
{
limit = CONST_MAX_SP_CREATEFX;
}
else if ( type == "sound" )
{
limit = CONST_MAX_SP_CREATESOUND;
}
if ( count > limit )
AssertMsg( "CREATEFX: You have too many " + type + " createFX ents. You need to reduce the amount.\nYou have " + count + " and the limit is " + limit );
#/
}
print_org( fxcommand, fxId, fxPos, waittime )
{
if ( GetDvar( "debug" ) == "1" )
{
println( "{" );
println( "\"origin\" \"" + fxPos[ 0 ] + " " + fxPos[ 1 ] + " " + fxPos[ 2 ] + "\"" );
println( "\"classname\" \"script_model\"" );
println( "\"model\" \"fx\"" );
println( "\"script_fxcommand\" \"" + fxcommand + "\"" );
println( "\"script_fxid\" \"" + fxId + "\"" );
println( "\"script_delay\" \"" + waittime + "\"" );
println( "}" );
}
}
OneShotfx( fxId, fxPos, waittime, fxPos2 )
{
// level thread print_org ("OneShotfx", fxId, fxPos, waittime);
// level thread OneShotfxthread (fxId, fxPos, waittime, fxPos2);
}
exploderfx( num, fxId, fxPos, waittime, fxPos2, fireFx, fireFxDelay, fireFxSound, fxSound, fxQuake, fxDamage, soundalias, repeat, delay_min, delay_max, damage_radius, fireFxTimeout, exploder_group )
{
if ( 1 )
{
ent = createExploder( fxId );
ent.v[ "origin" ] = fxPos;
ent.v[ "angles" ] = ( 0, 0, 0 );
if ( isdefined( fxPos2 ) )
ent.v[ "angles" ] = vectortoangles( fxPos2 - fxPos );
ent.v[ "delay" ] = waittime;
ent.v[ "exploder" ] = num;
if (isdefined(level.createFXexploders))
{ // if we're using the optimized lookup, add it in the proper place
ary = level.createFXexploders[ ent.v[ "exploder" ] ];
if (!isdefined(ary))
ary = [];
ary[ary.size] = ent;
level.createFXexploders[ ent.v[ "exploder" ] ] = ary;
}
// deprecated
return;
}
fx = spawn( "script_origin", ( 0, 0, 0 ) );
// println ("total ", getentarray ("script_origin","classname").size);
fx.origin = fxPos;
fx.angles = vectortoangles( fxPos2 - fxPos );
// fx.targetname = "exploder";
fx.script_exploder = num;
fx.script_fxid = fxId;
fx.script_delay = waittime;
fx.script_firefx = fireFx;
fx.script_firefxdelay = ( fireFxDelay );// for awhile the script exported strings for this value so we cast it to float
fx.script_firefxsound = fireFxSound;
fx.script_sound = fxSound;
fx.script_earthquake = fxQuake;
fx.script_damage = ( fxDamage );
fx.script_radius = ( damage_radius );
fx.script_soundalias = soundalias;
fx.script_firefxtimeout = ( fireFxTimeout );
fx.script_repeat = ( repeat );
fx.script_delay_min = ( delay_min );
fx.script_delay_max = ( delay_max );
fx.script_exploder_group = exploder_group;
forward = anglestoforward( fx.angles );
forward *= ( 150 );
fx.targetPos = fxPos + forward;
if ( !isdefined( level._script_exploders ) )
level._script_exploders = [];
level._script_exploders[ level._script_exploders.size ] = fx;
}
/*
loopfxRotate(fxId, fxPos, waittime, angle, fxStart, fxStop, timeout)
{
level thread print_org ("loopfx", fxId, fxPos, waittime);
level thread loopfxthread (fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout);
}
*/
loopfx( fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout )
{
println( "Loopfx is deprecated!" );
ent = createLoopEffect( fxId );
ent.v[ "origin" ] = fxPos;
ent.v[ "angles" ] = ( 0, 0, 0 );
if ( isdefined( fxPos2 ) )
ent.v[ "angles" ] = vectortoangles( fxPos2 - fxPos );
ent.v[ "delay" ] = waittime;
}
/*
loopfx(fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout)
{
level thread print_org ("loopfx", fxId, fxPos, waittime);
level thread loopfxthread (fxId, fxPos, waittime, fxPos2, fxStart, fxStop, timeout);
}
*/
create_looper()
{
//assert (isdefined(self.looper));
self.looper = playLoopedFx( level._effect[ self.v[ "fxid" ] ], self.v[ "delay" ], self.v[ "origin" ], 0, self.v[ "forward" ], self.v[ "up" ] );
create_loopsound();
}
create_loopsound()
{
self notify( "stop_loop" );
if ( !IsDefined( self.v[ "soundalias" ] ) )
return;
if ( self.v[ "soundalias" ] == "nil" )
return;
/#
if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" )
return;
#/
culled = false;
end_on = undefined;
if ( isdefined( self.v[ "stopable" ] ) && self.v[ "stopable" ] )
{
if ( IsDefined( self.looper ) )
end_on = "death";
else
end_on = "stop_loop";
}
else
{
if ( level._fx.server_culled_sounds && IsDefined( self.v[ "server_culled" ] ) )
culled = self.v[ "server_culled" ];
}
ent = self;
if ( IsDefined( self.looper ) )
ent = self.looper;
createfx_ent = undefined;
if ( level.createFX_enabled )
createfx_ent = self;
ent loop_fx_sound_with_angles( self.v[ "soundalias" ], self.v[ "origin" ], self.v[ "angles" ], culled, end_on, createfx_ent );
}
create_interval_sound()
{
self notify( "stop_loop" );
if ( !IsDefined( self.v[ "soundalias" ] ) )
return;
if ( self.v[ "soundalias" ] == "nil" )
return;
ender = undefined;
runner = self;
/#
if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" )
return;
#/
if( ( IsDefined( self.v[ "stopable" ] ) && self.v[ "stopable" ] ) || level.createFX_enabled )
{
if ( IsDefined( self.looper ) )
{
runner = self.looper;
ender = "death";
}
else
ender = "stop_loop";
}
runner thread loop_fx_sound_interval_with_angles( self.v[ "soundalias" ], self.v[ "origin" ], self.v[ "angles" ], ender, undefined, self.v[ "delay_min" ], self.v[ "delay_max" ] );
}
loopfxthread()
{
waitframe();
// println ( "fx testing running Id: ", fxId );
// if ((isdefined (level.scr_sound)) && (isdefined (level.scr_sound[fxId])))
// loopSound(level.scr_sound[fxId], fxPos);
if ( isdefined( self.fxStart ) )
level waittill( "start fx" + self.fxStart );
while ( 1 )
{
/*
if (isdefined (ent.org2))
{
fxAngle = vectorNormalize (ent.org2 - ent.org);
looper = playLoopedFx( level._effect[fxId], ent.delay, ent.org, 0, fxAngle );
}
else
looper = playLoopedFx( level._effect[fxId], ent.delay, ent.org, 0 );
*/
create_looper();
if ( isdefined( self.timeout ) )
thread loopfxStop( self.timeout );
if ( isdefined( self.fxStop ) )
level waittill( "stop fx" + self.fxStop );
else
return;
if ( isdefined( self.looper ) )
self.looper delete();
if ( isdefined( self.fxStart ) )
level waittill( "start fx" + self.fxStart );
else
return;
}
}
loopfxChangeID( ent )
{
self endon( "death" );
ent waittill( "effect id changed", change );
}
loopfxChangeOrg( ent )
{
self endon( "death" );
for ( ;; )
{
ent waittill( "effect org changed", change );
self.origin = change;
}
}
loopfxChangeDelay( ent )
{
self endon( "death" );
ent waittill( "effect delay changed", change );
}
loopfxDeletion( ent )
{
self endon( "death" );
ent waittill( "effect deleted" );
self delete();
}
loopfxStop( timeout )
{
self endon( "death" );
wait( timeout );
self.looper delete();
}
loopSound( sound, Pos, waittime )
{
// level thread print_org ("loopSound", sound, Pos, waittime);
level thread loopSoundthread( sound, Pos, waittime );
}
loopSoundthread( sound, pos, waittime )
{
org = spawn( "script_origin", ( pos ) );
org.origin = pos;
// println ("hello1 ", org.origin, sound);
org playLoopSound( sound );
}
gunfireloopfx( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax )
{
thread gunfireloopfxthread( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax );
}
gunfireloopfxthread( fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax )
{
level endon( "stop all gunfireloopfx" );
waitframe();
if ( betweenSetsMax < betweenSetsMin )
{
temp = betweenSetsMax;
betweenSetsMax = betweenSetsMin;
betweenSetsMin = temp;
}
betweenSetsBase = betweenSetsMin;
betweenSetsRange = betweenSetsMax - betweenSetsMin;
if ( shotdelayMax < shotdelayMin )
{
temp = shotdelayMax;
shotdelayMax = shotdelayMin;
shotdelayMin = temp;
}
shotdelayBase = shotdelayMin;
shotdelayRange = shotdelayMax - shotdelayMin;
if ( shotsMax < shotsMin )
{
temp = shotsMax;
shotsMax = shotsMin;
shotsMin = temp;
}
shotsBase = shotsMin;
shotsRange = shotsMax - shotsMin;
fxEnt = spawnFx( level._effect[ fxId ], fxPos );
if ( !level.createFX_enabled )
fxEnt willNeverChange();
for ( ;; )
{
shotnum = shotsBase + randomint( shotsRange );
for ( i = 0;i < shotnum;i++ )
{
triggerFx( fxEnt );
wait( shotdelayBase + randomfloat( shotdelayRange ) );
}
wait( betweenSetsBase + randomfloat( betweenSetsRange ) );
}
}
gunfireloopfxVec( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax )
{
thread gunfireloopfxVecthread( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax );
}
gunfireloopfxVecthread( fxId, fxPos, fxPos2, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax )
{
level endon( "stop all gunfireloopfx" );
waitframe();
if ( betweenSetsMax < betweenSetsMin )
{
temp = betweenSetsMax;
betweenSetsMax = betweenSetsMin;
betweenSetsMin = temp;
}
betweenSetsBase = betweenSetsMin;
betweenSetsRange = betweenSetsMax - betweenSetsMin;
if ( shotdelayMax < shotdelayMin )
{
temp = shotdelayMax;
shotdelayMax = shotdelayMin;
shotdelayMin = temp;
}
shotdelayBase = shotdelayMin;
shotdelayRange = shotdelayMax - shotdelayMin;
if ( shotsMax < shotsMin )
{
temp = shotsMax;
shotsMax = shotsMin;
shotsMin = temp;
}
shotsBase = shotsMin;
shotsRange = shotsMax - shotsMin;
fxPos2 = vectornormalize( fxPos2 - fxPos );
fxEnt = spawnFx( level._effect[ fxId ], fxPos, fxPos2 );
if ( !level.createFX_enabled )
fxEnt willNeverChange();
for ( ;; )
{
shotnum = shotsBase + randomint( shotsRange );
for ( i = 0;i < int( shotnum / level.fxfireloopmod );i++ )
{
triggerFx( fxEnt );
delay = ( ( shotdelayBase + randomfloat( shotdelayRange ) ) * level.fxfireloopmod );
if ( delay < .05 )
delay = .05;
wait delay;
}
wait( shotdelayBase + randomfloat( shotdelayRange ) );
wait( betweenSetsBase + randomfloat( betweenSetsRange ) );
}
}
setfireloopmod( value )
{
level.fxfireloopmod = 1 / value;
}
setup_fx()
{
if ( ( !isdefined( self.script_fxid ) ) || ( !isdefined( self.script_fxcommand ) ) || ( !isdefined( self.script_delay ) ) )
{
// println (self.script_fxid);
// println (self.script_fxcommand);
// println (self.script_delay);
// println ("Effect at origin ", self.origin," doesn't have script_fxid/script_fxcommand/script_delay");
// self delete();
return;
}
// println ("^a Command:", self.script_fxcommand, " Effect:", self.script_fxID, " Delay:", self.script_delay, " ", self.origin);
if ( isdefined( self.model ) )
if ( self.model == "toilet" )
{
self thread burnville_paratrooper_hack();
return;
}
org = undefined;
if ( isdefined( self.target ) )
{
ent = getent( self.target, "targetname" );
if ( isdefined( ent ) )
org = ent.origin;
}
fxStart = undefined;
if ( isdefined( self.script_fxstart ) )
fxStart = self.script_fxstart;
fxStop = undefined;
if ( isdefined( self.script_fxstop ) )
fxStop = self.script_fxstop;
if ( self.script_fxcommand == "OneShotfx" )
OneShotfx( self.script_fxId, self.origin, self.script_delay, org );
if ( self.script_fxcommand == "loopfx" )
loopfx( self.script_fxId, self.origin, self.script_delay, org, fxStart, fxStop );
if ( self.script_fxcommand == "loopsound" )
loopsound( self.script_fxId, self.origin, self.script_delay );
self delete();
}
burnville_paratrooper_hack()
{
normal = ( 0, 0, self.angles[ 1 ] );
// println ("z: paratrooper fx hack: ", normal);
id = level._effect[ self.script_fxId ];
origin = self.origin;
// if (isdefined (self.script_delay))
// wait (self.script_delay);
wait 1;
level thread burnville_paratrooper_hack_loop( normal, origin, id );
self delete();
}
burnville_paratrooper_hack_loop( normal, origin, id )
{
while ( 1 )
{
// iprintln ("z: playing paratrooper fx", origin);
playfx( id, origin );
wait( 30 + randomfloat( 40 ) );
}
}
create_triggerfx()
{
//assert (isdefined(self.looper));
if( ! verify_effects_assignment( self.v[ "fxid" ] ) )
return;
self.looper = spawnFx( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
triggerFx( self.looper, self.v[ "delay" ] );
if ( !level.createFX_enabled )
self.looper willNeverChange();
create_loopsound();
}
verify_effects_assignment( effectID )
{
if( isdefined ( level._effect[ effectID ] ) )
return true;
if( ! isdefined( level._missing_FX ) )
level._missing_FX = [];
level._missing_FX[ self.v[ "fxid" ] ] = effectID;
verify_effects_assignment_print( effectID );
return false;
}
verify_effects_assignment_print( effectID )
{
level notify ( "verify_effects_assignment_print" );
level endon ( "verify_effects_assignment_print" );
wait .05; //allow errors on the same frame to que up before printing
println("Error:");
println("Error:**********MISSING EFFECTS IDS**********");
keys = getarraykeys( level._missing_FX );
foreach( key in keys )
{
println( "Error: Missing Effects ID assignment for: "+ key );
}
println("Error:");
assertmsg( "Missing Effects ID assignments ( see console )" );
}
OneShotfxthread()
{
wait(0.05);
if ( self.v[ "delay" ] > 0 )
wait self.v[ "delay" ];
[[ level.func[ "create_triggerfx" ] ]]();
}
//---------------------------------------------------------
// Reactive Section
//---------------------------------------------------------
CONST_MAX_REACTIVE_SOUND_ENTS = 4;
CONST_NEXT_PLAY_TIME = 3000;
add_reactive_fx()
{
// MP should not start this thread in release
if ( !isSP() && GetDVar( "createfx" ) == "" )
{
return;
}
if ( !IsDefined( level._fx.reactive_thread ) )
{
level._fx.reactive_thread = true;
level thread reactive_fx_thread();
}
if ( !IsDefined( level._fx.reactive_fx_ents ) )
{
level._fx.reactive_fx_ents = [];
}
level._fx.reactive_fx_ents[ level._fx.reactive_fx_ents.size ] = self;
self.next_reactive_time = 3000;
}
reactive_fx_thread()
{
if ( !isSp() )
{
if ( GetDvar( "createfx" ) == "on" )
{
// wait till the player spawns and createfxlogic starts before continuing.
flag_wait( "createfx_started" );
}
}
// TODO: Switch to using level notify instead
// HOWEVER!!! we will need the trigger_radius for when we are in CREATEFX mode for MP only!!!
// use level.mp_createfx condition
// trigger = Spawn( "trigger_radius", level.player.origin, 0, 5000, 5000 );
// trigger SetCanDamage( true );
// trigger EnableLinkTo();
// trigger LinkTo( level.player );
level._fx.reactive_sound_ents = [];
explosion_radius = 256;
while ( 1 )
{
// trigger waittill( "damage", dmg, attacker, dir_vec, point, type );
level waittill( "code_damageradius", attacker, explosion_radius, point, weapon_name );
ents = sort_reactive_ents( point, explosion_radius );
foreach ( i, ent in ents )
ent thread play_reactive_fx( i );
}
}
vector2d( vec )
{
return ( vec[ 0 ], vec[ 1 ], 0 );
}
sort_reactive_ents( point, explosion_radius )
{
closest = [];
time = GetTime();
foreach ( ent in level._fx.reactive_fx_ents )
{
if ( ent.next_reactive_time > time )
continue;
radius_squared = ent.v[ "reactive_radius" ] + explosion_radius;
radius_squared *= radius_squared;
if ( DistanceSquared( point, ent.v[ "origin" ] ) < radius_squared )
{
closest[ closest.size ] = ent;
}
}
foreach ( ent in closest )
{
playerToEnt = vector2d( ent.v[ "origin" ] - level.player.origin );
playerToPoint = vector2d( point - level.player.origin );
vec1 = VectorNormalize( playerToEnt );
vec2 = VectorNormalize( playerToPoint );
ent.dot = VectorDot( vec1, vec2 );
}
// Sort from lowest dot to greatest
for ( i = 0; i < closest.size - 1; i++ )
{
for ( j = i + 1; j < closest.size; j++ )
{
if ( closest[ i ].dot > closest[ j ].dot )
{
temp = closest[ i ];
closest[ i ] = closest[ j ];
closest[ j ] = temp;
}
}
}
// remove the .origin and .dot since we're done with sortbydistance()
foreach ( ent in closest )
{
ent.origin = undefined;
ent.dot = undefined;
}
// Make sure we only have 4
for ( i = CONST_MAX_REACTIVE_SOUND_ENTS; i < closest.size; i++ )
{
closest[ i ] = undefined;
}
return closest;
}
play_reactive_fx( num )
{
sound_ent = get_reactive_sound_ent();
if ( !IsDefined( sound_ent ) )
return;
/#
self.is_playing = true;
#/
self.next_reactive_time = GeTTime() + CONST_NEXT_PLAY_TIME;
sound_ent.origin = self.v[ "origin" ];
sound_ent.is_playing = true;
wait( num * RandomFloatRange( 0.05, 0.1 ) );
if ( isSP() )
{
sound_ent PlaySound( self.v[ "soundalias" ], "sounddone" );
sound_ent waittill( "sounddone" );
}
else
{
sound_ent PlaySound( self.v[ "soundalias" ] );
wait( 2 );
}
// wait for sounddone to be removed compeletely
// bug in prague port to iw6 where in the same frame this got called again after the sounddone notify
// odd thing, even 0.05 doesn't work. Code should fix this!
wait( 0.1 );
sound_ent.is_playing = false;
/#
self.is_playing = undefined;
#/
}
get_reactive_sound_ent()
{
foreach ( ent in level._fx.reactive_sound_ents )
{
if ( !ent.is_playing )
return ent;
}
if ( level._fx.reactive_sound_ents.size < CONST_MAX_REACTIVE_SOUND_ENTS )
{
ent = Spawn( "script_origin", ( 0, 0, 0 ) );
ent.is_playing = false;
level._fx.reactive_sound_ents[ level._fx.reactive_sound_ents.size ] = ent;
return ent;
}
return undefined;
}

1104
common_scripts/_painter.gsc Normal file

File diff suppressed because it is too large Load Diff

395
common_scripts/_pipes.gsc Normal file
View File

@ -0,0 +1,395 @@
#include common_scripts\utility;
//////////////////////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////////////////////
level_limit_pipe_fx = 8;
max_fires_from_entity = 4;
level_pipe_fx_chance = 33;
//////////////////////////////////////////////////////////////////////////////
// LOGIC //
//////////////////////////////////////////////////////////////////////////////
main()
{
if ( IsDefined( level.pipes_init ) )
return;
level.pipes_init = true;
//level._pipe_fx_time = 25; //handle this individually for different pipe types
pipes = GetEntArray( "pipe_shootable", "targetname" );
if ( !pipes.size )
return;
level._pipes = SpawnStruct();
level._pipes.num_pipe_fx = 0;
pipes thread precacheFX();
pipes thread methodsInit();
thread post_load( pipes );
}
post_load( pipes )
{
waittillframeend;// insure that structs are initialized
if( level.createFX_enabled )
return;
array_thread( pipes, ::pipesetup );
}
pipesetup()
{
self SetCanDamage( true );
self SetCanRadiusDamage( false ); // optimization
self.pipe_fx_array = [];
node = undefined;
if ( IsDefined( self.target ) )
{
node = getstruct( self.target, "targetname" );
self.A = node.origin;
vec = AnglesToForward( node.angles );
vec = ( vec * 128 );
self.B = self.A + vec;
}
else
{
vec = AnglesToForward( self.angles );
vec1 = ( vec * 64 );
self.A = self.origin + vec1;
vec1 = ( vec * -64 );
self.B = self.origin + vec1;
}
self thread pipe_wait_loop();
}
pipe_wait_loop()
{
P = ( 0, 0, 0 );// just to initialize P as a vector
hasTakenDamage = false;
remaining = max_fires_from_entity;
while ( 1 )
{
self waittill( "damage", damage, attacker, direction_vec, P, type );
// random so we don't get so many fx, but the very first time is guarenteed
if ( hasTakenDamage )
{
if ( randomint( 100 ) <= level_pipe_fx_chance )
continue;
}
hasTakenDamage = true;
result = self pipe_logic( direction_vec, P, type, attacker );
if ( result )
remaining--;
if ( remaining <= 0 )
break;
}
self SetCanDamage( false );
}
pipe_logic( direction_vec, P, type, damageOwner )
{
if ( level._pipes.num_pipe_fx > level_limit_pipe_fx )
return false;
if ( !isDefined( level._pipes._pipe_methods[ type ] ) )
P = self pipe_calc_nofx( P, type );
else
P = self [[ level._pipes._pipe_methods[ type ] ]]( P, type );
if ( !isdefined( P ) )
return false;
if ( IsDefined( damageOwner.classname ) && damageOwner.classname == "worldspawn" )
return false;
foreach ( value in self.pipe_fx_array )
{
if ( DistanceSquared( P, value.origin ) < 25 )
return false;
}
//calculate the vector derived from the center line of our pipe and the point of damage
// generate a vector from the attacker's eye to the impact point (AI) or origin to impact point (non-AI)
E = undefined;
if( IsAI( damageOwner ))
E = damageOwner GetEye();
else
E = damageOwner.origin;
temp_vec = P - E;
// Extend the vector (this is to ensure it intersects the damaged entity, tracing to the point itself generated new points which were slightly off and bad normals) and return a trace
trace = BulletTrace ( E, E + 1.5 * temp_vec, false, damageOwner, false );
if ( isdefined ( trace [ "normal" ] ) && isdefined ( trace [ "entity" ] ) && trace ["entity"] == self )
{
vec = trace[ "normal" ];
// Use the surface normal of the impact point to generate the angles for the burst effect
self thread pipefx( P, vec, damageOwner );
return true;
}
return false;
}
pipefx( P, vec, damageOwner )
{
time = level._pipes.fx_time[ self.script_noteworthy ] ;
fx_time = level._pipes._pipe_fx_time[ self.script_noteworthy ] ;
intervals = Int( fx_time / time );// loops for 25 seconds
intervals_end = 30;
hitsnd = level._pipes._sound[ self.script_noteworthy + "_hit" ];
loopsnd = level._pipes._sound[ self.script_noteworthy + "_loop" ];
endsnd = level._pipes._sound[ self.script_noteworthy + "_end" ];
snd = Spawn( "script_origin", P );
// snd Hide();
snd PlaySound( hitsnd );
snd PlayLoopSound( loopsnd );
self.pipe_fx_array[ self.pipe_fx_array.size ] = snd;
if ( isSP() || self.script_noteworthy != "steam" )
self thread pipe_damage( P, vec, damageOwner, snd );
//if it is a barrel, rotate the emitter angle over time
if( self.script_noteworthy == "oil_leak" )
{
efx_rot = Spawn( "script_model", P );
efx_rot SetModel( "tag_origin" );
efx_rot.angles = VectorToAngles( vec );
PlayFXOnTag( level._pipes._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
level._pipes.num_pipe_fx++;
efx_rot RotatePitch( 90, time, 1, 1 );
wait time;
StopFXOnTag( level._pipes._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
intervals--;
}
else
{
//do it once without checking for newer fx being played ( we're the newest )
PlayFX( level._pipes._effect[ self.script_noteworthy ], P, vec );
level._pipes.num_pipe_fx++;
wait time;
intervals--;
}
//now check for other fx and rest of intervals
while ( level._pipes.num_pipe_fx <= level_limit_pipe_fx && intervals > 0 )
{
if( self.script_noteworthy == "oil_leak" )
{
efx_rot = Spawn( "script_model", P );
efx_rot SetModel( "tag_origin" );
efx_rot.angles = VectorToAngles( vec );
PlayFXOnTag( level._pipes._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
level._pipes.num_pipe_fx++;
efx_rot RotatePitch( 90, time, 1, 1 );
wait time;
StopFXOnTag( level._pipes._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
}
else
{
//do it once without checking for newer fx being played ( we're the newest )
PlayFX( level._pipes._effect[ self.script_noteworthy ], P, vec );
wait time;
intervals--;
}
}
snd PlaySound( endsnd );
wait( .5 );
snd StopLoopSound( loopsnd );
snd Delete();
self.pipe_fx_array = array_removeUndefined( self.pipe_fx_array );
level._pipes.num_pipe_fx--;
}
pipe_damage( P, vec, damageOwner, fx )
{
if ( !allow_pipe_damage() )
return;
fx endon( "death" );
origin = fx.origin + ( VectorNormalize( vec ) * 40 );
dmg = level._pipes._dmg[ self.script_noteworthy ];
while ( 1 )
{
// do not pass damage owner if they have disconnected before the barrels explode.. the barrels?
if ( !isdefined( self.damageOwner ) )
{
// MOD_TRIGGER_HURT so they dont do dirt on the player's screen
self RadiusDamage( origin, 36, dmg, dmg * 0.75, undefined, "MOD_TRIGGER_HURT" );
}
else
{
// MOD_TRIGGER_HURT so they dont do dirt on the player's screen
self RadiusDamage( origin, 36, dmg, dmg * 0.75, damageOwner, "MOD_TRIGGER_HURT" );
}
wait( 0.4 );
}
}
allow_pipe_damage()
{
if( !isSP() )
return false;
if ( !isDefined( level.pipesDamage ) )
return true;
return ( level.pipesDamage );
}
//////////////////////////////////////////////////////////////////////////////
// CALCULATIONS / SETUP //
//////////////////////////////////////////////////////////////////////////////
methodsInit()
{
level._pipes._pipe_methods = [];
level._pipes._pipe_methods[ "MOD_UNKNOWN" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_PISTOL_BULLET" ] = ::pipe_calc_ballistic;
level._pipes._pipe_methods[ "MOD_RIFLE_BULLET" ] = ::pipe_calc_ballistic;
level._pipes._pipe_methods[ "MOD_GRENADE" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_GRENADE_SPLASH" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_PROJECTILE" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_PROJECTILE_SPLASH" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_TRIGGER_HURT" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_EXPLOSIVE" ] = ::pipe_calc_splash;
level._pipes._pipe_methods[ "MOD_EXPLOSIVE_BULLET" ] = ::pipe_calc_splash;
}
pipe_calc_ballistic( P, type )
{
return P;
}
pipe_calc_splash( P, type )
{
vec = VectorNormalize( VectorFromLineToPoint( self.A, self.B, P ) );
P = PointOnSegmentNearestToPoint( self.A, self.B, P );
return( P + ( vec * 4 ) );
}
pipe_calc_nofx( P, type )
{
return undefined;
}
precacheFX()
{
steam = false;
fire = false;
steam_small = false;
oil_leak = false;
oil_cap = false;
foreach ( value in self )
{
if ( value.script_noteworthy == "water" )
value.script_noteworthy = "steam";
if ( value.script_noteworthy == "steam" )
{
value willNeverChange();
steam = true;
}
else if ( value.script_noteworthy == "fire" )
{
value willNeverChange();
fire = true;
}
else if ( value.script_noteworthy == "steam_small" )
{
value willNeverChange();
steam_small = true;
}
else if ( value.script_noteworthy == "oil_leak" )
{
value willNeverChange();
oil_leak = true;
}
else if ( value.script_noteworthy == "oil_cap" )
{
value willNeverChange();
oil_cap = true;
}
else
{
println( "Unknown 'pipe_shootable' script_noteworthy type '%s'\n", value.script_noteworthy );
}
}
if ( steam )
{
level._pipes._effect[ "steam" ] = LoadFX( "fx/impacts/pipe_steam" );
level._pipes._sound[ "steam_hit" ] = "mtl_steam_pipe_hit";
level._pipes._sound[ "steam_loop" ] = "mtl_steam_pipe_hiss_loop";
level._pipes._sound[ "steam_end" ] = "mtl_steam_pipe_hiss_loop_end";
level._pipes.fx_time[ "steam" ] = 3;
level._pipes._dmg[ "steam" ] = 5;
level._pipes._pipe_fx_time["steam"] = 25;
}
if ( steam_small )
{
level._pipes._effect[ "steam_small" ] = LoadFX( "fx/impacts/pipe_steam_small" );
level._pipes._sound[ "steam_small_hit" ] = "mtl_steam_pipe_hit";
level._pipes._sound[ "steam_small_loop" ] = "mtl_steam_pipe_hiss_loop";
level._pipes._sound[ "steam_small_end" ] = "mtl_steam_pipe_hiss_loop_end";
level._pipes.fx_time[ "steam_small" ] = 3;
level._pipes._dmg[ "steam_small" ] = 5;
level._pipes._pipe_fx_time["steam_small"] = 25;
}
if ( fire )
{
level._pipes._effect[ "fire" ] = LoadFX( "fx/impacts/pipe_fire" );
level._pipes._sound[ "fire_hit" ] = "mtl_gas_pipe_hit";
level._pipes._sound[ "fire_loop" ] = "mtl_gas_pipe_flame_loop";
level._pipes._sound[ "fire_end" ] = "mtl_gas_pipe_flame_end";
level._pipes.fx_time[ "fire" ] = 3;
level._pipes._dmg[ "fire" ] = 5;
level._pipes._pipe_fx_time["fire"] = 25;
}
if ( oil_leak )
{
level._pipes._effect[ "oil_leak" ] = LoadFX( "fx/impacts/pipe_oil_barrel_spill" );
// level._pipes._effect[ "oil_leak_end" ] = LoadFX( "fx/impacts/pipe_oil_barrel_spill_ending1" );
level._pipes._sound[ "oil_leak_hit" ] = "mtl_oil_barrel_hit";
level._pipes._sound[ "oil_leak_loop" ] = "mtl_oil_barrel_hiss_loop";
level._pipes._sound[ "oil_leak_end" ] = "mtl_oil_barrel_hiss_loop_end";
level._pipes.fx_time[ "oil_leak" ] = 6;
level._pipes._pipe_fx_time["oil_leak"] = 6;
level._pipes._dmg[ "oil_leak" ] = 5;
}
if ( oil_cap )
{
level._pipes._effect[ "oil_cap" ] = LoadFX( "fx/impacts/pipe_oil_barrel_squirt" );
level._pipes._sound[ "oil_cap_hit" ] = "mtl_steam_pipe_hit";
level._pipes._sound[ "oil_cap_loop" ] = "mtl_steam_pipe_hiss_loop";
level._pipes._sound[ "oil_cap_end" ] = "mtl_steam_pipe_hiss_loop_end";
level._pipes.fx_time[ "oil_cap" ] = 3;
level._pipes._dmg[ "oil_cap" ] = 5;
level._pipes._pipe_fx_time["oil_cap"] = 5;
}
}

4981
common_scripts/utility.gsc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#include common_scripts\_destructible;
#include destructible_scripts\toy_chicken_common;
#using_animtree( "destructibles" );
main()
{
toy_chicken_common( "" );
}

View File

@ -0,0 +1,8 @@
#include common_scripts\_destructible;
#include destructible_scripts\toy_chicken_common;
#using_animtree( "destructibles" );
main()
{
toy_chicken_common( "_black_white" );
}

View File

@ -0,0 +1,19 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
toy_chicken_common( version )
{
//---------------------------------------------------------------------
// Chicken
//---------------------------------------------------------------------
destructible_create( "toy_chicken" + version, "tag_origin", 0, undefined, 32 );
destructible_anim( %chicken_cage_loop_01, #animtree, "setanimknob", undefined, 0, "chicken_cage_loop_01", 1.6 );
destructible_anim( %chicken_cage_loop_02, #animtree, "setanimknob", undefined, 1, "chicken_cage_loop_02", 1.6 );
destructible_loopsound( "animal_chicken_idle_loop" );
destructible_state( "tag_origin", "chicken" + version, 25 );
destructible_fx( "tag_origin", "fx/props/chicken_exp" + version );
destructible_anim( %chicken_cage_death, #animtree, "setanimknob", undefined, 0, "chicken_cage_death" );
destructible_anim( %chicken_cage_death_02, #animtree, "setanimknob", undefined, 1, "chicken_cage_death_02" );
destructible_sound( "animal_chicken_death" );
destructible_state( undefined, "chicken" + version, undefined, undefined, "no_melee" );
}

View File

@ -0,0 +1,21 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// filecabinet toy
//---------------------------------------------------------------------
destructible_create( "toy_filecabinet", "tag_origin", 120 );
destructible_fx( "tag_drawer_lower", "fx/props/filecabinet_dam", true, damage_not( "splash" ) ); // coin drop
destructible_sound( "exp_filecabinet" );
destructible_state( undefined, "com_filecabinetblackclosed_dam", 20, undefined, undefined, "splash" );
destructible_fx( "tag_drawer_upper", "fx/props/filecabinet_des", true, "splash" ); // coin drop
destructible_sound( "exp_filecabinet" ); // coin drop sounds
destructible_physics( "tag_drawer_upper", ( 50, -10, 5 ) ); // coin drop sounds
destructible_state( undefined, "com_filecabinetblackclosed_des", undefined, undefined, undefined, undefined, undefined, false );
// front door
destructible_part( "tag_drawer_upper", "com_filecabinetblackclosed_drawer", undefined, undefined, undefined, undefined, 1.0, 1.0 );
}

View File

@ -0,0 +1,25 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// Ceiling fluorescent light
//---------------------------------------------------------------------
destructible_create( "toy_light_ceiling_fluorescent", "tag_origin", 150, undefined, 32, "no_melee" );
destructible_splash_damage_scaler( 15 );
destructible_fx( "tag_fx", "fx/misc/light_fluorescent_blowout_runner" );
destructible_fx( "tag_swing_fx", "fx/misc/light_blowout_swinging_runner" );
destructible_lights_out( 16 );
destructible_explode( 20, 2000, 64, 64, 40, 80 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_anim( %light_fluorescent_swing, #animtree, "setanimknob", undefined, 0, "light_fluorescent_swing" );
destructible_sound( "fluorescent_light_fall", undefined, 0 );
destructible_sound( "fluorescent_light_bulb", undefined, 0 );
//destructible_sound( "fluorescent_light_spark", undefined, 0 );
destructible_anim( %light_fluorescent_swing_02, #animtree, "setanimknob", undefined, 1, "light_fluorescent_swing_02" );
destructible_sound( "fluorescent_light_fall", undefined, 1 );
destructible_sound( "fluorescent_light_bulb", undefined, 1 );
//destructible_sound( "fluorescent_light_spark", undefined, 1 );
destructible_anim( %light_fluorescent_null, #animtree, "setanimknob", undefined, 2, "light_fluorescent_null" );
destructible_state( undefined, "me_lightfluohang_double_destroyed", undefined, undefined, "no_melee" );
}

View File

@ -0,0 +1,30 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// Small hanging Transformer box for Favela
//---------------------------------------------------------------------
destructible_create( "toy_transformer_small01", "tag_origin", 75, undefined, 32, "no_melee" );
destructible_splash_damage_scaler( 15 );
destructible_loopfx( "tag_fx", "fx/smoke/car_damage_whitesmoke", 0.4 );
destructible_state( undefined, undefined, 75, undefined, 32, "no_melee" );
destructible_loopfx( "tag_fx", "fx/smoke/car_damage_blacksmoke", 0.4 );
destructible_state( undefined, undefined, 150, undefined, 32, "no_melee" );
destructible_loopfx( "tag_fx", "fx/explosions/transformer_spark_runner", .5 );
destructible_loopsound( "transformer_spark_loop" );
destructible_healthdrain( 24, 0.2 );
destructible_state( undefined, undefined, 250, undefined, 32, "no_melee" );
destructible_loopfx( "tag_fx", "fx/explosions/transformer_spark_runner", .5 );
destructible_loopfx( "tag_fx", "fx/fire/transformer_small_blacksmoke_fire", .4 );
destructible_sound( "transformer01_flareup_med" );
destructible_loopsound( "transformer_spark_loop" );
destructible_healthdrain( 24, 0.2, 150, "allies" );
destructible_state( undefined, undefined, 400, undefined, 5, "no_melee" );
destructible_fx( "tag_fx", "fx/explosions/transformer_explosion", false );
destructible_fx( "tag_fx", "fx/fire/firelp_small_pm" );
destructible_sound( "transformer01_explode" );
destructible_explode( 7000, 8000, 150, 256, 16, 100, undefined, 0 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "utility_transformer_small01_dest", undefined, undefined, "no_melee" );
}

View File

@ -0,0 +1,17 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// trashcan_metal_closed
//---------------------------------------------------------------------
destructible_create( "toy_trashcan_metal_closed", "tag_origin", 120, undefined, 32, "no_melee" );
destructible_fx( "tag_fx", "fx/props/garbage_spew_des", true, "splash" );
destructible_fx( "tag_fx", "fx/props/garbage_spew", true, damage_not( "splash" ) );
destructible_sound( "exp_trashcan_sweet" );
destructible_explode( 600, 651, 1, 1, 10, 20 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "com_trashcan_metal_with_trash", undefined, undefined, undefined, undefined, undefined, false );
destructible_part( "tag_fx", "com_trashcan_metalLID", undefined, undefined, undefined, undefined, 1.0, 1.0 );
}

View File

@ -0,0 +1,97 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
toy_tvs_flatscreen( version, mounting, destroyFn )
{
//---------------------------------------------------------------------
// Flatscreen TVs
//---------------------------------------------------------------------
if(IsDefined( self.script_noteworthy ) && self.script_noteworthy == "blackice_tv")
{
destructible_create( "toy_tv_flatscreen_" + mounting + version, "tag_origin", 1, undefined, 32 );
destructible_splash_damage_scaler( 1 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion_quick" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "ma_flatscreen_tv_" + mounting + "broken_" + version, 200, undefined, "no_melee" );
}
else
{
destructible_create( "toy_tv_flatscreen_" + mounting + version, "tag_origin", 1, undefined, 32 );
destructible_splash_damage_scaler( 1 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "ma_flatscreen_tv_" + mounting + "broken_" + version, 200, undefined, "no_melee" );
}
}
toy_tvs_flatscreen_sturdy( version, mounting, destroyFn )
{
//---------------------------------------------------------------------
// Flatscreen TVs that can take more damage
//---------------------------------------------------------------------
if ( IsDefined( self.script_noteworthy ) && self.script_noteworthy == "blackice_tv" )
{
destructible_create( "toy_tv_flatscreen_" + mounting + version + "_sturdy", "tag_origin", 1, undefined, 1280 );
destructible_splash_damage_scaler( 0.5 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion_quick" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "ma_flatscreen_tv_" + mounting + "broken_" + version, 200, undefined, "no_melee" );
}
else
{
destructible_create( "toy_tv_flatscreen_" + mounting + version + "_sturdy", "tag_origin", 1, undefined, 1280 );
destructible_splash_damage_scaler( 0.5 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion_cheap" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_state( undefined, "ma_flatscreen_tv_" + mounting + "broken_" + version, 200, undefined, "no_melee" );
}
}
toy_tvs_flatscreen_cinematic( modelName, destroyFn )
{
//---------------------------------------------------------------------
// Flatscreen TV that has a (optional) separate model that shows a cinematic on the screen
//---------------------------------------------------------------------
if ( IsDefined( self.script_noteworthy ) && self.script_noteworthy == "blackice_tv" )
{
destructible_create( "toy_" + modelName, "tag_origin", 1, undefined, 32 );
destructible_splash_damage_scaler( 1 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion_quick" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_function( destroyFn );
destructible_state( undefined, modelName + "_d", 200, undefined, "no_melee" );
}
else
{
destructible_create( "toy_" + modelName, "tag_origin", 1, undefined, 32 );
destructible_splash_damage_scaler( 1 );
destructible_fx( "tag_fx", "fx/explosions/tv_flatscreen_explosion" );
destructible_sound( "tv_shot_burst" );
destructible_explode( 20, 2000, 10, 10, 3, 3, undefined, 15 ); // force_min, force_max, rangeSP, rangeMP, mindamage, maxdamage
destructible_function( destroyFn );
destructible_state( undefined, modelName + "_d", 200, undefined, "no_melee" );
}
}
// Finds and removes a targetted model. Commonly used to remove the cinematic-playing screen and/or a light when a TV is destroyed.
RemoveTargetted()
{
if ( IsDefined( self.target ) ) {
tgtModels = GetEntArray( self.target, "targetname" );
if ( isDefined( tgtModels ) )
{
foreach ( tgtModel in tgtModels )
{
if ( tgtModel.classname == "light_omni" || tgtModel.classname == "light_spot" )
tgtModel SetLightIntensity( 0 );
else
tgtModel Delete();
}
}
}
}

View File

@ -0,0 +1,8 @@
#include common_scripts\_destructible;
#include destructible_scripts\toy_tv_flatscreen;
#using_animtree( "destructibles" );
main()
{
toy_tvs_flatscreen_cinematic( "tv_video_monitor", ::RemoveTargetted );
}

View File

@ -0,0 +1,20 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// wall fan
//---------------------------------------------------------------------
destructible_create( "toy_wall_fan", "tag_swivel", 0, undefined, 32 );
destructible_anim( %wall_fan_rotate, #animtree, "setanimknob", undefined, undefined, "wall_fan_rotate" );
destructible_loopsound( "wall_fan_fanning" );
destructible_state( "tag_wobble", "cs_wallfan1", 150 );
destructible_anim( %wall_fan_stop, #animtree, "setanimknob", undefined, undefined, "wall_fan_wobble" );
destructible_fx( "tag_fx", "fx/explosions/wallfan_explosion_dmg" );
destructible_sound( "wall_fan_sparks" );
destructible_state( "tag_wobble", "cs_wallfan1", 150, undefined, "no_melee" );
destructible_fx( "tag_fx", "fx/explosions/wallfan_explosion_des" );
destructible_sound( "wall_fan_break" );
destructible_state( undefined, "cs_wallfan1_dmg", undefined, undefined, "no_melee" );
}

View File

@ -0,0 +1,120 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
//---------------------------------------------------------------------
// White Pickup Truck
//---------------------------------------------------------------------
destructible_create( "vehicle_pickup", "tag_body", 300, undefined, 32, "no_melee" );
//destructible_splash_damage_scaler( 18 );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_whitesmoke", 0.4 );
destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_blacksmoke", 0.4 );
destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_blacksmoke_fire", 0.4 );
destructible_sound( "fire_vehicle_flareup_med" );
destructible_loopsound( "fire_vehicle_med" );
destructible_healthdrain( 15, 0.25, 210, "allies" );
destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" );
destructible_loopsound( "fire_vehicle_med" );
destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" );
destructible_fx( "tag_death_fx", "fx/explosions/small_vehicle_explosion", false );
destructible_sound( "car_explode" );
destructible_explode( 4000, 5000, 210, 250, 50, 300, undefined, undefined, 0.3, 500 );
destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" );
destructible_state( undefined, "vehicle_pickup_destroyed", undefined, 32, "no_melee" );
// Hood
tag = "tag_hood";
destructible_part( tag, "vehicle_pickup_hood", 800, undefined, undefined, undefined, 1.0, 2.5 );
// Tires
destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
// Doors
destructible_part( "tag_door_left_front", "vehicle_pickup_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 );
destructible_part( "tag_door_right_front", "vehicle_pickup_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 );
// Glass ( Front )
tag = "tag_glass_front";
destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_front_fx", "fx/props/car_glass_large" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Back )
tag = "tag_glass_back";
destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_back_fx", "fx/props/car_glass_large" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Left Front )
tag = "tag_glass_left_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_left_front_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Right Front )
tag = "tag_glass_right_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_right_front_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Left Back )
tag = "tag_glass_left_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_left_back_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Right Back )
tag = "tag_glass_right_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_right_back_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Head Light ( Left )
tag = "tag_light_left_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_headlight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Head Light ( Right )
tag = "tag_light_right_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_headlight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Tail Light ( Left )
tag = "tag_light_left_back";
destructible_part( tag, undefined, 20 );
destructible_fx( tag, "fx/props/car_glass_brakelight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Tail Light ( Right )
tag = "tag_light_right_back";
destructible_part( tag, undefined, 20 );
destructible_fx( tag, "fx/props/car_glass_brakelight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Bumpers
destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0, 1.0 );
destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, undefined, 1.0 );
// Side Mirrors
destructible_part( "tag_mirror_left", "vehicle_pickup_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 );
destructible_physics();
destructible_part( "tag_mirror_right", "vehicle_pickup_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 );
destructible_physics();
}

View File

@ -0,0 +1,120 @@
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
vehicle_small_hatch( color )
{
//---------------------------------------------------------------------
// small hatch
//---------------------------------------------------------------------
destructible_create( "vehicle_small_hatch_" + color, "tag_body", 250, undefined, 32, "no_melee" );
//destructible_splash_damage_scaler( 18 );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_whitesmoke", 0.4 );
destructible_state( undefined, undefined, 200, undefined, 32, "no_melee" );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_blacksmoke", 0.4 );
destructible_state( undefined, undefined, 100, undefined, 32, "no_melee" );
destructible_loopfx( "tag_hood_fx", "fx/smoke/car_damage_blacksmoke_fire", 0.4 );
destructible_sound( "fire_vehicle_flareup_med" );
destructible_loopsound( "fire_vehicle_med" );
destructible_healthdrain( 15, 0.25, 150, "allies" );
destructible_state( undefined, undefined, 300, "player_only", 32, "no_melee" );
destructible_loopsound( "fire_vehicle_med" );
destructible_state( undefined, undefined, 400, undefined, 32, "no_melee" );
destructible_fx( "tag_death_fx", "fx/explosions/small_vehicle_explosion", false );
destructible_sound( "car_explode" );
destructible_explode( 4000, 5000, 150, 250, 50, 300, undefined, undefined, 0.3, 500 );
destructible_anim( %vehicle_80s_sedan1_destroy, #animtree, "setanimknob", undefined, undefined, "vehicle_80s_sedan1_destroy" );
destructible_state( undefined, "vehicle_small_hatch_" + color + "_destroyed", undefined, 32, "no_melee" );
// Hood
tag = "tag_hood";
destructible_part( tag, "vehicle_small_hatch_" + color + "_hood", 800, undefined, undefined, undefined, 1.0, 1.5 );
// Tires
destructible_part( "left_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_LF, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "left_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_LB, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "right_wheel_01_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_RF, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
destructible_part( "right_wheel_02_jnt", undefined, 20, undefined, undefined, "no_melee" );
destructible_anim( %vehicle_80s_sedan1_flattire_RB, #animtree, "setanim" );
destructible_sound( "veh_tire_deflate", "bullet" );
// Doors
destructible_part( "tag_door_left_front", "vehicle_small_hatch_" + color + "_door_LF", undefined, undefined, undefined, undefined, 1.0, 1.0 );
destructible_part( "tag_door_right_front", "vehicle_small_hatch_" + color + "_door_RF", undefined, undefined, undefined, undefined, 1.0, 1.0 );
// Glass ( Front )
tag = "tag_glass_front";
destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_front_fx", "fx/props/car_glass_large" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Back )
tag = "tag_glass_back";
destructible_part( tag, undefined, 40, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_back_fx", "fx/props/car_glass_large" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Left Front )
tag = "tag_glass_left_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_left_front_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Right Front )
tag = "tag_glass_right_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_right_front_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Left Back )
tag = "tag_glass_left_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_left_back_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Glass ( Right Back )
tag = "tag_glass_right_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, undefined, undefined, true );
destructible_state( tag + "_d", undefined, 60, undefined, undefined, undefined, true );
destructible_fx( "tag_glass_right_back_fx", "fx/props/car_glass_med" );
destructible_sound( "veh_glass_break_large" );
destructible_state( undefined );
// Head Light ( Left )
tag = "tag_light_left_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_headlight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Head Light ( Right )
tag = "tag_light_right_front";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_headlight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Tail Light ( Left )
tag = "tag_light_left_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_brakelight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Tail Light ( Right )
tag = "tag_light_right_back";
destructible_part( tag, undefined, 20, undefined, undefined, undefined, 0.5 );
destructible_fx( tag, "fx/props/car_glass_brakelight" );
destructible_sound( "veh_glass_break_small" );
destructible_state( tag + "_d" );
// Bumpers
destructible_part( "tag_bumper_front", undefined, undefined, undefined, undefined, undefined, 1.0 );
destructible_part( "tag_bumper_back", undefined, undefined, undefined, undefined, undefined, 0.5 );
// Side Mirrors
destructible_part( "tag_mirror_left", "vehicle_small_hatch_" + color + "_mirror_L", 40, undefined, undefined, undefined, undefined, 1.0 );
destructible_physics();
destructible_part( "tag_mirror_right", "vehicle_small_hatch_" + color + "_mirror_R", 40, undefined, undefined, undefined, undefined, 1.0 );
destructible_physics();
}

View File

@ -0,0 +1,8 @@
#include destructible_scripts\vehicle_small_hatch;
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
vehicle_small_hatch( "blue" );
}

View File

@ -0,0 +1,8 @@
#include destructible_scripts\vehicle_small_hatch;
#include common_scripts\_destructible;
#using_animtree( "destructibles" );
main()
{
vehicle_small_hatch( "white" );
}

View File

@ -0,0 +1,22 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
// Would use isSP() but this runs before we can
mapname = tolower( getdvar( "mapname" ) );
SP = true;
if ( string_starts_with( mapname, "mp_" ) )
SP = false;
model = "com_roofvent2_animated";
if ( SP )
{
level.anim_prop_models[ model ][ "rotate" ] = %roofvent_rotate;
}
else
level.anim_prop_models[ model ][ "rotate" ] = "roofvent_rotate";
}

View File

@ -0,0 +1,16 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "foliage_pacific_bushtree01_animated";
if ( isSp() )
{
level.anim_prop_models[ model ][ "sway" ] = %foliage_pacific_bushtree01_sway;
}
else
level.anim_prop_models[ model ][ "sway" ] = "foliage_pacific_bushtree01_sway";
}

View File

@ -0,0 +1,14 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "clothes_line_tank_iw6";
if ( isSP() )
level.anim_prop_models[ model ][ "wind_medium" ] = %hanging_clothes_apron_wind_medium;
else
level.anim_prop_models[ model ][ "wind_medium" ] = "hanging_clothes_apron_wind_medium";
}

View File

@ -0,0 +1,14 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "clothes_line_sweater_iw6";
if ( isSP() )
level.anim_prop_models[ model ][ "wind_medium" ] = %hanging_clothes_long_sleeve_wind_medium;
else
level.anim_prop_models[ model ][ "wind_medium" ] = "hanging_clothes_long_sleeve_wind_medium";
}

View File

@ -0,0 +1,14 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "clothes_line_sheet_iw6";
if ( isSP() )
level.anim_prop_models[ model ][ "wind_medium" ] = %hanging_clothes_sheet_wind_medium;
else
level.anim_prop_models[ model ][ "wind_medium" ] = "hanging_clothes_sheet_wind_medium";
}

View File

@ -0,0 +1,14 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "clothes_line_tshirt_iw6";
if ( isSP() )
level.anim_prop_models[ model ][ "wind_medium" ] = %hanging_clothes_short_sleeve_wind_medium;
else
level.anim_prop_models[ model ][ "wind_medium" ] = "hanging_clothes_short_sleeve_wind_medium";
}

View File

@ -0,0 +1,22 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
// Would use isSP() but this runs before we can
mapname = tolower( getdvar( "mapname" ) );
SP = true;
if ( string_starts_with( mapname, "mp_" ) )
SP = false;
model = "debris_water_trash";
if ( SP )
{
level.anim_prop_models[ model ][ "debris_water_trash" ] = %debris_water_trash_bob_anim;
}
else
level.anim_prop_models[ model ][ "debris_water_trash" ] = "debris_water_trash_bob_anim";
}

View File

@ -0,0 +1,23 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
// Would use isSP() but this runs before we can
mapname = tolower( getdvar( "mapname" ) );
SP = true;
if ( string_starts_with( mapname, "mp_" ) )
SP = false;
model = "debris_water_trash";
if ( SP )
{
level.anim_prop_models[ model ][ "debris_water_trash" ] = %debris_water_trash_spiral_anim;
}
else
level.anim_prop_models[ model ][ "debris_water_trash" ] = "debris_water_trash_spiral_anim";
}

View File

@ -0,0 +1,23 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
// Would use isSP() but this runs before we can
mapname = tolower( getdvar( "mapname" ) );
SP = true;
if ( string_starts_with( mapname, "mp_" ) )
SP = false;
model = "mp_flooded_street_water";
if ( SP )
{
level.anim_prop_models[ model ][ "mp_flooded_street_water" ] = %mp_flooded_street_water_anim;
}
else
level.anim_prop_models[ model ][ "mp_flooded_street_water" ] = "mp_flooded_street_water_anim";
}

View File

@ -0,0 +1,16 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
model = "mp_frag_crane_anim";
if ( isSP() )
{
level.anim_prop_models[ model ][ "idle" ] = %mp_frag_crane_sway;
}
else
level.anim_prop_models[ model ][ "idle" ] = "mp_frag_crane_sway";
}

View File

@ -0,0 +1,23 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
if( !isdefined ( level.anim_prop_models ) )
level.anim_prop_models = [];
// Would use isSP() but this runs before we can
mapname = tolower( getdvar( "mapname" ) );
SP = true;
if ( string_starts_with( mapname, "mp_" ) )
SP = false;
model = "prop_wire_hanging_192long";
if ( SP )
{
level.anim_prop_models[ model ][ "self.wind" ] = %prop_wire_hanging_192long_wind1;
}
else
level.anim_prop_models[ model ][ "self.wind" ] = "prop_wire_hanging_192long_wind1";
}

View File

@ -0,0 +1,11 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_alien_town_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
//setExpFog( 0, 5211.68, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0.838639, 0.691254, 0.567937, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 );
//VisionSetNaked( "mp_alien_town", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_battery3_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 7346.26, 10487.6, 0.583682, 0.52939, 0.302793, 1, 1, 0, 0, 0, 0 );
VisionSetNaked( "mp_battery3", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_boneyard_ns_fog::main;
//* Fog section *
VisionSetNaked( "mp_boneyard_ns", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_ca_behemoth_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 34658, 0.423529, 0.490196, 0.666667, 0.88, 0.776167, 0, 0.482353, 0.458824, 0.4, 2.3, (0, 0, -1), 0, 135, 10, 0.901, 180, 113 );
VisionSetNaked( "mp_ca_behemoth", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_ca_impact_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 3026.57, 1163.94, 0.711328, 0.78437, 0.798145, 0.793067, 0.811095, 0, 1, -0.538688, 90 );
VisionSetNaked( "mp_ca_impact", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_ca_red_river_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 7220, 1084, 0.901961, 0.917647, 0.843137, 1, 0.2094, 0, 0, 0, 90 );
VisionSetNaked( "mp_ca_red_river", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_ca_rumble_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 562.278, 5000, 0.685692, 0.564965, 0.436857, 1, 0.60214, 0, 0, 0, 90 );
VisionSetNaked( "mp_ca_rumble", 0 );
}

View File

@ -0,0 +1,14 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_chasm_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 5211.68, 0.480657, 0.755661, 0.785471, 2.01908, 0, 0, 0, 0, 0 );
VisionSetNaked( "mp_chasm", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_conflict_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 1958.84, 0.656882, 0.680657, 0.696267, 2, 0.90625, 0, 0.396688, 0.396688, 0.396619, 0.5, (0, 0, -1), 80, 105, 0.0625, 0.960938, 0, 54 );
VisionSetNaked( "mp_conflict", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_dart_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 200, 3500, 0.54, 0.54, 0.54, 1, 0.75, 0, 0.92, 0.69, 0.44, 1, (-0.27, -0.86, 0.4), 15, 60, 2.25, 1, 61, 85 );
VisionSetNaked( "mp_dart", 0 );
}

View File

@ -0,0 +1,13 @@
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_descent_new_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 5211.68, 0.480657, 0.755661, 0.785471, 2.01908, 0, 0, 0, 0, 0 );
VisionSetNaked( "mp_descent_new", 0 );
}

View File

@ -0,0 +1,11 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_dig_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 5211.68, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0.838639, 0.691254, 0.567937, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 );
VisionSetNaked( "mp_dig", 0 );
}

View File

@ -0,0 +1,16 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_dome_ns_fog::main;
//* Fog section *
//setDevDvar( "scr_fog_disable", "0" );
//setExpFog( 0, 5211.68, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0.838639, 0.691254, 0.567937, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 );
VisionSetNaked( "mp_dome_ns", 0 );
//setdvar_cg_ng("r_specularColorScale", 3, 8.5);
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_fahrenheit_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 624.344, 2914.77, 0.53, 0.52, 0.57, 1, 1, 0, 0.84, 0.77, 0.67, 1, (-0.79, 0.17, 0.57), 0, 80.7, 0.9, 1, 23.32, 89.58 );
VisionSetNaked( "mp_fahrenheit", 0 );
}

View File

@ -0,0 +1,11 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_favela_iw6_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 5211.68, 0.627451, 0.717647, 0.745098, 0.38927, 0, 0.838639, 0.691254, 0.567937, (0.00390755, 0.00323934, -1), 83.5416, 92.7872, 2.25266 );
VisionSetNaked( "mp_favela_iw6", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_flooded_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 600, 1600, 0.721569, 0.823529, 0.929412, 1, 0.314067, 0, 0, 0, 90 );
VisionSetNaked( "mp_flooded", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_frag_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 1500, 6145, 0.8, 0.88, 1, 1, 0.25, 0, 1, 1, 0.94, 1.06, (0.76, 0.38, 0.51), 0, 100, 1, 1, 60, 85 );
VisionSetNaked( "mp_frag", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_hashima_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 1536, 10241, 0, 0.705811, 0.921875, 1, 0.5, 0, 0.757813, 0.607019, 0.363672, 1, (0.097, -0.031, -0.375), 55, 180, 2.5, 1, 60, 80 );
VisionSetNaked( "mp_hashima", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_lonestar_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 512, 7760.62, 0.5, 0.5, 0.5, 0.75, 0.859375, 0, 0.328125, 0.328125, 0.328125, 1, (0, 0, 1), 64, 91, 0.5, 1, 54, 82 );
VisionSetNaked( "mp_lonestar", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_mine_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 122.24, 25282, 0.846864, 0.748939, 0.5479, 1, 1, 0, 0, 0, 0 );
VisionSetNaked( "mp_mine", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_pirate_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 1, 0.109, 0.113, 0.124, 0.807, 1, 0, 1, 30, 90 );
VisionSetNaked( "mp_pirate", 0 );
}

View File

@ -0,0 +1,11 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_prisonbreak_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
//setExpFog( 1400, 40500, 0.92, 0.99, 1.0, 0.22, 1, 0.64, 0.50, 0.50, (0.98, 0.09, 0.1), 0, 80.0, 5.0 );
VisionSetNaked( "mp_prisonbreak", 0 );
}

View File

@ -0,0 +1,9 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_shipment_ns_fog::main;
setDevDvar( "scr_fog_disable", 0 );
VisionSetNaked( "mp_shipment_ns", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_skeleton_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 575.658, 5181.9, 0.899167, 0.930833, 1, 3.42928, 0.619243, 0, 1, 78.972, 92.2944 );
VisionSetNaked( "mp_skeleton", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_snow_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 714.363, 7073.18, 0.345189, 0.457268, 0.453545, 1, 0.55, 0, 0.608505, 0.999996, 0.828083, 1, (0.12, -0.03, 0.99), 0, 55, 0.38, 1, 67.2161, 92.6819 );
VisionSetNaked( "mp_snow", 0 );
}

View File

@ -0,0 +1,15 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_sovereign_fog::main;
//* Fog section *
setDevDvar( "scr_fog_disable", "0" );
//setExpFog( 650, 2049, 0.352941, 0.411765, 0.478431, 1, 0.5, 0, 1, 0.854902, 0.74902, 1, (0.00390755, 0.00323934, -1), 61, 93.7872, 0.25 );
VisionSetNaked( "mp_sovereign", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_strikezone_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 525.762, 18137.9, 0.62, 0.81, 0.81, 1.4, 1, 0, 0.99, 0.97, 0.83, 1.2, (-0.05, -0.89, 0.44), 0, 100, 0.9, 1, 13.7392, 117.129 );
VisionSetNaked( "mp_strikezone", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_swamp_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 2985.05, 0.339273, 0.302975, 0.400243, 1, 0.485193, 0, 0, 0, 0 );
VisionSetNaked( "mp_swamp", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_warhawk_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 1307.29, 8178.08, 0.888789, 0.851156, 0.664851, 1.07658, 0.468766, 0, 0.639683, 0.464798, 0.346012, 0.573353, (0.89, 0.06, 0.44), 0, 137, 2.40463, 0.730742, 26.9803, 63.638 );
VisionSetNaked( "mp_warhawk", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_zebra_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 371.287, 7055.43, 0.395946, 0.358963, 0.352442, 0.742574, 0.919554, 0, 0, 0, 0 );
VisionSetNaked( "mp_zebra", 0 );
}

View File

@ -0,0 +1,12 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_zerosub_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 0, 2985.05, 0.339273, 0.302975, 0.400243, 1, 0.485193, 0, 0, 0, 0 );
VisionSetNaked( "mp_zerosub", 0 );
}

View File

@ -0,0 +1,10 @@
// _createart generated. modify at your own risk. Changing values should be fine.
main()
{
level.tweakfile = true;
level.parse_fog_func = maps\createart\mp_zulu_fog::main;
setDevDvar( "scr_fog_disable", "0" );
// setExpFog( 7346.26, 10487.6, 0.583682, 0.52939, 0.302793, 1, 1, 0, 0, 0, 0 );
VisionSetNaked( "mp_zulu", 0 );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,664 @@
#include common_scripts\utility;
/*
=============
///ScriptDocBegin
"Name: delete_on_notify( <ent>, <notify1>, <notify2>, <notify3> )"
"Summary: Just like delete_on_death, but takes up to 3 strings. Notifying any of the strings will result in ent being deleted."
"Module: Entity"
"CallOn: An entity"
"MandatoryArg: <ent>: The entity to be deleted"
"OptionalArg: <notify1>: Strings on the called-on-entity that you want to listen for."
"Example: self thread delete_on_notify( trigger, "death", "damage" );"
"SPMP: both"
///ScriptDocEnd
=============
*/
delete_on_notify( ent, notify1, notify2, notify3 )
{
//self ==> the entity you want to wait for a notify on before deleting the ent
ent endon( "death" );
self waittill_any( notify1, notify2, notify3 );
if ( IsDefined( ent ) )
ent Delete();
}
// array_sortByArray - given an array, and another array of equal size containing a value to sort on, returns a copy of the first array, sorted.
// Not optimized. O(n^2), I think.
array_sortByArray( array, sorters )
{
newArray = [];
newArray[0] = array[0];
newSorters = [];
newSorters[0] = sorters[0];
for ( i=1; i<array.size; i++ )
{
sorted = false;
for ( j=0; j<newArray.size; j++ )
{
if ( sorters[i] < newSorters[j] )
{
for ( k=newArray.size-1; k>=j; k-- )
{
newArray[ k+1 ] = newArray[ k ];
newSorters[ k+1 ] = newSorters[ k ];
}
newArray[ j ] = array[ i ];
newSorters[ j ] = sorters[ i ];
sorted = true;
break;
}
}
if ( !sorted )
{
newArray[ i ] = array[ i ];
newSorters[ i ] = sorters[ i ];
}
}
return newArray;
}
// array_sortBySorter - given an array of structs, each of which contains a field named "sorter", returns a copy of the array, sorted.
// Notes:
// Not optimized. O(n^2), I think.
// Does not copy the structs. Copies the array but references the original structs.
array_sortBySorter( array )
{
newArray = [];
newArray[0] = array[0];
for ( i=1; i<array.size; i++ )
{
sorted = false;
for ( j=0; j<newArray.size; j++ )
{
if ( array[i].sorter < newArray[j].sorter )
{
for ( k=newArray.size-1; k>=j; k-- )
{
newArray[ k+1 ] = newArray[ k ];
}
newArray[ j ] = array[ i ];
sorted = true;
break;
}
}
if ( !sorted )
{
newArray[ i ] = array[ i ];
}
}
return newArray;
}
/*
=============
///ScriptDocBegin
"Name: wait_then_fn( <notifyStr>, <fn>, <arg1>, <arg2>, <arg3> )"
"Summary: Waits for a notify or a time, then calls the specified function with specified args."
"Module: "
"CallOn: Entity"
"MandatoryArg: <notifyStr> : String to notify or time to wait"
"MandatoryArg: <enders>: String (or array of strings) to kill the thread. Can be undefined."
"MandatoryArg: <fn> : pointer to a script function"
"OptionalArg: <arg1> : parameter 1 to pass to the process"
"OptionalArg: <arg2> : parameter 2 to pass to the process"
"OptionalArg: <arg3> : parameter 3 to pass to the process"
"OptionalArg: <arg4> : parameter 4 to pass to the process"
"Example: fish1 thread wait_then_fn( "path_complete", ::arriveAtLocation, false );"
"SPMP: both"
///ScriptDocEnd
=============
*/
wait_then_fn( notifyStr, enders, fn, arg1, arg2, arg3, arg4 )
{
self endon( "death" );
if ( IsDefined( enders ) ) {
if ( IsArray( enders ) ) {
foreach ( ender in enders )
{
self endon( ender );
}
} else {
self endon( enders );
}
}
if ( isString( notifyStr ) )
self waittill( notifyStr );
else // Assume it's a time
wait ( notifyStr );
if ( IsDefined( arg4 ) )
self [[ fn ]]( arg1, arg2, arg3, arg4 );
else if ( IsDefined( arg3 ) )
self [[ fn ]]( arg1, arg2, arg3 );
else if ( IsDefined( arg2 ) )
self [[ fn ]]( arg1, arg2 );
else if ( IsDefined( arg1 ) )
self [[ fn ]]( arg1 );
else
self [[ fn ]]();
}
/*
=============
///ScriptDocBegin
"Name: waittill_notify ( <waitStr> , <notifyEnt> , <notifyStr> , <ender> )"
"Summary: Wait for a notify on one ent and then notify another ent."
"Module: Entity"
"CallOn: An entity"
"MandatoryArg: <waitStr>: String to wait for."
"MandatoryArg: <notifyEnt>: Entity to notify."
"MandatoryArg: <notifyStr>: String to notify."
"OptionalArg: <ender>: String that will end this thread."
"OptionalArg: <multiple>: Continue waiting for more notifies after the first one. Defaults to false."
"Example: waittill_notify ( "trigger", self, trigger.script_triggername );"
"SPMP: singleplayer"
///ScriptDocEnd
=============
*/
waittill_notify ( waitStr, notifyEnt, notifyStr, ender, multiple )
{
if ( !isDefined( multiple ) ) multiple = false;
doItAgain = true;
while ( doItAgain )
{
self endon( "death" );
if ( IsDefined( ender ) ) self endon( ender );
self waittill( waitStr );
notifyEnt notify( notifyStr );
doItAgain = multiple;
}
}
/*
=============
///ScriptDocBegin
"Name: loop_anim( <animArray> , <animName> , <ender> )"
"Summary: Plays an animation or a group of animations over and over until notified. A very simple alternative to anim_loop_solo. Takes the animations as a parameter, so you don't need to set the model up in level.scr_anim."
"Module: Anim"
"CallOn: An entity"
"MandatoryArg: <animArray>: An array. Can contain animations, arrays of animations and animweights (just like those found in level.scr_anim[animname])."
"MandatoryArg: <animName>: The animation index in the array, just like anime in anim_loop_solo."
"OptionalArg: <ender>: Notify string"
"OptionalArg: <animRate>: Playback speed for the animation. Defaults to 1."
"Example: "
"SPMP: singleplayer"
///ScriptDocEnd
=============
*/
loop_anim( animArray, animName, ender, animRate )
{
self endon( "death" );
if ( IsDefined( ender ) ) self endon( ender );
while ( 1 )
{
a = self single_anim( animArray, animName, "loop_anim", false, animRate );
if ( isSP() ) {
self waittillmatch( "loop_anim", "end" );
} else {
wait GetAnimLength( a );
}
}
}
/*
=============
///ScriptDocBegin
"Name: single_anim( <animArray> , <animName> , <notifyStr> , <restartAnim> )"
"Summary: Plays an animation or a group of animations. Similar to (but much simpler than) anim_single_solo. Takes the animations as a parameter, so you don't need to set the model up in level.scr_anim. Returns the animation chosen, so you can check the length or whatever."
"Module: Anim"
"CallOn: An entity"
"MandatoryArg: <animArray>: An array. Can contain animations, arrays of animations and weights (just like those found in level.scr_anim[animname]). Can also contain mp animations (strings) using the suffix "mp"."
"MandatoryArg: <animName>: The animation index in the array, just like anime in anim_loop_solo."
"OptionalArg: <notifyStr>: String that the animation will notify for notetracks and when finished. Defaults to single_anim. SP only."
"OptionalArg: <restartAnim>: Set to true to force the animation to start from the beginning, otherwise it will simply continue if it is already playing. Defaults to false. SP only."
"OptionalArg: <animRate>: Playback speed for the animation. Defaults to 1. SP only."
"Example: "
"SPMP: both"
///ScriptDocEnd
=============
*/
single_anim( animArray, animName, notifyStr, restartAnim, animRate )
{
if ( !IsDefined( notifyStr ) ) notifyStr = "single_anim";
if ( !IsDefined( animRate ) ) animRate = 1;
if ( IsArray( animArray[ animName ] ) )
{
//AssertEx( IsDefined( animArray[ ( animName + "weight" ) ] ) , "Array of anims labeled \""+animName+"\" does not have associated \""+animName+"weight\" array." );
if ( !IsDefined( animArray[ ( animName + "weight" ) ] ) )
{
animArray[ ( animName + "weight" ) ] = [];
keys = GetArrayKeys( animArray[ animName ] );
foreach ( key in keys )
{
animArray[ ( animName + "weight" ) ][ key ] = 1;
}
}
AssertEx( IsArray( animArray[ ( animName + "weight" ) ] ) , "Array of anim weights labeled \""+animName+"weight\" is not an array." );
AssertEx( animArray[ ( animName + "weight" ) ].size == animArray[ animName ].size, "Array of anims labeled \""+animName+"\" does not have a matching array of weights." );
numAnims = animArray[ animName ].size;
totalWeight = 0;
for ( i = 0; i < numAnims; i++ )
{
totalWeight += animArray[ ( animName + "weight" ) ][ i ];
}
rand = RandomFloat( totalWeight );
runningWeight = 0;
sel = -1;
while ( runningWeight <= rand )
{
sel++;
runningWeight += animArray[ ( animName + "weight" ) ][ sel ];
}
animation = animArray[ animName ][ sel ];
if ( IsDefined( animArray[ animName + "mp" ] ) ) {
animation_mp = animArray[ animName + "mp" ][ sel ];
} else {
animation_mp = undefined;
}
}
else
{
animation = animArray[ animName ];
animation_mp = animArray[ animName + "mp" ];
}
if ( isSP() ) {
if ( IsDefined( restartAnim) && restartAnim )
self call [[ level.func[ "setflaggedanimknobrestart" ] ]]( notifyStr, animation, 1, 0.1, animRate );
else
self call [[ level.func[ "setflaggedanimknob" ] ]]( notifyStr, animation, 1, 0.1, animRate );
} else {
self call [[ level.func[ "scriptModelPlayAnim" ] ]]( animation_mp );
}
return animation;
}
/*
=============
///ScriptDocBegin
"Name: blendAnimsBySpeed( <speed> , <anims> , <animSpeeds>, <animLengths> )"
"Summary: Only blends in SPBlends between animations in an array according to the speed parameter. Keeps all animations playing in sync (without using loopsync in the animtree). Note: uses SetAnimLimited, so be sure to set the parent node in the animtree separately."
"Module: Anim"
"CallOn: An entity"
"MandatoryArg: <speed>: The number to be compared to the values in animSpeeds."
"MandatoryArg: <anims>: Array of animations."
"MandatoryArg: <anims>: Array of speeds that correspond to the animations."
"MandatoryArg: <animLengths>: Array of lengths of the animations, to save it having to be calculated every time the function is called."
"OptionalArg: <blendTime>: Blend time used as a parameter to SetAnim."
"Example: "
"SPMP: both"
///ScriptDocEnd
=============
*/
blendAnimsBySpeed( speed, anims, animSpeeds, animLengths, blendTime )
{
/#
Assert( anims.size == animSpeeds.size && anims.size == animLengths.size );
for ( i=1; i<animSpeeds.size; i++)
Assert( animSpeeds[ i-1 ] < animSpeeds[ i ] );
#/
if ( !IsDefined( blendTime ) ) blendTime = 0.1;
speed = clamp( speed, animSpeeds[ 0 ], animSpeeds[ animSpeeds.size-1 ] );
i = 0;
while ( speed > animSpeeds[ i+1 ] )
{
i++;
}
fastWeight = speed - animSpeeds[ i ];
fastWeight /=animSpeeds[ i+1 ] - animSpeeds[ i ];
if ( isSP() ) // We only blend in SP
{
fastWeight = clamp( fastWeight, 0.01, 0.99 ); // Don't allow anims to blend out so they don't lose their time.
// Scale playback rates according to blend weights.
// I'd love to use loopsync to achieve this but it appears to prevent SetAnimTime from working.
speedRatio = animLengths[ i+1 ] / animLengths[ i ];
fastRate = fastWeight + ( ( 1 - fastWeight ) * speedRatio );
self call [[ level.func[ "setanimlimited" ] ]]( anims[ i ], 1 - fastWeight, blendTime, fastRate / speedRatio );
self call [[ level.func[ "setanimlimited" ] ]]( anims[ i+1 ], fastWeight, blendTime, fastRate );
for ( j=0; j<i; j++ )
{
speedRatio = animLengths[ i+1 ] / animLengths[ j ];
self call [[ level.func[ "setanimlimited" ] ]]( anims[ j ], 0.01, blendTime, fastRate / speedRatio );
}
for ( j=i+2; j<animSpeeds.size; j++ )
{
speedRatio = animLengths[ i+1 ] / animLengths[ j ];
self call [[ level.func[ "setanimlimited" ] ]]( anims[ j ], 0.01, blendTime, fastRate / speedRatio );
}
}
else // MP. Just play the one that matches the speed best.
{
if ( fastWeight > 0.5 )
{
self call [[ level.func[ "scriptModelPlayAnim" ] ]]( anims[ i+1 ] );
}
else
{
self call [[ level.func[ "scriptModelPlayAnim" ] ]]( anims[ i ] );
}
}
}
/*
=============
///ScriptDocBegin
"Name: detect_events()"
"Summary: Makes an entity sentient and sets it up to detect nearby firefights. self.interrupted will be set to true for the frame in which an interruption occurs, so you can check it in situations where you can't wait for a notification."
"Module: Entity"
"CallOn: An entity"
"MandatoryArg: <notifyString>: String that will be notified when violence is detected."
"Example: self thread detect_events( "interrupted" );"
"SPMP: singleplayer"
///ScriptDocEnd
=============
*/
detect_events( notifyString )
{
if ( isSP() ) {
self endon( "death" );
self endon( "damage" );
self call [[ level.makeEntitySentient_func ]]( "neutral" );
self call [[ level.addAIEventListener_func ]]( "projectile_impact" );
self call [[ level.addAIEventListener_func ]]( "bulletwhizby" );
self call [[ level.addAIEventListener_func ]]( "gunshot" );
self call [[ level.addAIEventListener_func ]]( "explode" );
while( 1 )
{
self waittill( "ai_event", eventtype );
self notify( notifyString );
self.interrupted = true;
waittillframeend;
self.interrupted = false;
}
}
}
/*
=============
///ScriptDocBegin
"Name: detect_people( <radius> , <notifyStr> )"
"Summary: Creates a trigger that detects people and vehicles. self.interrupted will be set to true for the frame in which an interruption occurs, so you can check it in situations where you can't wait for a notification."
"Module: Entity"
"CallOn: An entity"
"MandatoryArg: <radius>: Radious and height of the trigger volume."
"MandatoryArg: <notifyStr>: String to notify when someone enters the trigger."
"MandatoryArg: <endonStr>: String(s) that will end this thread and delete the trigger when notified."
"Example: self thread detect_people( info.react_distance, "interrupted", [ "death", "damage" ] );"
"SPMP: singleplayer"
///ScriptDocEnd
=============
*/
detect_people( radius, notifyStr, endonStr )
{
if ( !IsArray( endonStr ) )
{
tempStr = endonStr;
endonStr = [];
endonStr[0] = tempStr;
}
foreach (str in endonStr )
self endon( str );
// I think the trigger_radius flags are as follows: AI_AXIS = 1, AI_ALLIES = 2, AI_NEUTRAL = 4, NOTPLAYER = 8 VEHICLE = 16 TRIGGER_SPAWN = 32 TOUCH_ONCE = 64
// AI_AXIS + AI_ALLIES + AI_NEUTRAL + VEHICLE = 23
self.detect_people_trigger[ notifyStr ] = Spawn( "trigger_radius", self.origin, 23, radius, radius );
for ( i = endonStr.size; i < 3; i++ ) // Pad the array to make it easier to use for function parameters.
endonStr[i] = undefined;
self thread delete_on_notify( self.detect_people_trigger[ notifyStr ], endonStr[0], endonStr[1], endonStr[2] );
while( 1 )
{
self.detect_people_trigger[ notifyStr ] waittill( "trigger", interruptedEnt );
self.interruptedEnt = interruptedEnt; // (self.interruptedEnt can't be modified directly as a parameter to waittill.)
self notify( notifyStr );
self.interrupted = true;
waittillframeend;
self.interrupted = false;
}
}
detect_player_event( radius, notifyStr, endonStr, eventStr )
{
if ( !IsArray( endonStr ) )
{
tempStr = endonStr;
endonStr = [];
endonStr[0] = tempStr;
}
foreach (str in endonStr )
self endon( str );
while( 1 ) {
level.player waittill( eventStr );
if ( DistanceSquared( level.player.origin, self.origin ) < radius*radius ) {
self notify( notifyStr );
self.interruptedEnt = level.player;
self notify( notifyStr );
self.interrupted = true;
waittillframeend;
self.interrupted = false;
}
}
}
// Wraps <number> into 0 to <range>, just like AngleClamp does for the range of 0-360. Result will be >=0 and < abs(range). AKA modulo, %, remainder.
wrap( number, range )
{
quotient = Int( number / range );
remainder = number - ( range * quotient );
if ( number < 0 ) remainder += range;
if ( remainder == range ) remainder = 0;
return remainder;
}
interactives_DrawDebugLineForTime( org1, org2, r, g, b, timer )
{
/#
if ( GetDvarInt( "interactives_debug" ) )
{
thread draw_line_for_time( org1, org2, r, g, b, timer );
}
#/
}
// Draws a cross in 3D space
drawCross( origin, size, color, timeSeconds )
{
thread draw_line_for_time ( origin -( size, 0, 0 ), origin +( size, 0, 0 ), color[0], color[1], color[2], timeSeconds );
thread draw_line_for_time ( origin -( 0, size, 0 ), origin +( 0, size, 0 ), color[0], color[1], color[2], timeSeconds );
thread draw_line_for_time ( origin -( 0, 0, size ), origin +( 0, 0, size ), color[0], color[1], color[2], timeSeconds );
}
// Draws a circle in 3D space
drawCircle( origin, radius, color, timeSeconds )
{
numSegments = 16;
for ( i=0; i<360; i+=(360/numSegments) )
{
j = i + (360/numSegments);
thread draw_line_for_time ( origin + ( radius*Cos(i), radius*Sin(i), 0 ), origin + ( radius*Cos(j), radius*Sin(j), 0 ), color[0], color[1], color[2], timeSeconds );
}
}
// Draw an arc with an arrowhead on the end, in 3D space. Positive degrees means counterclockwise.
drawCircularArrow( origin, radius, color, timeseconds, degrees )
{
if ( degrees == 0 ) return;
numSegmentsFullCircle = 16;
numSegments = int( 1 + (numSegmentsFullCircle * abs(degrees) / 360 ) );
for ( seg=0; seg<numSegments; seg++ )
{
i = seg * degrees / numSegments;
j = i + (degrees / numSegments);
thread draw_line_for_time ( origin + ( radius*Cos(i), radius*Sin(i), 0 ), origin + ( radius*Cos(j), radius*Sin(j), 0 ), color[0], color[1], color[2], timeSeconds );
}
i = degrees;
j = degrees - ( sign( degrees ) * 20 );
thread draw_line_for_time ( origin + ( radius*Cos(i), radius*Sin(i), 0 ), origin + ( radius*0.8*Cos(j), radius*0.8*Sin(j), 0 ), color[0], color[1], color[2], timeSeconds );
thread draw_line_for_time ( origin + ( radius*Cos(i), radius*Sin(i), 0 ), origin + ( radius*1.2*Cos(j), radius*1.2*Sin(j), 0 ), color[0], color[1], color[2], timeSeconds );
}
IsInArray( e, array )
{
foreach ( a in array )
{
if ( e == a ) return true;
}
return false;
}
// Newton's Method (Newton-Raphson method) to find a root of the polynomial y = p3*x^3 + p2*x^2 + p1*x + p0 in the interval x0 to x1.
newtonsMethod( x0, x1, p3, p2, p1, p0, tolerance )
{
iterations = 5;
x = ( x0 + x1 ) / 2;
offset = tolerance + 1;
while ( abs( offset ) > tolerance && iterations > 0)
{
value = (p3*x*x*x) + (p2*x*x) + (p1*x) + p0;
slope = (3*p3*x*x) + (2*p2*x) + p1;
AssertEx( slope != 0, "newtonsMethod found zero slope. Can't work with that." );
offset = -1 * value / slope;
oldx = x;
x += offset;
// Hack to keep the value within the bounds
if ( x > x1 )
x = ( oldX + (3*x1) ) / 4;
else if ( x < x0 )
x = ( oldX + (3*x0) ) / 4;
iterations--;
/# if ( iterations == 0 )
Print( "_interactive_utility::newtonsMethod failed to converge. x0:"+x0+", x1:"+x1+", p3:"+p3+", p2:"+p2+", p1:"+p1+", p0:"+p0+", x:"+x );
#/
}
return x;
}
// rootsOfCubic. Doesn't work.
rootsOfCubic(a,b,c,d)
{
if ( a == 0 ) {
return rootsOfQuadratic(b,c,d);
}
// I can't do this mathematically without having a cube root function.
q = (2*b*b*b) - (9*a*b*c) + (27*a*a*d);
//Q = sqrt( q*q*q );
bSquared3ac = (b*b) - (3*a*c);
if ( ( bSquared3ac == 0 ) )
{
// If ( bSquared3ac == 0 ) there's only one real root regardless of what q is, but I can't find it without a cube root function.
// root = cubeRoot( d/a );
}
if ( q == 0 && bSquared3ac==0 )
{
x[0] = -1 * b / (3*a);
}
else if ( q == 0 && bSquared3ac!=0 )
{
// There's a double root that I don't care about since it isn't a change from acceleration to deceleration
// The other root is
x[0] = ( (9*a*a*d) - (4*a*b*c) + (b*b*b) ) / ( a * ( (3*a*c) - (b*b) ) );
}
else
{
// Typical case...can't do it mathematically so do it numerically.
// Need to break the curve into intervals and use Newton's Method above.
}
}
rootsOfQuadratic(a,b,c)
{
// The spline code generates some big numbers which cause errors due to overflow
while ( abs(a)>65536 || abs(b)>65536 || abs(c)>65536 ) {
a /= 10;
b /= 10;
c /= 10;
}
x = [];
if ( a == 0 ) {
if ( b != 0 ) {
x[0] = -1 * c / b;
}
}
else {
bSquared4ac = (b*b) - (4*a*c);
if ( bSquared4ac > 0 ) {
x[0] = ( (-1*b) - sqrt( bSquared4ac ) ) / (2*a);
x[1] = ( (-1*b) + sqrt( bSquared4ac ) ) / (2*a);
}
else if ( bSquared4ac == 0 ) {
x[0] = -1 * b / (2*a);
}
}
// Note: If there are no roots, x will be empty.
return x;
}
// NonVectorLength
// Just like Length, but gets the length of a vector represented as an array.
// Optional second array will be sutracted (per-component) from the first. That is, NonVectorLength(origin1,origtin2) is the same as Length(origin1-origin2).
NonVectorLength( array, array2 )
{
AssertEx( ( !IsDefined(array2) ) || ( array.size==array2.size ), "NonVectorLength: second array must have same number of components as first array." );
sum = 0;
for ( i=0; i<array.size; i++ )
{
value = array[i];
if ( IsDefined(array2) ) value -= array2[i];
sum += value*value;
}
return sqrt( sum );
}
// clampAndNormalize
// Clamps x to the range min-max and then divides it by that range, to give a result between 0 and 1.
// Works for min<max and max<min.
clampAndNormalize( x, min, max )
{
AssertEx( min != max, "clampAndNormalize: min must not equal max" );
if ( min < max )
x = clamp( x, min, max );
else x = clamp( x, max, min );
return ( x - min ) / (max - min );
}
PointOnCircle( center, radius, deg )
{
x = Cos( deg );
x *= radius;
x += center[0];
y = Sin( deg );
y *= radius;
y += center[1];
z = center[2];
return (x,y,z);
}
zeroComponent( vector, comp )
{
return ( vector[0] * (comp != 0 ), vector[1] * (comp != 1 ), vector[2] * (comp != 2 ) );
}
rotate90AroundAxis( vector, comp )
{
if ( comp == 0 )
{
return ( vector[0], vector[2], -1 * vector[1] );
}
else if ( comp == 1 )
{
return ( -1 * vector[2], vector[1], vector[0] );
}
else
{
return ( vector[1], -1 * vector[0], vector[2] );
}
}

View File

@ -0,0 +1,136 @@
/*
* How to use this script:
* You need an exploder which creates the FX of the bats flying,
* and an animation which moves "tag_attach" along the flight path (for the sound).
* You need a trigger with a targetname, to detect if players are close to the bats spawn location.
* Then, just call vfxBatCaveWaitInit() with all those things.
*/
#include common_scripts\utility;
VFX_BAT_COOLDOWN = 60;
/*
=============
///ScriptDocBegin
"Name: vfxBatCaveWaitInit( <triggername> , <exploderID> , <audioAnim> , <pos> , <emptyRoomCooldown> )"
"Summary: Sets up a bat colony to detect players and play a bat exploder when a player fires his/her weapon nearby."
"Module: "
"CallOn: "
"MandatoryArg: <triggername>: Targetname of a trigger that will detect players."
"MandatoryArg: <exploderID>: ID of the exploder to be triggered."
"OptionalArg: <audioAnim>: Animation with 'tag_attach' moving along the path of the EFX, for a sound to be attached to."
"OptionalArg: <pos>: Position of the exploder, for the animation to be placed at."
"OptionalArg: <emptyRoomCooldown>: Time the trigger must be undisturbed before the exploder can fire again. If undefined or 0, the exploder can fire periodically even the trigger has never been empty."
"Example: thread vfxBatCaveWaitInit( "bats_1", 1, "bats_flyaway_1", (-2028, 464, 413) );"
"SPMP: both"
///ScriptDocEnd
=============
*/
vfxBatCaveWaitInit( triggername, exploderID, audioAnim, pos, emptyRoomCooldown )
{
if ( !IsDefined( emptyRoomCooldown ) )
emptyRoomCooldown = 0;
level endon( "game_ended" );
// get the trigger
trigger = GetEnt( triggername, "targetname" );
if ( IsDefined( trigger ) )
{
trigger childthread vfxBatCaveTrigger( exploderID, audioAnim, pos );
trigger childthread vfxBatCaveWatchForEmpty( emptyRoomCoolDown );
while ( true )
{
trigger waittill( "trigger", player );
trigger thread vfxBatCaveWatchPlayerState( player );
}
}
}
vfxBatCaveWatchPlayerState( player ) // self == bat trigger
{
// if any other player starts the bats, stop checking
self endon( "batCaveTrigger" );
player endon( "death" );
player endon( "disconnect" );
// make sure we aren't already runnning one
player notify( "batCaveExit" );
player endon( "batCaveExit" );
self childthread vfxBatCaveWatchPlayerWeapons( player );
// this detects if the player has exited the trigger
while ( player IsTouching( self ) )
{
waitframe();
self.lastTouchedTime = GetTime();
}
player notify( "batCaveExit" );
}
vfxBatCaveWatchPlayerWeapons( player )
{
player waittill( "weapon_fired" );
self notify ( "batCaveTrigger" );
}
vfxBatCaveWatchForEmpty( emptyRoomCoolDown )
{
self.lastTouchedTime = GetTime();
self.batCaveReset = true;
while ( true )
{
waitframe();
if ( self.lastTouchedTime + emptyRoomCoolDown <= GetTime() ) {
self.batCaveReset = true;
}
}
}
vfxBatCaveTrigger( exploderID, audioAnim, pos )
{
/#
SetDvarIfUninitialized( "scr_dbg_batcave_cooldown", VFX_BAT_COOLDOWN );
#/
while ( true )
{
self waittill( "batCaveTrigger" );
if ( self.batCaveReset ) {
vfxBatsFly( exploderID, audioAnim, pos );
self.batCaveReset = false;
waitTime = VFX_BAT_COOLDOWN;
/#
waitTime = GetDvarInt( "scr_dbg_batcave_cooldown" );
#/
wait ( waitTime );
}
}
}
// Plays the bats effect and moving sound
vfxBatsFly(exploderID, audioAnim, pos)
{
exploder(exploderID); // It's become pretty pointless to do these as exploders, but it works, so I'm leaving it for now.
// Play a sound that moves with the bats as they fly.
if ( IsDefined(audioAnim) && IsDefined(pos) ) {
soundrig = Spawn( "script_model", pos );
soundrig SetModel( "vulture_circle_rig" );
soundrig ScriptModelPlayAnim( audioAnim );
dummy = Spawn( "script_model", soundrig GetTagOrigin( "tag_attach" ) );
dummy LinkTo( soundrig, "tag_attach" );
wait(0.1); // Without this the sound won't play. Because the tag is inside the wall?
dummy PlaySoundOnMovingEnt( "scn_mp_swamp_bat_cave_big" );
}
}

View File

@ -0,0 +1,78 @@
// Interactive_models\crows_dlc.gsc
// At Nate's suggestion I'm trying not to entangle this with other systems. There are some things I can't avoid though.
// I introduced a level array called "_interactive" that I'll use for all this stuff that isn't a traditional destructible.
// However, my intention is that any given type of interactive object can have its own struct in this array.
// Crows are interactive_birds. They have a rig that all the birds attach to and different bird models for flying vs sitting.
// The 'dlc' version uses modified mp animations, which are hacky but still, it should be copied over the original version if
// we plan to continue using it for the next game. (NB: It hasn't been tested in SP yet.)
#include common_scripts\utility;
#using_animtree( "animals_dlc" );
main()
{
info = SpawnStruct();
info.interactive_type = "crows_dlc";
info.rig_model = "use_radiant_model";
info.rig_animtree = #animtree;
info.rig_numtags = 2;//backup, really handled in Radiant
info.bird_model["idle"] = "crow_fly";
info.bird_model["fly"] = "crow_fly";
info.bird_animtree = #animtree;
info.topSpeed = 300; // Inches per second.
info.accn = 75; // Use this for both acceleration and deceleration.
info.scareRadius = 600; // Default distance at which pigeons will leave perch to avoid player or AI.
info.death_effect = LoadFX( "fx/props/bird_feather_exp_black" );
info.birdmodel_anims = [];
info.rigmodel_anims = [];
info.birdmodel_anims[ "idle" ][ 0 ] = %crow_idle_1;
info.birdmodel_anims[ "idleweight" ][ 0 ] = 1;
info.birdmodel_anims[ "idle" ][ 1 ] = %crow_idle_2;
info.birdmodel_anims[ "idleweight" ][ 1 ] = 0.3;
info.birdmodel_anims[ "flying" ] = %crow_fly;
info.rigmodel_anims[ "flying" ] = %pigeon_flock_fly_loop;
info.rigmodel_anims[ "takeoff_wire" ] = %pigeon_flock_takeoff_wire; // These match the Radiant keypairs "interactive_takeoffAnim" and "interactive_landAnim"
info.rigmodel_anims[ "land_wire" ] = %pigeon_flock_land_wire;
info.rigmodel_anims[ "takeoff_ground" ] = %pigeon_flock_takeoff_ground;
info.rigmodel_anims[ "land_ground" ] = %pigeon_flock_land_ground;
info.rigmodel_anims[ "takeoff_inpipe" ] = %pigeon_flock_takeoff_inpipe;
info.rigmodel_anims[ "land_inpipe" ] = %pigeon_flock_land_inpipe;
if ( !isSP() ) {
info.birdmodel_anims[ "idlemp" ][ 0 ] = "crow_idle_1";
info.birdmodel_anims[ "idlemp" ][ 1 ] = "crow_idle_2";
info.birdmodel_anims[ "flyingmp" ] = "crow_fly";
// These _mp animations for the rig are a hack. They are identical to the SP animations in length and
// motion, but keep the tags all facing forward, since the MP animations can't be rotated the same way
// the SP ones can.
info.rigmodel_anims[ "flyingmp" ] = "pigeon_flock_fly_loop_mp";
info.rigmodel_anims[ "takeoff_wiremp" ] = "pigeon_flock_takeoff_wire_mp";
info.rigmodel_anims[ "land_wiremp" ] = "pigeon_flock_land_wire_mp";
info.rigmodel_anims[ "takeoff_groundmp" ] = "pigeon_flock_takeoff_ground_mp";
info.rigmodel_anims[ "land_groundmp" ] = "pigeon_flock_land_ground_mp";
info.rigmodel_anims[ "takeoff_inpipemp" ] = "pigeon_flock_takeoff_inpipe_mp";
info.rigmodel_anims[ "land_inpipemp" ] = "pigeon_flock_land_inpipe_mp";
/*info.rigmodel_anims[ "flyingmp" ] = "pigeon_flock_fly_loop";
info.rigmodel_anims[ "takeoff_wiremp" ] = "pigeon_flock_takeoff_wire";
info.rigmodel_anims[ "land_wiremp" ] = "pigeon_flock_land_wire";
info.rigmodel_anims[ "takeoff_groundmp" ] = "pigeon_flock_takeoff_ground";
info.rigmodel_anims[ "land_groundmp" ] = "pigeon_flock_land_ground";
info.rigmodel_anims[ "takeoff_inpipemp" ] = "pigeon_flock_takeoff_inpipe";
info.rigmodel_anims[ "land_inpipemp" ] = "pigeon_flock_land_inpipe";*/
}
info.sounds = [];
info.sounds[ "takeoff" ] = "anml_crow_startle_flyaway";
info.sounds[ "idle" ] = "anml_crow_idle";
//TODO JL will also need to change KVPs in 'prefabs/mp_shipment_ns/shns_interactive_crows.map' from 'sound_csv_include:animal_bird' to the new csv
PreCacheModel( info.rig_model );
foreach ( model in info.bird_model ) {
PreCacheModel( model );
}
if( !isdefined ( level._interactive ) )
level._interactive = [];
level._interactive[ info.interactive_type ] = info;
thread maps\interactive_models\_birds_dlc::birds(info);
}

View File

@ -0,0 +1,76 @@
// Interactive_models\Parakeets.gsc
// At Nate's suggestion I'm trying not to entangle this with other systems. There are some things I can't avoid though.
// I introduced a level array called "_interactive" that I'll use for all this stuff that isn't a traditional destructible.
// However, my intention is that any given type of interactive object can have its own struct in this array.
// Parakeets are interactive_birds. They have a rig that all the birds attach to and different bird models for flying vs sitting.
// The 'dlc' version uses modified mp animations, which are hacky but still, it should be copied over the original version if
// we plan to continue using it for the next game. (NB: It hasn't been tested in SP yet.)
#include common_scripts\utility;
#using_animtree( "animals_dlc" );
main()
{
info = SpawnStruct();
info.interactive_type = "parakeets_dlc";
info.rig_model = "pigeon_flock_rig";
info.rig_animtree = #animtree;
info.rig_numtags = 12;
info.bird_model["idle"] = "parakeet";
info.bird_model["fly"] = "parakeet_fly";
info.bird_animtree = #animtree;
info.topSpeed = 600; // Inches per second.
info.accn = 150; // Use this for both acceleration and deceleration.
info.scareRadius = 300; // Default distance at which pigeons will leave perch to avoid player or AI.
info.death_effect = LoadFX( "fx/props/chicken_exp_white" );
info.birdmodel_anims = [];
info.rigmodel_anims = [];
info.birdmodel_anims[ "idle" ][ 0 ] = %pigeon_idle;
info.birdmodel_anims[ "idleweight" ][ 0 ] = 1;
info.birdmodel_anims[ "idle" ][ 1 ] = %pigeon_idle_twitch_1;
info.birdmodel_anims[ "idleweight" ][ 1 ] = 0.3;
info.birdmodel_anims[ "flying" ] = %pigeon_flying_cycle;
info.rigmodel_anims[ "flying" ] = %pigeon_flock_fly_loop;
info.rigmodel_anims[ "takeoff_wire" ] = %pigeon_flock_takeoff_wire; // These match the Radiant keypairs "interactive_takeoffAnim" and "interactive_landAnim"
info.rigmodel_anims[ "land_wire" ] = %pigeon_flock_land_wire;
info.rigmodel_anims[ "takeoff_ground" ] = %pigeon_flock_takeoff_ground;
info.rigmodel_anims[ "land_ground" ] = %pigeon_flock_land_ground;
info.rigmodel_anims[ "takeoff_inpipe" ] = %pigeon_flock_takeoff_inpipe;
info.rigmodel_anims[ "land_inpipe" ] = %pigeon_flock_land_inpipe;
if ( !isSP() ) {
info.birdmodel_anims[ "idlemp" ][ 0 ] = "pigeon_idle";
info.birdmodel_anims[ "idlemp" ][ 1 ] = "pigeon_idle_twitch_1";
info.birdmodel_anims[ "flyingmp" ] = "pigeon_flying_cycle";
// These _mp animations for the rig are a hack. They are identical to the SP animations in length and
// motion, but keep the tags all facing forward, since the MP animations can't be rotated the same way
// the SP ones can.
info.rigmodel_anims[ "flyingmp" ] = "pigeon_flock_fly_loop_mp";
info.rigmodel_anims[ "takeoff_wiremp" ] = "pigeon_flock_takeoff_wire_mp";
info.rigmodel_anims[ "land_wiremp" ] = "pigeon_flock_land_wire_mp";
info.rigmodel_anims[ "takeoff_groundmp" ] = "pigeon_flock_takeoff_ground_mp";
info.rigmodel_anims[ "land_groundmp" ] = "pigeon_flock_land_ground_mp";
info.rigmodel_anims[ "takeoff_inpipemp" ] = "pigeon_flock_takeoff_inpipe_mp";
info.rigmodel_anims[ "land_inpipemp" ] = "pigeon_flock_land_inpipe_mp";
/*info.rigmodel_anims[ "flyingmp" ] = "pigeon_flock_fly_loop";
info.rigmodel_anims[ "takeoff_wiremp" ] = "pigeon_flock_takeoff_wire";
info.rigmodel_anims[ "land_wiremp" ] = "pigeon_flock_land_wire";
info.rigmodel_anims[ "takeoff_groundmp" ] = "pigeon_flock_takeoff_ground";
info.rigmodel_anims[ "land_groundmp" ] = "pigeon_flock_land_ground";
info.rigmodel_anims[ "takeoff_inpipemp" ] = "pigeon_flock_takeoff_inpipe";
info.rigmodel_anims[ "land_inpipemp" ] = "pigeon_flock_land_inpipe";*/
}
info.sounds = [];
info.sounds[ "takeoff" ] = "anml_bird_startle_flyaway";
PreCacheModel( info.rig_model );
foreach ( model in info.bird_model ) {
PreCacheModel( model );
}
if( !isdefined ( level._interactive ) )
level._interactive = [];
level._interactive[ info.interactive_type ] = info;
thread maps\interactive_models\_birds_dlc::birds(info);
}

View File

@ -0,0 +1,96 @@
#include common_scripts\utility;
/*
=============
///ScriptDocBegin
"Name: vulture_circling( <origin> )"
"Summary: Creates a vulture circling around the specified origin. Don't forget to include interactive_vulture_circling.csv in your zone file."
"Module: "
"CallOn: Nothing"
"MandatoryArg: <origin>: A vector specifying a point in space."
"Example: vulture_circling((105, -1320, 1600));"
"SPMP: Both"
///ScriptDocEnd
=============
*/
vulture_circling(origin, number)
{
if ( !IsDefined(number) )
number = 1;
if ( !IsDefined(level._interactive) ) {
level._interactive = [];
}
if ( !IsDefined(level._interactive["vultures"]) ) {
level._interactive["vultures"]["count"] = 0;
level._interactive["vultures"]["anims"][0] = "vulture_rig_circle";
level._interactive["vultures"]["anims"][1] = "vulture_rig_circle2";
level._interactive["vultures"]["anims"][2] = "vulture_rig_circle3";
level._interactive["vultures"]["rigs"] = [];
level._interactive["vultures"]["vultures"] = [];
}
for ( i=0; i<number; i++ ) {
newOrigin = origin + ( (0,0,50) * i );
if ( i > 0 )
newOrigin += (0,0,RandomIntRange(-20,20));
thread vulture_circling_internal(newOrigin);
}
}
vulture_circling_internal(origin)
{
count = level._interactive["vultures"]["rigs"].size;
yaw = RandomInt(360);
rig = Spawn( "script_model", origin );
rig.angles = (0, yaw, 0);
rig SetModel( "vulture_circle_rig" );
vulture = Spawn( "script_model", rig.origin );
vulture.angles = (0, yaw, 0);
vulture SetModel( "ng_vulture" );
vulture LinkTo( rig, "tag_attach" );
riganim = level._interactive["vultures"]["anims"][mod(count, 3)];
rig ScriptModelPlayAnim( riganim );
level._interactive["vultures"]["vultures"][count] = vulture;
level._interactive["vultures"]["rigs"][count] = rig;
vulture endon("death");
wait( RandomFloat(5) );
vulture ScriptModelPlayAnim( "vulture_fly_loop_all" );
}
/#
vultures_toggle_thread()
{
SetDevDvar("vultures_enable", "1");
while ( true ) {
while( GetDvarInt("vultures_enable") >= 1 )
{
wait .5;
}
IPrintLn("Deleting vultures");
positions = [];
foreach (vulture in level._interactive["vultures"]["vultures"] ) {
vulture Delete();
}
foreach ( rig in level._interactive["vultures"]["rigs"] ) {
positions[positions.size] = rig.origin;
rig Delete();
}
level._interactive["vultures"]["rigs"] = [];
level._interactive["vultures"]["vultures"] = [];
while( GetDvarInt("vultures_enable") < 1 )
{
wait .5;
}
IPrintLn("Adding vultures");
foreach ( position in positions ) {
thread vulture_circling(position);
}
}
}
#/

View File

@ -0,0 +1,63 @@
#include common_scripts\utility;
#using_animtree( "animated_props" );
main()
{
//level.init_animatedmodels_dump = false;
if ( !isdefined( level.anim_prop_models ) )
level.anim_prop_models = []; // this is what the LD puts in their map
// Do special MP anim precaching
model_keys = GetArrayKeys( level.anim_prop_models );
foreach ( model_key in model_keys )
{
anim_keys = GetArrayKeys( level.anim_prop_models[model_key] );
foreach ( anim_key in anim_keys )
PrecacheMpAnim( level.anim_prop_models[model_key][anim_key] );
//PrecacheMpAnim( level.anim_prop_models[ "foliage_tree_palm_bushy_1" ][ "strong" ] );
}
// wait until the end of the frame so that maps can init their trees
// in their _anim instead of only above _load
waittillframeend;
level.init_animatedmodels = [];
animated_models = getentarray( "animated_model", "targetname" );
//array_thread( animated_models, ::model_init );
// one or more of the models initialized by model_init() was not setup by the map
// so print this helpful note so the designer can see how to add it ot their level
//if ( level.init_animatedmodels_dump )
//assertmsg( "anims not cached for animated prop model, Repackage Zones and Rebuild Precache Script in Launcher:" );
array_thread_amortized( animated_models, ::animateModel, 0.05 );
level.init_animatedmodels = undefined;
}
// Disabled for now since we are precaching .animation prefabs in a non-standard way
/*model_init()
{
if ( !isdefined( level.anim_prop_models[ self.model ] ) )
level.init_animatedmodels_dump = true;
}*/
// TODO: When we have multiple animations, instead of choosing randomly, do round-robin to get an even spread
animateModel()
{
if ( IsDefined( self.animation ) )
{
animation = self.animation;
}
else
{
keys = GetArrayKeys( level.anim_prop_models[ self.model ] );
animkey = keys[ RandomInt( keys.size ) ];
animation = level.anim_prop_models[ self.model ][ animkey ];
}
self ScriptModelPlayAnim( animation );
self willNeverChange();
}

98
maps/mp/_areas.gsc Normal file
View File

@ -0,0 +1,98 @@
#include maps\mp\_utility;
#include common_scripts\utility;
/*QUAKED trigger_multiple_area (0.12 0.23 1.0)
defaulttexture="trigger"
"script_area" - A localized string that names the area. e.g. "MP_FLOWER_SHOP"
Defines an area that the player is in.*/
/*QUAKED trigger_multiple_softlanding (0.12 0.23 1.0)
defaulttexture="trigger"
"script_type" - "car", "boxes", "trash"
Defines a soft landing area.*/
init()
{
level.softLandingTriggers = getEntArray( "trigger_multiple_softlanding", "classname" );
destructibles = getEntArray( "destructible_vehicle", "targetname" );
foreach ( trigger in level.softLandingTriggers )
{
if ( trigger.script_type != "car" )
continue;
foreach ( destructible in destructibles )
{
/*
if ( !trigger isTouching( destructible ) )
{
println( distance( trigger.origin, destructible.origin ) );
continue;
}
*/
if ( distance( trigger.origin, destructible.origin ) > 64.0 )
continue;
assert( !isDefined( trigger.destructible ) );
trigger.destructible = destructible;
}
}
//foreach ( trigger in level.softLandingTriggers )
// trigger thread common_scripts\_dynamic_world::triggerTouchThink( ::playerEnterSoftLanding, ::playerLeaveSoftLanding );
thread onPlayerConnect();
}
onPlayerConnect()
{
for ( ;; )
{
level waittill ( "connected", player );
player.softLanding = undefined;
player thread softLandingWaiter();
}
}
playerEnterSoftLanding( trigger )
{
self.softLanding = trigger;
}
playerLeaveSoftLanding( trigger )
{
self.softLanding = undefined;
}
softLandingWaiter()
{
self endon ( "disconnect" );
for ( ;; )
{
self waittill ( "soft_landing", trigger, damage );
//if ( damage < 10 )
// continue;
if ( !isDefined( trigger.destructible ) )
continue;
//magicBullet( "mp5_mp", self.origin, self.origin + (0,0,-100), self );
//self waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, dflags );
//traceData = bulletTrace( self.origin, self.origin + (0,0,-100), true, self );
}
}

714
maps/mp/_art.gsc Normal file
View File

@ -0,0 +1,714 @@
// This function should take care of grain and glow settings for each map, plus anything else that artists
// need to be able to tweak without bothering level designers.
#include common_scripts\utility;
#include common_scripts\_artCommon;
#include maps\mp\_utility;
main()
{
/#
PrecacheMenu( "dev_vision_noloc" );
PrecacheMenu( "dev_vision_exec" );
setDevDvarIfUninitialized( "scr_art_tweak", 0 );
setDevDvarIfUninitialized( "scr_cmd_plr_sun", "0" );
SetDevDvarIfUninitialized( "scr_cmd_plr_sunflare", "0" );
setDevDvarIfUninitialized( "scr_art_visionfile", level.script );
SetDevDvar( "r_artUseTweaks", false );
thread tweakart();
tess_init();
if ( !isdefined( level.script ) )
level.script = ToLower( GetDvar( "mapname" ) );
#/
}
/#
initTweaks()
{
SetDevDvar( "r_artUseTweaks", true );
if ( IsDefined( level.parse_fog_func ) )
[[level.parse_fog_func]]();
if ( !IsDefined( level.buttons ) )
level.buttons = [];
level._clearalltextafterhudelem = false;
if ( !IsDefined( level.vision_set_names ) )
level.vision_set_names = [];
if( !IsDefined( level.vision_set_fog ) )
{
level.vision_set_fog = [];
create_default_vision_set_fog( level.script );
common_scripts\_artCommon::setfogsliders();
}
foreach( key, value in level.vision_set_fog )
{
common_scripts\_artCommon::add_vision_set_to_list( key );
}
add_vision_sets_from_triggers();
update_current_vision_set_dvars();
if ( !IsDefined( level.current_vision_set ) )
level.current_vision_set = GetDvar( "r_artTweaksLastVisionSet", "" );
IPrintLnBold( "ART TWEAK ENABLED" );
hud_init();
last_vision_set = level.current_vision_set;
if ( !IsDefined( last_vision_set ) || last_vision_set == "" )
last_vision_set = level.script;
setcurrentgroup( last_vision_set );
}
tweakart()
{
if ( !isdefined( level.tweakfile ) )
level.tweakfile = false;
// not in DEVGUI
SetDevDvar( "scr_fog_fraction", "1.0" );
SetDevDvar( "scr_art_dump", "0" );
printed = false;
last_vision_set = "";
for ( ;; )
{
while ( GetDvarInt( "scr_art_tweak", 0 ) == 0 )
wait .05;
if ( !printed )
{
printed = true;
initTweaks();
}
//translate the slider values to script variables
common_scripts\_artCommon::translateFogSlidersToScript();
common_scripts\_artCommon::fogslidercheck();
updateSunFlarePosition();
dumpsettings();
updateFogFromScript();
if ( getdvarint( "scr_select_art_next" ) || button_down( "dpad_down", "kp_downarrow" ) )
setgroup_down();
else if ( getdvarint( "scr_select_art_prev" ) || button_down( "dpad_up", "kp_uparrow" ) )
setgroup_up();
else if( level.current_vision_set != last_vision_set )
{
last_vision_set = level.current_vision_set;
setcurrentgroup( last_vision_set );
}
wait .05;
}
}
tess_init()
{
using_tessellation = GetDvar( "r_tessellation" );
if( using_tessellation == "" )
{
return;
}
level.tess = SpawnStruct();
// Default Tessellation Values - push base settings to game values
level.tess.cutoff_distance_current = GetDvarFloat( "r_tessellationCutoffDistanceBase", 960.0 );
level.tess.cutoff_distance_goal = level.tess.cutoff_distance_current;
level.tess.cutoff_falloff_current = GetDvarFloat( "r_tessellationCutoffFalloffBase", 320.0 );
level.tess.cutoff_falloff_goal = level.tess.cutoff_falloff_current;
level.tess.time_remaining = 0.0;
SetDvar( "r_tessellationCutoffDistance", level.tess.cutoff_distance_current );
SetDvar( "r_tessellationCutoffFalloff" , level.tess.cutoff_falloff_current );
thread tess_update();
}
tess_set_goal( cutoff_distance, cutoff_falloff, blend_time )
{
level.tess.cutoff_distance_goal = cutoff_distance;
level.tess.cutoff_falloff_goal = cutoff_falloff;
level.tess.time_remaining = blend_time;
}
tess_update()
{
while ( 1 )
{
cutoff_distance_old = level.tess.cutoff_distance_current;
cutoff_falloff_old = level.tess.cutoff_falloff_current;
waitframe();
if ( level.tess.time_remaining > 0.0 )
{
frames = level.tess.time_remaining * 20;
distance_increment = ( level.tess.cutoff_distance_goal - level.tess.cutoff_distance_current ) / frames;
falloff_increment = ( level.tess.cutoff_falloff_goal - level.tess.cutoff_falloff_current ) / frames;
level.tess.cutoff_distance_current += distance_increment;
level.tess.cutoff_falloff_current += falloff_increment;
level.tess.time_remaining -= 0.05;
}
else
{
level.tess.cutoff_distance_current = level.tess.cutoff_distance_goal;
level.tess.cutoff_falloff_current = level.tess.cutoff_falloff_goal;
}
if( cutoff_distance_old != level.tess.cutoff_distance_current )
{
SetDvar( "r_tessellationCutoffDistance", level.tess.cutoff_distance_current );
}
if( cutoff_falloff_old != level.tess.cutoff_falloff_current )
{
SetDvar( "r_tessellationCutoffFalloff" , level.tess.cutoff_falloff_current );
}
}
}
updateSunFlarePosition()
{
if ( GetDvarInt( "scr_cmd_plr_sunflare" ) )
{
SetDevDvar( "scr_cmd_plr_sunflare", 0 );
pos = level.players[0] GetPlayerAngles();
// Output the pos to the window
pos_string = "Sun Flare = ( " + pos[0] + ", " + pos[1] + ", " + pos[2] + " )";
IPrintLnBold( pos_string );
Print( pos_string );
}
}
dumpsettings()
{
if ( GetDvarInt( "scr_art_dump" ) == 0 )
return false;
SetdevDvar( "scr_art_dump", "0" );
////////////////// [level]_art.gsc
fileprint_launcher_start_file();
fileprint_launcher( "// _createart generated. modify at your own risk. Changing values should be fine." );
fileprint_launcher( "main()" );
fileprint_launcher( "{" );
fileprint_launcher( "\tlevel.tweakfile = true;" );
if ( IsDefined( level.parse_fog_func ) ) // Don't print this unless it already exists (otherwise [levelname]_fog.gsc will likely fail to compile)
fileprint_launcher( "\tlevel.parse_fog_func = maps\\createart\\" + level.script + "_fog::main;" );
fileprint_launcher( "" );
fileprint_launcher( "\tsetDevDvar( \"scr_fog_disable\"" + ", " + "\"" + GetDvarInt( "scr_fog_disable" ) + "\"" + " );" );
// Writing this out in case someone needs it
if ( ! GetDvarInt( "scr_fog_disable" ) )
{
if ( level.sunFogEnabled )
fileprint_launcher( "//\tsetExpFog( " + level.fognearplane + ", " + level.fogexphalfplane + ", " + level.fogcolor[0] + ", " + level.fogcolor[1] + ", " + level.fogcolor[2] + ", " + level.fogHDRColorIntensity + ", " + level.fogmaxopacity + ", 0, " + level.sunFogColor[0] + ", " + level.sunFogColor[1] + ", " + level.sunFogColor[2] + ", " + level.sunFogHDRColorIntensity + ", (" + level.sunFogDir[0] + ", " + level.sunFogDir[1] + ", " + level.sunFogDir[2] + "), " + level.sunFogBeginFadeAngle + ", " + level.sunFogEndFadeAngle + ", " + level.sunFogScale + ", " + level.skyFogIntensity + ", " + level.skyFogMinAngle + ", " + level.skyFogMaxAngle + " );" );
else
fileprint_launcher( "//\tsetExpFog( " + level.fognearplane + ", " + level.fogexphalfplane + ", " + level.fogcolor[0] + ", " + level.fogcolor[1] + ", " + level.fogcolor[2] + ", " + level.fogHDRColorIntensity + ", " + level.fogmaxopacity + ", 0, " + level.skyFogIntensity + ", " + level.skyFogMinAngle + ", " + level.skyFogMaxAngle + " );" );
}
fileprint_launcher( "\tVisionSetNaked( \"" + level.script + "\", 0 );" );
fileprint_launcher( "}" );
if ( !fileprint_launcher_end_file( "\\share\\raw\\maps\\createart\\" + level.script + "_art.gsc", true ) )
return;
//////////////////////////////
// MP doesn't write [level]_art.csv?
////////////////// [level]_fog.gsc
if ( IsDefined( level.parse_fog_func ) )
{
fileprint_launcher_start_file();
fileprint_launcher( "// _createart generated. modify at your own risk. Do not use block comments." );
fileprint_launcher( "main()" );
fileprint_launcher( "{" );
common_scripts\_artCommon::print_fog_ents( true );
fileprint_launcher( "}" );
if ( !fileprint_launcher_end_file( "\\share\\raw\\maps\\createart\\" + level.script + "_fog.gsc", true ) )
return;
}
//////////////////////////////
////////////////// [level].vision
if ( !common_scripts\_artCommon::print_vision( level.current_vision_set ) )
return;
iprintlnbold( "Save successful!" );
PrintLn( "Art settings dumped success!" );
}
add_vision_sets_from_triggers()
{
assert( IsDefined( level.vision_set_fog ) );
triggers = GetEntArray( "trigger_multiple_visionset" , "classname" );
// mkornkven: probably won't get anything -- need a way to get at the client trigger data?
foreach( trigger in triggers )
{
name = undefined;
if( IsDefined( trigger.script_visionset ) )
name = ToLower( trigger.script_visionset );
else if ( IsDefined( trigger.script_visionset_start ) )
name = ToLower( trigger.script_visionset_start );
else if ( IsDefined( trigger.script_visionset_end ) )
name = ToLower( trigger.script_visionset_end );
if ( IsDefined( name ) )
add_vision_set( name );
}
}
add_vision_set( vision_set_name )
{
assert( vision_set_name == ToLower( vision_set_name ) );
if ( IsDefined( level.vision_set_fog[ vision_set_name ] ) )
return;
create_default_vision_set_fog( vision_set_name );
common_scripts\_artCommon::add_vision_set_to_list( vision_set_name );
IPrintLnBold( "new vision: " + vision_set_name );
}
button_down( btn, btn2 )
{
pressed = level.players[0] ButtonPressed( btn );
if ( !pressed )
{
pressed = level.players[0] ButtonPressed( btn2 );
}
if ( !IsDefined( level.buttons[ btn ] ) )
{
level.buttons[ btn ] = 0;
}
// To Prevent Spam
if ( GetTime() < level.buttons[ btn ] )
{
return false;
}
level.buttons[ btn ] = GetTime() + 400;
return pressed;
}
updateFogFromScript()
{
if ( GetDvarInt( "scr_cmd_plr_sun" ) )
{
SetDevDvar( "scr_sunFogDir", AnglesToForward( level.players[0] GetPlayerAngles() ) );
SetDevDvar( "scr_cmd_plr_sun", 0 );
}
ent = get_fog_ent_for_vision_set( level.current_vision_set );
if( IsDefined( ent ) && isdefined( ent.name ) )
{
ent.startDist = level.fognearplane;
ent.halfwayDist = level.fogexphalfplane;
ent.red = level.fogcolor[ 0 ];
ent.green = level.fogcolor[ 1 ];
ent.blue = level.fogcolor[ 2 ];
ent.HDRColorIntensity = level.fogHDRColorIntensity;
ent.maxOpacity = level.fogmaxopacity;
ent.sunFogEnabled = level.sunFogEnabled;
ent.sunRed = level.sunFogColor[ 0 ];
ent.sunGreen = level.sunFogColor[ 1 ];
ent.sunBlue = level.sunFogColor[ 2 ];
ent.HDRSunColorIntensity = level.sunFogHDRColorIntensity;
ent.sunDir = level.sunFogDir;
ent.sunBeginFadeAngle = level.sunFogBeginFadeAngle;
ent.sunEndFadeAngle = level.sunFogEndFadeAngle;
ent.normalFogScale = level.sunFogScale;
ent.skyFogIntensity = level.skyFogIntensity;
ent.skyFogMinAngle = level.skyFogMinAngle;
ent.skyFogMaxAngle = level.skyFogMaxAngle;
if ( GetDvarInt( "scr_fog_disable" ) )
{
ent.startDist = 2000000000;
ent.halfwayDist = 2000000001;
ent.red = 0;
ent.green = 0;
ent.blue = 0;
ent.HDRSunColorIntensity = 1;
ent.maxOpacity = 0;
ent.skyFogIntensity = 0;
}
if ( IsDefined( level.parse_fog_func ) ) // Otherwise, this is the default set, which we don't want to set
set_fog_to_ent_values( ent, 0 );
}
}
update_current_vision_set_dvars()
{
level.players[0] openpopupmenu("dev_vision_exec");
wait( 0.05 );
level.players[0] closepopupmenu();
}
vision_set_changes( vision_set )
{
// Set the vision set and push the values to tweak dvars in code
VisionSetNaked( vision_set, 0 );
update_current_vision_set_dvars();
level.current_vision_set = vision_set;
}
vision_set_fog_changes( vision_set, transition_time )
{
vision_set_changes( vision_set );
fog_ent = get_fog_ent_for_vision_set( vision_set );
if ( IsDefined( fog_ent ) )
{
translateFogEntTosliders( fog_ent );
if ( IsDefined( level.parse_fog_func ) ) // Otherwise, this is the default set, which we don't want to set
set_fog_to_ent_values( fog_ent, transition_time);
}
}
get_fog_ent_for_vision_set( vision_set )
{
fog_ent = level.vision_set_fog[ ToLower( vision_set ) ];
if ( using_hdr_fog() && IsDefined( fog_ent ) && IsDefined( fog_ent.HDROverride ) )
fog_ent = level.vision_set_fog[ ToLower( fog_ent.HDROverride ) ];
return fog_ent;
}
using_hdr_fog()
{
if ( !IsDefined( level.console ) )
set_console_status();
AssertEx( IsDefined( level.console ) && IsDefined( level.xb3 ) && IsDefined( level.ps4 ), "Expected platform defines to be complete." );
return is_gen4();
}
translateFogEntTosliders( ent )
{
SetDevDvar( "scr_fog_exp_halfplane", ent.halfwayDist );
SetDevDvar( "scr_fog_nearplane", ent.startDist );
SetDevDvar( "scr_fog_color", ( ent.red, ent.green, ent.blue ) );
SetDevDvar( "scr_fog_color_intensity", ent.HDRColorIntensity );
SetDevDvar( "scr_fog_max_opacity", ent.maxOpacity );
SetDevDvar( "scr_skyFogIntensity", ent.skyFogIntensity );
SetDevDvar( "scr_skyFogMinAngle", ent.skyFogMinAngle );
SetDevDvar( "scr_skyFogMaxAngle", ent.skyFogMaxAngle );
if ( IsDefined( ent.sunFogEnabled ) && ent.sunFogEnabled )
{
SetDevDvar( "scr_sunFogEnabled", 1 );
SetDevDvar( "scr_sunFogColor", ( ent.sunRed, ent.sunGreen,ent.sunBlue ) );
SetDevDvar( "scr_sunFogColorIntensity", ent.HDRSunColorIntensity );
SetDevDvar( "scr_sunFogDir", ent.sunDir );
SetDevDvar( "scr_sunFogBeginFadeAngle", ent.sunBeginFadeAngle );
SetDevDvar( "scr_sunFogEndFadeAngle", ent.sunEndFadeAngle );
SetDevDvar( "scr_sunFogScale", ent.normalFogScale );
}
else
{
SetDevDvar( "scr_sunFogEnabled", 0 );
}
}
set_fog_to_ent_values( ent, transition_time )
{
if ( IsDefined( ent.sunFogEnabled) && ent.sunFogEnabled )
{
if ( !isPlayer( self ) )
{
SetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.sunRed,
ent.sunGreen,
ent.sunBlue,
ent.HDRSunColorIntensity,
ent.sunDir,
ent.sunBeginFadeAngle,
ent.sunEndFadeAngle,
ent.normalFogScale,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
else
{
self PlayerSetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.sunRed,
ent.sunGreen,
ent.sunBlue,
ent.HDRSunColorIntensity,
ent.sunDir,
ent.sunBeginFadeAngle,
ent.sunEndFadeAngle,
ent.normalFogScale,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
}
else
{
if ( !isPlayer( self ) )
{
SetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
else
{
self PlayerSetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
}
}
create_default_vision_set_fog( name )
{
ent = create_vision_set_fog( name );
ent.startDist = 3764.17;
ent.halfwayDist = 19391;
ent.red = 0.661137;
ent.green = 0.554261;
ent.blue = 0.454014;
ent.maxOpacity = 0.7;
ent.transitionTime = 0;
ent.skyFogIntensity = 0;
ent.skyFogMinAngle = 0;
ent.skyFogMaxAngle = 0;
}
hud_init()
{
listsize = 7;
hudelems = [];
spacer = 15;
div = int( listsize / 2 );
org = 240 - div * spacer;
alphainc = .5 / div;
alpha = alphainc;
for ( i = 0;i < listsize;i++ )
{
hudelems[ i ] = _newhudelem();
hudelems[ i ].location = 0;
hudelems[ i ].alignX = "left";
hudelems[ i ].alignY = "middle";
hudelems[ i ].foreground = 1;
hudelems[ i ].fontScale = 2;
hudelems[ i ].sort = 20;
if ( i == div )
hudelems[ i ].alpha = 1;
else
hudelems[ i ].alpha = alpha;
hudelems[ i ].x = 20;
hudelems[ i ].y = org;
hudelems[ i ] _settext( "." );
if ( i == div )
alphainc *= -1;
alpha += alphainc;
org += spacer;
}
level.spam_group_hudelems = hudelems;
}
_newhudelem()
{
if ( !isdefined( level.scripted_elems ) )
level.scripted_elems = [];
elem = newhudelem(); // client?
level.scripted_elems[ level.scripted_elems.size ] = elem;
return elem;
}
_settext( text )
{
self.realtext = text;
self setDevText( "_" );
self thread _clearalltextafterhudelem();
sizeofelems = 0;
foreach ( elem in level.scripted_elems )
{
if ( isdefined( elem.realtext ) )
{
sizeofelems += elem.realtext.size;
elem setDevText( elem.realtext );
}
}
println( "Size of elems: " + sizeofelems );
}
_clearalltextafterhudelem()
{
if ( level._clearalltextafterhudelem )
return;
level._clearalltextafterhudelem = true;
self clearalltextafterhudelem();
wait .05;
level._clearalltextafterhudelem = false;
}
setgroup_up()
{
reset_cmds();
current_vision_set_name = level.current_vision_set;
index = array_find( level.vision_set_names, current_vision_set_name );
if ( !IsDefined( index ) )
return;
index -= 1;
if ( index < 0 )
return;
setcurrentgroup( level.vision_set_names[index] );
}
setgroup_down()
{
reset_cmds();
current_vision_set_name = level.current_vision_set;
index = array_find( level.vision_set_names, current_vision_set_name );
if ( !IsDefined( index ) )
return;
index += 1;
if ( index >= level.vision_set_names.size )
return;
setcurrentgroup( level.vision_set_names[index] );
}
reset_cmds()
{
SetDevDvar( "scr_select_art_next", 0 );
SetDevDvar( "scr_select_art_prev", 0 );
}
setcurrentgroup( group )
{
level.spam_model_current_group = group;
index = array_find( level.vision_set_names, group );
if ( !IsDefined( index ) )
index = -1;
hud_list_size = level.spam_group_hudelems.size;
hud_start_index = index - int( hud_list_size / 2 );
for ( i = 0; i < hud_list_size; i++ )
{
hud_index = hud_start_index + i;
if ( hud_index < 0 || hud_index >= level.vision_set_names.size )
{
level.spam_group_hudelems[i] _settext( "." );
continue;
}
level.spam_group_hudelems[i] _settext( level.vision_set_names[hud_index] );
}
group_name = "";
if ( index >= 0 )
group_name = level.vision_set_names[ index ];
vision_set_fog_changes( group_name, 0 );
}
#/
create_vision_set_fog( fogsetName )
{
/#
if ( !isdefined( level.vision_set_fog ) )
level.vision_set_fog = [];
ent = SpawnStruct();
ent.name = fogsetName;
// Special init for variables that may not exist on every set of fog yet -- add variable defaults here to avoid IsDefined checks everywhere later on
ent.HDRColorIntensity = 1;
ent.HDRSunColorIntensity = 1;
ent.skyFogIntensity = 0;
ent.skyFogMinAngle = 0;
ent.skyFogMaxAngle = 0;
level.vision_set_fog[ ToLower(fogsetName) ] = ent;
return ent;
#/
}

139
maps/mp/_audio.gsc Normal file
View File

@ -0,0 +1,139 @@
#include maps\mp\_utility;
#include common_scripts\utility;
init_audio()
{
if ( !IsDefined( level.audio ) )
{
level.audio = SpawnStruct();
}
init_reverb();
init_whizby();
level.onPlayerConnectAudioInit = ::OnPlayerConnectAudioInit;
}
OnPlayerConnectAudioInit()
{
self apply_reverb( "default" );
// self apply_whizby(); <-- Does not work yet... Looks like it overflows the server.
}
//---------------------------------------------------------
// Reverb Section
//---------------------------------------------------------
init_reverb()
{
add_reverb( "default", "generic", 0.15, 0.9, 2 );
}
add_reverb( name, type, wetlevel, drylevel, fadetime )
{
Assert( IsDefined( type ) );
Assert( IsDefined( wetlevel ) );
Assert( IsDefined( drylevel ) );
reverb = [];
is_roomtype_valid( type );
reverb[ "roomtype" ] = type;
reverb[ "wetlevel" ] = wetlevel;
reverb[ "drylevel" ] = drylevel;
reverb[ "fadetime" ] = fadetime;
level.audio.reverb_settings[ name ] = reverb;
}
is_roomtype_valid( type )
{
/#
switch ( type )
{
case "generic":
case "paddedcell":
case "room":
case "bathroom":
case "livingroom":
case "stoneroom":
case "auditorium":
case "concerthall":
case "cave":
case "arena":
case "hangar":
case "carpetedhallway":
case "hallway":
case "stonecorridor":
case "alley":
case "forest":
case "city":
case "mountains":
case "quarry":
case "plain":
case "parkinglot":
case "sewerpipe":
case "underwater":
case "drugged":
case "dizzy":
case "psychotic":
return;
default:
AssertMsg( type + " is an Invalid Roomtype" );
break;
}
#/
}
apply_reverb( name )
{
if ( !IsDefined( level.audio.reverb_settings[ name ] ) )
{
reverb = level.audio.reverb_settings[ "default" ];
}
else
{
reverb = level.audio.reverb_settings[ name ];
}
self SetReverb( "snd_enveffectsprio_level", reverb[ "roomtype" ], reverb[ "drylevel" ], reverb[ "wetlevel" ], reverb[ "fadetime" ] );
// self SetClientDvar( "cg_levelReverbRoomType", reverb[ "roomtype" ] );
// self SetClientDvar( "cg_levelReverbDryLevel", reverb[ "drylevel" ] );
// self SetClientDvar( "cg_levelReverbWetLevel", reverb[ "wetlevel" ] );
}
//---------------------------------------------------------
// whizBy Section
//---------------------------------------------------------
init_whizby()
{
SetDevDvar( "snd_newwhizby", 1 );
// Default settings -- Call wrappers in your level to overwrite.
level.audio.whizby_settings = [];
set_whizby_radius( 15.0, 30.0, 50.0 );
set_whizby_spread( 150.0, 250.0, 350.0 );
}
set_whizby_radius( near, medium, far )
{
assertex( near != 0, "whizby near radius cannot be zero" );
level.audio.whizby_settings[ "radius" ] = [ near, medium, far ];
}
set_whizby_spread( near, medium, far )
{
level.audio.whizby_settings[ "spread" ] = [ near, medium, far ];
}
apply_whizby()
{
settings = level.audio.whizby_settings;
spread = settings[ "spread" ];
rad = settings[ "radius" ];
self SetWhizbySpreads( spread[ 0 ], spread[ 1 ], spread[ 2 ] );
self SetWhizbyRadii( rad[ 0 ], rad[ 1 ], rad[ 2 ] );
}

1084
maps/mp/_awards.gsc Normal file

File diff suppressed because it is too large Load Diff

335
maps/mp/_barrels_leak.gsc Normal file
View File

@ -0,0 +1,335 @@
#include common_scripts\utility;
//////////////////////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////////////////////
level_limit_barrel_fx = 8;
max_fires_from_entity = 4;
level_barrel_fx_chance = 33;
//////////////////////////////////////////////////////////////////////////////
// LOGIC //
//////////////////////////////////////////////////////////////////////////////
main()
{
if ( IsDefined( level.barrels_init ) )
return;
level.barrels_init = true;
//level._barrel_fx_time = 25; //handle this individually for different barrel types
barrels = GetEntArray( "barrel_shootable", "targetname" );
if ( !barrels.size )
return;
level._barrels = SpawnStruct();
level._barrels.num_barrel_fx = 0;
barrels thread precacheFX();
barrels thread methodsInit();
thread post_load( barrels );
}
post_load( barrels )
{
waittillframeend;// insure that structs are initialized
if( level.createFX_enabled )
return;
array_thread( barrels, ::barrelsetup );
}
barrelsetup()
{
self SetCanDamage( true );
self SetCanRadiusDamage( false ); // optimization
self.barrel_fx_array = [];
node = undefined;
if ( IsDefined( self.target ) )
{
node = getstruct( self.target, "targetname" );
self.A = node.origin;
vec = AnglesToForward( node.angles );
vec = ( vec * 128 );
self.B = self.A + vec;
}
else
{
vec = AnglesToForward( self.angles );
vec1 = ( vec * 64 );
self.A = self.origin + vec1;
vec1 = ( vec * -64 );
self.B = self.origin + vec1;
}
self thread barrel_wait_loop();
}
barrel_wait_loop()
{
P = ( 0, 0, 0 );// just to initialize P as a vector
hasTakenDamage = false;
remaining = max_fires_from_entity;
while ( 1 )
{
self waittill( "damage", damage, attacker, direction_vec, P, type );
// random so we don't get so many fx, but the very first time is guarenteed
if ( hasTakenDamage )
{
if ( randomint( 100 ) <= level_barrel_fx_chance )
continue;
}
hasTakenDamage = true;
result = self barrel_logic( direction_vec, P, type, attacker );
if ( result )
remaining--;
if ( remaining <= 0 )
break;
}
self SetCanDamage( false );
}
barrel_logic( direction_vec, P, type, damageOwner )
{
if ( level._barrels.num_barrel_fx > level_limit_barrel_fx )
return false;
if ( !isDefined( level._barrels._barrel_methods[ type ] ) )
P = self barrel_calc_nofx( P, type );
else
P = self [[ level._barrels._barrel_methods[ type ] ]]( P, type );
if ( !isdefined( P ) )
return false;
if ( IsDefined( damageOwner.classname ) && damageOwner.classname == "worldspawn" )
return false;
foreach ( value in self.barrel_fx_array )
{
if ( DistanceSquared( P, value.origin ) < 25 )
return false;
}
//calculate the vector derived from the center line of our barrel and the point of damage
// generate a vector from the attacker's eye to the impact point (AI) or origin to impact point (non-AI)
E = undefined;
if( IsAI( damageOwner ))
E = damageOwner GetEye();
else
E = damageOwner.origin;
temp_vec = P - E;
// Extend the vector (this is to ensure it intersects the damaged entity, tracing to the point itself generated new points which were slightly off and bad normals) and return a trace
trace = BulletTrace ( E, E + 1.5 * temp_vec, false, damageOwner, false );
if ( isdefined ( trace [ "normal" ] ) && isdefined ( trace [ "entity" ] ) && trace ["entity"] == self )
{
vec = trace[ "normal" ];
// Use the surface normal of the impact point to generate the angles for the burst effect
self thread barrelfx( P, vec, damageOwner );
return true;
}
return false;
}
//DC_NOTE commented out all sound related stuff because it was giving me grief in mp_zulu
barrelfx( P, vec, damageOwner )
{
time = level._barrels.fx_time[ self.script_noteworthy ] ;
fx_time = level._barrels._barrel_fx_time[ self.script_noteworthy ] ;
intervals = Int( fx_time / time );// loops for 25 seconds
intervals_end = 30;
hitsnd = level._barrels._sound[ self.script_noteworthy + "_hit" ];
loopsnd = level._barrels._sound[ self.script_noteworthy + "_loop" ];
endsnd = level._barrels._sound[ self.script_noteworthy + "_end" ];
snd = Spawn( "script_origin", P );
// snd Hide();
snd PlaySound( hitsnd );
snd PlayLoopSound( loopsnd );
self.barrel_fx_array[ self.barrel_fx_array.size ] = snd;
// if ( isSP() || self.script_noteworthy != "steam" )
if ( isSP() )
self thread barrel_damage( P, vec, damageOwner, snd );
//rotate the emitter angle over time
efx_rot = Spawn( "script_model", P );
efx_rot SetModel( "tag_origin" );
efx_rot.angles = VectorToAngles( vec );
wait .05;//cant play fx on same frame it's spawned in mp appearantly
PlayFXOnTag( level._barrels._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
level._barrels.num_barrel_fx++;
efx_rot RotatePitch( 90, time, 1, 1 );
wait time;
StopFXOnTag( level._barrels._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
intervals--;
//now check for other fx and rest of intervals
while ( level._barrels.num_barrel_fx <= level_limit_barrel_fx && intervals > 0 )
{
efx_rot = Spawn( "script_model", P );
efx_rot SetModel( "tag_origin" );
efx_rot.angles = VectorToAngles( vec );
wait .05;//cant play fx on same frame it's spawned in mp appearantly
PlayFXOnTag( level._barrels._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
level._barrels.num_barrel_fx++;
efx_rot RotatePitch( 90, time, 1, 1 );
wait time;
StopFXOnTag( level._barrels._effect[ self.script_noteworthy ] , efx_rot, "tag_origin" );
}
// snd PlaySound( endsnd );
wait( .5 );
// snd StopLoopSound( loopsnd );
snd Delete();
self.barrel_fx_array = array_removeUndefined( self.barrel_fx_array );
level._barrels.num_barrel_fx--;
}
barrel_damage( P, vec, damageOwner, fx )
{
if ( !allow_barrel_damage() )
return;
fx endon( "death" );
origin = fx.origin + ( VectorNormalize( vec ) * 40 );
dmg = level._barrels._dmg[ self.script_noteworthy ];
while ( 1 )
{
// do not pass damage owner if they have disconnected before the barrels explode.. the barrels?
if ( !isdefined( self.damageOwner ) )
{
// MOD_TRIGGER_HURT so they dont do dirt on the player's screen
self RadiusDamage( origin, 36, dmg, dmg * 0.75, undefined, "MOD_TRIGGER_HURT" );
}
else
{
// MOD_TRIGGER_HURT so they dont do dirt on the player's screen
self RadiusDamage( origin, 36, dmg, dmg * 0.75, damageOwner, "MOD_TRIGGER_HURT" );
}
wait( 0.4 );
}
}
allow_barrel_damage()
{
if( !isSP() )
return false;
if ( !isDefined( level.barrelsDamage ) )
return false;
return ( level.barrelsDamage );
}
//////////////////////////////////////////////////////////////////////////////
// CALCULATIONS / SETUP //
//////////////////////////////////////////////////////////////////////////////
methodsInit()
{
level._barrels._barrel_methods = [];
level._barrels._barrel_methods[ "MOD_UNKNOWN" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_PISTOL_BULLET" ] = ::barrel_calc_ballistic;
level._barrels._barrel_methods[ "MOD_RIFLE_BULLET" ] = ::barrel_calc_ballistic;
level._barrels._barrel_methods[ "MOD_GRENADE" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_GRENADE_SPLASH" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_PROJECTILE" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_PROJECTILE_SPLASH" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_TRIGGER_HURT" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_EXPLOSIVE" ] = ::barrel_calc_splash;
level._barrels._barrel_methods[ "MOD_EXPLOSIVE_BULLET" ] = ::barrel_calc_splash;
}
barrel_calc_ballistic( P, type )
{
return P;
}
barrel_calc_splash( P, type )
{
vec = VectorNormalize( VectorFromLineToPoint( self.A, self.B, P ) );
P = PointOnSegmentNearestToPoint( self.A, self.B, P );
return( P + ( vec * 4 ) );
}
barrel_calc_nofx( P, type )
{
return undefined;
}
precacheFX()
{
oil_leak = false;
oil_cap = false;
beer_leak = false;
foreach ( value in self )
{
if ( value.script_noteworthy == "oil_leak" )
{
value willNeverChange();
oil_leak = true;
}
else if ( value.script_noteworthy == "oil_cap" )
{
value willNeverChange();
oil_cap = true;
}
else if ( value.script_noteworthy == "beer_leak" )
{
value willNeverChange();
beer_leak = true;
}
else
{
println( "Unknown 'barrel_shootable' script_noteworthy type '%s'\n", value.script_noteworthy );
}
}
//DC_NOTE commented out all sound related stuff because it was giving me grief in mp_zulu
if ( oil_leak )
{
level._barrels._effect[ "oil_leak" ] = loadfx( "fx/impacts/pipe_oil_barrel_spill" );
//level._barrels._sound[ "oil_leak_hit" ] = "mtl_oil_barrel_hit";
//level._barrels._sound[ "oil_leak_loop" ] = "mtl_oil_barrel_hiss_loop";
//level._barrels._sound[ "oil_leak_end" ] = "mtl_oil_barrel_hiss_loop_end";
level._barrels.fx_time[ "oil_leak" ] = 6;
level._barrels._barrel_fx_time["oil_leak"] = 6;
level._barrels._dmg[ "oil_leak" ] = 5;
}
if ( oil_cap )
{
level._barrels._effect[ "oil_cap" ] = loadfx( "fx/impacts/pipe_oil_barrel_squirt" );
//level._barrels._sound[ "oil_cap_hit" ] = "mtl_oil_barrel_hit";
//level._barrels._sound[ "oil_cap_loop" ] = "mtl_oil_barrel_hiss_loop";
//level._barrels._sound[ "oil_cap_end" ] = "mtl_oil_barrel_hiss_loop_end";
level._barrels.fx_time[ "oil_cap" ] = 3;
level._barrels._dmg[ "oil_cap" ] = 5;
level._barrels._barrel_fx_time["oil_cap"] = 5;
}
if ( beer_leak )//DC_TODO create beer fx
{
level._barrels._effect[ "beer_leak" ] = loadfx( "fx/impacts/beer_barrel_spill" );
level._barrels._sound[ "beer_leak_hit" ] = "mtl_beer_keg_hit";
level._barrels._sound[ "beer_leak_loop" ] = "mtl_beer_keg_hiss_loop";
level._barrels._sound[ "beer_leak_end" ] = "mtl_beer_keg_hiss_loop_end";
level._barrels.fx_time[ "beer_leak" ] = 6;
level._barrels._barrel_fx_time["beer_leak"] = 6;
level._barrels._dmg[ "beer_leak" ] = 5;
}
}

753
maps/mp/_breach.gsc Normal file
View File

@ -0,0 +1,753 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
main()
{
thread main_thread();
}
main_thread()
{
breach_precache();
waitframe();
breach = getstructarray("breach", "targetname");
array_thread(breach, ::breach_init);
}
breach_precache()
{
level.breach_icon_count = -1;
level._effect["default"] = loadfx("fx/explosions/breach_room_cheap");
}
breach_init()
{
if( getDvar( "r_reflectionProbeGenerate" ) == "1" )
return;
if(!IsDefined(self.target))
return;
self.breach_targets = [];
self.auto_breach_gametypes = [];
if(IsDefined(self.script_noteworthy))
{
toks = StrTok(self.script_noteworthy, ",");
foreach(tok in toks)
{
if(GetSubStr(tok,0,7) == "not_in_")
{
self.auto_breach_gametypes[self.auto_breach_gametypes.size] = GetSubStr(tok,7,tok.size);
}
if(tok == "only_if_allowClassChoice")
{
if(!allowClassChoice())
{
self.auto_breach_gametypes[self.auto_breach_gametypes.size] = level.gameType;
}
}
}
}
ents = GetEntArray(self.target, "targetname");
structs = getstructarray(self.target, "targetname");
targets = array_combine(ents, structs);
nodes = self getLinknameNodes();
foreach (node in nodes)
{
node.isPathNode = true;
}
targets = array_combine(targets, nodes);
foreach(target in targets)
{
if(!IsDefined(target.script_noteworthy))
{
target.script_noteworthy = target.classname;
}
if(target.script_noteworthy == "trigger_use_touch")
{
target UseTriggerRequireLookAt();
target.script_noteworthy = "trigger_use";
}
if(!IsDefined(target.isPathNode) || target.isPathNode == false)
target.script_noteworthy = ToLower(target.script_noteworthy);
types = StrTok(target.script_noteworthy, ", ");
foreach(type in types)
{
event_name = undefined;
toks = StrTok(type, "_");
if(toks.size>=3 && toks[toks.size-2] == "on")
{
event_name = toks[toks.size-1];
type = toks[0];
for(i=1;i<toks.size-2;i++)
type = type + "_" + toks[i];
}
useSide = false;
toks = StrTok(type, "_");
if(toks.size>=2 && toks[toks.size-1] == "useside")
{
useSide = true;
type = toks[0];
for(i=1;i<toks.size-2;i++)
type = type + "_" + toks[i];
}
add_breach_target(target, type, event_name, useSide);
switch(type)
{
case "show":
case "animated":
target Hide();
break;
case "solid":
if( IsDefined( target.spawnflags ) && ( target.spawnflags & 2 ) ) // AI_SIGHT_LINE
{
target SetAISightLineVisible( 0 );
}
target NotSolid();
break;
case "teleport_show":
target trigger_off();
break;
case "use_icon":
// self thread breach_icon("use", target.origin, target.angles, ["breach_used","breach_activated"] );
break;
case "trigger_damage":
self thread breach_damage_watch(target);
break;
case "fx":
if(!IsDefined(target.angles))
target.angles = (0,0,0);
break;
case "connect_node":
target DisconnectNode();
break;
case "disconnect_node":
target ConnectNode();
break;
case "delete":
if( IsDefined( target.spawnflags ) && ( target.spawnflags & 2 ) ) // AI_SIGHT_LINE
{
target SetAISightLineVisible( 1 );
}
break;
default:
break;
}
}
}
if(level.createFX_enabled)
return;
use_trigger = get_breach_target("trigger_use");
if(IsDefined(use_trigger))
{
if(!IsDefined(get_breach_target("sound")))
{
script_origin = spawn("script_origin", use_trigger.origin);
add_breach_target(script_origin, "sound");
}
if(!IsDefined(get_breach_target("damage")))
{
damage = SpawnStruct();
damage.origin = use_trigger.origin;
add_breach_target(damage, "damage");
}
//init default damage info,
damages = get_breach_targets("damage");
foreach(damage in damages)
{
if(!IsDefined(damage.radius))
damage.radius = 128;
if(!IsDefined(damage.max_damage))
damage.max_damage = 100;
if(!IsDefined(damage.min_damage))
damage.min_damage = 1;
}
self thread breach_use_watch();
}
self thread breach_on_activate();
self breach_on_event("init");
foreach(type in self.auto_breach_gametypes)
{
if(level.gametype == type)
{
self notify("breach_activated", undefined, true);
break;
}
}
}
add_breach_target(target, action, event_name, useSide)
{
if(!IsDefined(event_name))
event_name = "activate";
if(!IsDefined(useSide))
useSide = false;
if(!IsDefined(self.breach_targets[event_name]))
self.breach_targets[event_name] = [];
if(!IsDefined(self.breach_targets[event_name][action]))
self.breach_targets[event_name][action] = [];
s = spawnStruct();
s.target = target;
//Check if object has a facing
if(useSide)
{
s.facing_dot = 0;
s.facing_angles3d = false;
s.facing_dir = AnglesToForward(target.angles);
if(IsDefined(target.target))
{
target_targets = getstructarray(target.target, "targetname");
foreach(target_target in target_targets)
{
if(!IsDefined(target_target.script_noteworthy))
continue;
switch(target_target.script_noteworthy)
{
case "angles":
case "angles_3d":
s.facing_angles3d = true;
//fall through
case "angles_2d":
if(!IsDefined(s.angles3d))
s.facing_angles3d = false;
s.facing_dir = AnglesToForward(target_target.angles);
if(IsDefined(target_target.script_dot))
s.facing_dot = target_target.script_dot;
break;
default:
break;
}
}
}
}
size = self.breach_targets[event_name][action].size;
self.breach_targets[event_name][action][size] = s;
}
get_breach_target(action, event_name, player)
{
targets = get_breach_targets(action, event_name, player);
if(targets.size>0)
{
return targets[0];
}
else
{
return undefined;
}
}
get_breach_targets(action, event_name, player)
{
targets = [];
if(!IsDefined(event_name))
event_name = "activate";
if(!IsDefined(self.breach_targets[event_name]))
return targets;
if(!IsDefined(self.breach_targets[event_name][action]))
return targets;
foreach(s in self.breach_targets[event_name][action])
{
if(IsDefined(s.facing_dir) && IsDefined(player))
{
player_dir = player.origin - s.target.origin;
if(!s.facing_angles3d)
player_dir = (player_dir[0], player_dir[1], 0);
player_dir = VectorNormalize(player_dir);
dot = VectorDot(player_dir, s.facing_dir);
if(dot<s.facing_dot)
continue;
}
targets[targets.size] = s.target;
}
return targets;
}
breach_damage_watch( trigger )
{
self endon( "breach_activated" );
trigger waittill( "trigger", player );
self notify( "breach_activated", player, false );
}
breach_on_activate()
{
self waittill("breach_activated", player, no_fx);
if(!isDefined(no_fx))
no_fx = false;
if( IsDefined(self.useObject) && !no_fx )
{
self.useObject breach_set_2dIcon("hud_grenadeicon_back_red");
self.useObject delayThread(3, ::breach_set_2dIcon, undefined);
}
breach_on_event("activate", player, no_fx);
if(IsDefined(self.useObject))
self.useObject.visuals = [];
breach_set_can_use(false);
}
breach_on_event( event_name, player, no_fx )
{
if ( !IsDefined( no_fx ) )
no_fx = false;
if ( event_name == "use" ) // breach is being manually planted
{
targets = get_breach_targets( "damage", "activate", player );
foreach ( target in targets )
{
target.planted = true;
}
}
array_call( get_breach_targets( "solid", event_name, player ), ::Solid );
array_call( get_breach_targets( "notsolid", event_name, player ), ::NotSolid );
array_thread( get_breach_targets( "hide", event_name, player ), ::breach_hide );
array_thread( get_breach_targets( "show", event_name, player ), ::breach_show );
array_thread( get_breach_targets( "teleport_show", event_name, player ), ::trigger_on );
array_thread( get_breach_targets( "delete", event_name, player ), ::breach_delete );
array_thread( get_breach_targets( "teleport_hide", event_name, player ), ::trigger_off );
array_call( get_breach_targets( "connect_node", event_name, player ), ::ConnectNode );
array_call( get_breach_targets( "disconnect_node", event_name, player ), ::DisconnectNode );
array_thread( get_breach_targets( "break_glass", event_name, player ), ::breach_break_glass );
array_thread( get_breach_targets( "animated", event_name, player ), ::breach_animate_model );
if ( !no_fx )
{
array_thread( get_breach_targets( "fx", event_name, player ), ::breach_play_fx, self );
array_thread( get_breach_targets( "damage", event_name, player ), ::breach_damage_radius, player );
}
}
breach_delete()
{
if(IsDefined(self.script_index))
{
exploder(self.script_index);
}
self SetAISightLineVisible( 0 );
self delete();
}
breach_hide()
{
self SetAISightLineVisible( 0 );
self Hide();
}
breach_show()
{
self SetAISightLineVisible( 1 );
self Show();
}
breach_play_fx(root)
{
fx_name = undefined;
if(isdefined(self.script_fxid))
{
fx_name = self.script_fxid;
}
else if(IsDefined(root.script_fxid))
{
fx_name = root.script_fxid;
}
if(!IsDefined(fx_name) || !IsDefined(level._effect[fx_name]))
{
fx_name = "default";
}
PlayFX(level._effect[fx_name], self.origin, AnglesToForward(self.angles), AnglesToUp(self.angles));
}
breach_damage_radius(attacker)
{
stuntime = 2.0; // 2 seconds is the minimum a concussion grenade will do
if( IsDefined( self.planted ) && ( self.planted == true ) )
{
// RadiusDamage(self.origin, self.radius, self.max_damage, self.min_damage, attacker);
foreach( participant in level.participants )
{
participant_to_breach_dist_sq = DistanceSquared( self.origin, participant.origin );
if( participant_to_breach_dist_sq < ( self.radius * self.radius ) )
{
participant ShellShock( "mp_radiation_high", stuntime );
}
}
}
PlayRumbleOnPosition( "artillery_rumble", self.origin );
}
breach_break_glass()
{
GlassRadiusDamage( self.origin, 128, 500, 500 );
}
breach_animate_model()
{
self SetAISightLineVisible( 1 );
self Show();
if ( IsDefined( self.animation ) )
{
self ScriptModelPlayAnim( self.animation );
}
}
breach_use_watch()
{
self endon("breach_activated");
wait .05;
self.useObject = maps\mp\gametypes\_gameobjects::createUseObject( "neutral", get_breach_target("trigger_use"), get_breach_targets("use_model"), (0,0,0) );
self.useObject.parent = self;
self.useObject.useWeapon = "breach_plant_mp";
self.useObject.id = "breach";
self breach_set_can_use(true);
self.useObject maps\mp\gametypes\_gameobjects::setUseTime( 0.5 );
self.useObject maps\mp\gametypes\_gameobjects::setUseText( &"MP_BREACHING" );
self.useObject maps\mp\gametypes\_gameobjects::setUseHintText( &"MP_BREACH" );
self.useObject maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" );
self.useObject.onUse = ::breach_onUse;
self.useObject.onEndUse = ::breach_onEndUse;
}
breach_set_can_use(canUse)
{
if(!IsDefined(self.useObject))
{
return;
}
if(canUse)
{
foreach(vis in self.useObject.visuals)
{
if( vis.model == "mil_semtex_belt" )
{
vis SetModel("mil_semtex_belt_obj");
}
}
self.useObject maps\mp\gametypes\_gameobjects::allowUse( "any" );
}
else
{
foreach(vis in self.useObject.visuals)
{
if( vis.model == "mil_semtex_belt" )
{
vis SetModel("mil_semtex_belt");
}
}
self.useObject notify( "disabled" );
self.useObject maps\mp\gametypes\_gameobjects::allowUse( "none" );
}
}
breach_onUse(player)
{
self.parent endon("breach_activated");
self.parent notify("breach_used");
self.parent breach_set_can_use(false);
self.parent breach_on_event("use", player);
self.parent thread breach_warning_icon(self);
sound_ent = undefined;
sound_targets = self.parent get_breach_targets( "sound" );
if ( sound_targets.size > 1 )
{
sound_targets = SortByDistance( sound_targets, player.origin );
sound_ent = sound_targets[0];
}
else if ( sound_targets.size > 0 )
{
sound_ent = sound_targets[0];
}
breaching_team = player.team; // need to store this in case the player switches teams between starting and finishing the breach
if(IsDefined(sound_ent))
{
for(i=0;i<3; i++)
{
sound_ent PlaySound("breach_beep");
wait .75;
}
if( IsDefined( sound_ent.script_parameters ) )
{
params = StrTok( sound_ent.script_parameters, ";" );
foreach ( param in params )
{
toks = StrTok( param, "=" );
if ( toks.size < 2 )
{
continue;
}
switch( toks[ 0 ] )
{
case "play_sound":
switch( toks[ 1 ] )
{
case "concrete":
sound_ent PlaySound( "detpack_explo_concrete" );
break;
case "wood":
sound_ent PlaySound( "detpack_explo_wood" );
break;
case "custom":
if ( toks.size == 3 )
{
sound_ent PlaySound( toks[2] );
}
break;
case "metal":
case "undefined":
default:
sound_ent PlaySound( "detpack_explo_metal" );
break;
}
break;
default:
break;
}
}
}
else
{
sound_ent PlaySound( "detpack_explo_metal" );
}
}
self.parent notify( "breach_activated", player, undefined, breaching_team );
}
breach_onEndUse( team, player, success )
{
if( IsPlayer( player ) )
{
player maps\mp\gametypes\_gameobjects::updateUIProgress( self, false );
}
}
breach_set_2dIcon( icon )
{
self maps\mp\gametypes\_gameobjects::set2DIcon( "enemy" , icon );
self maps\mp\gametypes\_gameobjects::set2DIcon( "friendly", icon );
}
breach_warning_icon( useObject )
{
icon_origin = useObject.curOrigin + ( 0, 0, 5 );
if ( useobject.parent get_breach_targets( "use_icon" ).size )
icon_origin = useobject.parent get_breach_targets( "use_icon" )[ 0 ].origin;
useObject.parent thread breach_icon( "warning", icon_origin, undefined, "breach_activated" );
}
breach_icon( type, origin, angles, end_ons )
{
if ( level.createFX_enabled )
return;
level.breach_icon_count++;
icon_id = "breach_icon_" + level.breach_icon_count;
breach_icon_update( type, origin, angles, icon_id, end_ons );
foreach ( player in level.players )
{
if ( IsDefined( player.breach_icons ) && IsDefined( player.breach_icons[ icon_id ] ) )
{
player.breach_icons[ icon_id ] thread breach_icon_fade_out();
}
}
}
breach_icon_update( type, origin, angles, icon_id, end_ons )
{
if ( IsDefined( end_ons ) )
{
if ( IsString( end_ons ) )
end_ons = [ end_ons ];
foreach ( end_on in end_ons )
self endon( end_on );
}
show_dist = 100;
show_z = 70;
icon = "hud_grenadeicon";
pin = true;
switch( type )
{
case "use":
show_dist = 300;
icon = "breach_icon";
pin = false;
break;
case "warning":
show_dist = 400;
damage_info = get_breach_target( "damage" );
if ( IsDefined( damage_info ) )
show_dist = damage_info.radius;
icon = "hud_grenadeicon";
pin = true;
break;
default:
break;
}
show_dir = undefined;
if ( IsDefined( angles ) )
{
show_dir = AnglesToForward( angles );
}
while ( 1 )
{
foreach ( player in level.players )
{
if ( !IsDefined( player.breach_icons ) )
player.breach_icons = [];
if ( breach_icon_update_is_player_in_range( player, origin, show_dist, show_dir, show_z ) )
{
if ( !IsDefined( player.breach_icons[ icon_id ] ) )
{
player.breach_icons[ icon_id ] = breach_icon_create( player, icon, origin, pin );
player.breach_icons[ icon_id ].alpha = 0;
}
player.breach_icons[ icon_id ] notify( "stop_fade" );
player.breach_icons[ icon_id ] thread breach_icon_fade_in();
}
else
{
if ( IsDefined( player.breach_icons[ icon_id ] ) )
{
player.breach_icons[ icon_id ] thread breach_icon_fade_out();
}
}
}
wait 0.05;
}
}
breach_icon_update_is_player_in_range( player, origin, show_dist, show_dir, show_z )
{
test_origin = player.origin+(0,0,30);
if(IsDefined(show_z) && abs(test_origin[2] - origin[2]) > show_z)
return false;
if(IsDefined(show_dist))
{
show_dist_sqr = show_dist*show_dist;
dist_sqr = DistanceSquared(test_origin, origin);
if(dist_sqr>show_dist_sqr)
return false;
}
if(IsDefined(show_dir))
{
dir_to_player = test_origin - origin;
//Normalize dir_to_player if not checking against zero.
if(VectorDot(show_dir, dir_to_player)<0)
return false;
}
return true;
}
breach_icon_create(player, icon, origin, pin)
{
icon = player createIcon( icon, 16, 16 );
icon setWayPoint( true, pin );
icon.x = origin[0];
icon.y = origin[1];
icon.z = origin[2];
return icon;
}
breach_icon_fade_in()
{
self endon("death");
if(self.alpha == 1)
return;
self FadeOverTime(.5);
self.alpha = 1;
}
breach_icon_fade_out()
{
self endon("death");
self endon("stop_fade");
if(self.alpha == 0)
return;
time = .5;
self FadeOverTime(time);
self.alpha = 0;
wait time;
self Destroy();
}

85
maps/mp/_compass.gsc Normal file
View File

@ -0,0 +1,85 @@
setupMiniMap(material)
{
// use 0 for no required map aspect ratio.
requiredMapAspectRatio = level.requiredMapAspectRatio;
corners = getentarray("minimap_corner", "targetname");
if (corners.size != 2)
{
println("^1Error: There are not exactly two \"minimap_corner\" entities in the map. Could not set up minimap.");
return;
}
corner0 = (corners[0].origin[0], corners[0].origin[1], 0);
corner1 = (corners[1].origin[0], corners[1].origin[1], 0);
cornerdiff = corner1 - corner0;
north = (cos(getnorthyaw()), sin(getnorthyaw()), 0);
west = (0 - north[1], north[0], 0);
// we need the northwest and southeast corners. all we know is that corner0 is opposite of corner1.
if (vectordot(cornerdiff, west) > 0) {
// corner1 is further west than corner0
if (vectordot(cornerdiff, north) > 0) {
// corner1 is northwest, corner0 is southeast
northwest = corner1;
southeast = corner0;
}
else {
// corner1 is southwest, corner0 is northeast
side = vecscale(north, vectordot(cornerdiff, north));
northwest = corner1 - side;
southeast = corner0 + side;
}
}
else {
// corner1 is further east than corner0
if (vectordot(cornerdiff, north) > 0) {
// corner1 is northeast, corner0 is southwest
side = vecscale(north, vectordot(cornerdiff, north));
northwest = corner0 + side;
southeast = corner1 - side;
}
else {
// corner1 is southeast, corner0 is northwest
northwest = corner0;
southeast = corner1;
}
}
if( GetDvar("mapname") == "mp_boneyard_ns")
{
southeast -= (220,220,0);
northwest += (220,220,0);
}
// expand map area to fit required aspect ratio
if ( requiredMapAspectRatio > 0 )
{
northportion = vectordot(northwest - southeast, north);
westportion = vectordot(northwest - southeast, west);
mapAspectRatio = westportion / northportion;
if ( mapAspectRatio < requiredMapAspectRatio )
{
incr = requiredMapAspectRatio / mapAspectRatio;
addvec = vecscale( west, westportion * (incr - 1) * 0.5 );
}
else
{
incr = mapAspectRatio / requiredMapAspectRatio;
addvec = vecscale( north, northportion * (incr - 1) * 0.5 );
}
northwest += addvec;
southeast -= addvec;
}
level.mapSize = vectordot(northwest - southeast, north);
setMiniMap(material, northwest[0], northwest[1], southeast[0], southeast[1]);
}
vecscale(vec, scalar)
{
return (vec[0]*scalar, vec[1]*scalar, vec[2]*scalar);
}

74
maps/mp/_createfx.gsc Normal file
View File

@ -0,0 +1,74 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include common_scripts\_createFxMenu;
#include common_scripts\_createfx;
#include common_scripts\_fx;
createfx()
{
level.func_position_player = ::void;
level.func_position_player_get = ::func_position_player_get;
level.func_loopfxthread = ::loopfxthread;
level.func_oneshotfxthread = ::oneshotfxthread;
level.func_create_loopsound = ::create_loopsound;
// level.func_exploder_preload = ::exploder_before_load;;
// level.func_exploder_postload = ::exploder_after_load;;
level.func_updatefx = ::restart_fx_looper;
level.func_process_fx_rotater = ::process_fx_rotater;
level.func_player_speed = ::func_player_speed;
level.mp_createfx = true;
// MP only stuff
level.callbackStartGameType = ::void;
level.callbackPlayerConnect = ::void;
level.callbackPlayerDisconnect = ::void;
level.callbackPlayerDamage = ::void;
level.callbackPlayerKilled = ::void;
level.callbackCodeEndGame = ::void;
level.callbackPlayerLastStand = ::void;
level.callbackPlayerConnect = ::Callback_PlayerConnect;
level.callbackPlayerMigrated = ::void;
thread func_get_level_fx(); // start gettin these on start
createfx_common();
level waittill( "eternity" );
}
func_position_player_get( lastPlayerOrigin )
{
return level.player.origin;
}
Callback_PlayerConnect()
{
self waittill( "begin" );
if ( !isdefined( level.player ) )
{
spawnpoints = getentarray( "mp_global_intermission", "classname" );
self spawn( spawnpoints[0].origin, spawnpoints[0].angles );
self updateSessionState( "playing", "" );
self.maxhealth = 10000000;
self.health = 10000000;
level.player = self;
thread createFxLogic();
//thread ufo_mode();
}
else
kick( self GetEntityNumber() );
}
//ufo_mode()
//{
// level.player openpopupmenu( "painter_mp" );// painter.menu execs some console commands( ufo mode ).. sneaky hacks.
// level.player closepopupmenu( "painter_mp" );
//}
func_player_speed()
{
scale = level._createfx.player_speed / 190;
level.player SetMoveSpeedScale( scale );
}

727
maps/mp/_crib.gsc Normal file
View File

@ -0,0 +1,727 @@
#include maps\mp\_utility;
#include common_scripts\utility;
CONST_default_radial_radius = 8; // default distance between radial button and center
CONST_radial_center_extrude_dist = 40; // this is the distance between the floating radial center and the oberver's eye
CONST_direct_travel = 1; // no path, directly zoom to position
CONST_view_travel_unit_dist = 1200; // distance unit per travel interval
CONST_view_travel_unit_time = 1; // in seconds per travel interval
CONST_blur_strength = 3; // blur strength during view travel, sine curved over travel duration
init()
{
precacheShellShock( "frag_grenade_mp" );
radial_button_definitions(); // define radial button sets and buttons
radial_init(); // setup radial button mechanism
view_path_setup(); // setup view flight paths
player_init();
}
// ====================================================================================
// == inits ==
// ====================================================================================
radial_button_definitions()
{
newRadialButtonGroup( "main", "player_view1_start", "player_view1_end" );
// Main menu's buttons:
bWeapons_a = newRadialButton( "main", "Primary Weapon", "radial_weapons_primary", ::action_weapons_primary );
bWeapons_b = newRadialButton( "main", "Secondary Weapon", "radial_weapons_secondary", ::action_weapons_secondary );
bGears = newRadialButton( "main", "Gears", "radial_gears", ::action_gears );
bKillStreaks= newRadialButton( "main", "Kill Streaks", "radial_killstreaks", ::action_killstreak );
bLeadboards = newRadialButton( "main", "Leaderboards", "radial_leaderboards", ::action_leaderboards );
//
newRadialButtonGroup( "gears", "player_view2_start", "player_view2_end" );
newRadialButtonGroup( "weapons_primary", "player_view3_start", "player_view3_end" );
newRadialButtonGroup( "weapons_secondary", "player_view3_start", "player_view3_end" );
newRadialButtonGroup( "killstreak", "player_view4_start", "player_view4_end" );
newRadialButtonGroup( "leaderboards", "player_view5_start", "player_view5_end" );
}
radial_init()
{
// calculate start & end angles of all buttons for range selection
foreach ( button_group in level.radial_button_group )
{
// sort buttons by angle so we can calculate mid angles in sequence
sort_buttons_by_angle( button_group );
for ( i = 0; i < button_group.size; i ++ )
{
if ( isdefined( button_group[ i + 1 ] ) )
{
mid_angle = getMidAngle( button_group[ i ].pos_angle, button_group[ i + 1 ].pos_angle );
button_group[ i ].end_angle = mid_angle;
button_group[ i + 1 ].start_angle = mid_angle;
}
else
{
mid_angle = getMidAngle( button_group[ i ].pos_angle, button_group[ 0 ].pos_angle ) + 180; // +180 to mirror angle
if ( mid_angle > 360 )
mid_angle -= 360;
button_group[ i ].end_angle = mid_angle;
button_group[ 0 ].start_angle = mid_angle;
}
}
}
// monitors
thread updateSelectedButton();
thread watchSelectButtonPress();
thread watchBackButtonPress();
thread debug_toggle();
}
debug_toggle()
{
level endon( "game_ended" );
level.crib_debug = 1;
while ( 1 )
{
if ( !isdefined( level.observer ) )
{
wait 0.05;
continue;
}
button_reset = true;
while ( !( level.observer buttonPressed( "BUTTON_Y" ) ) )
wait 0.05;
level.observer playsound("mouse_click");
if ( button_reset )
{
level.crib_debug *= -1;
button_reset = false;
}
while ( level.observer buttonPressed( "BUTTON_Y" ) )
wait 0.05;
}
}
player_init()
{
level thread onPlayerConnect();
level thread return_hud();
}
return_hud()
{
level waittill( "game_ended" );
setdvar( "cg_draw2d", 1 );
}
onPlayerConnect()
{
level waittill("connected", player);
player thread readyPlayer();
player waittill( "spawned_player" );
wait 1;
player takeallweapons();
setdvar( "cg_draw2d", 0 );
if ( !isdefined( player ) )
return;
else
level.observer = player;
player thread get_right_stick_angle();
zoom_to_radial_menu( "main" ); // fly to the first radial menu
}
readyPlayer()
{
self endon( "disconnect" );
team = "autoassign";
while(!isdefined(self.pers["team"]))
wait .05;
self notify("menuresponse", game["menu_team"], team);
wait 0.5;
classes = getArrayKeys( level.classMap );
okclasses = [];
for ( i = 0; i < classes.size; i++ )
{
if ( !isSubStr( classes[i], "custom" ) )
okclasses[ okclasses.size ] = classes[i];
}
assert( okclasses.size );
while( 1 )
{
class = okclasses[ 0 ];
self notify("menuresponse", "changeclass", class);
self waittill( "spawned_player" );
wait ( 0.10 );
}
}
// ====================================================================================
// == Radial Mechanics ==
// ====================================================================================
get_right_stick_angle()
{
// self is user
level endon( "game_ended" );
self endon( "disconnect" );
while ( 1 )
{
rs_vec = self GetNormalizedMovement();
rs_angles = vectortoangles( rs_vec );
level.rs_angle = int( rs_angles[1] );
wait 0.05; // update rate
}
}
newRadialButtonGroup( group_name, view_start, view_end )
{
if ( isdefined( level.radial_button_group ) && level.radial_button_group.size )
assertex( !isdefined( level.radial_button_group[ group_name ] ), "Radial button group: " + group_name + " is already defined." );
player_view_ent = getent( view_end, "targetname" );
assertex( isdefined( player_view_ent ), "Missing player view entity, can not setup radial menu in space" );
extruded_vec = ( VectorNormalize( AnglesToForward( player_view_ent.angles ) ) * CONST_radial_center_extrude_dist );
level.radial_button_group[ group_name ] = [];
level.radial_button_group_info[ group_name ][ "view_start" ] = view_start;
level.radial_button_group_info[ group_name ][ "view_pos" ] = player_view_ent.origin + extruded_vec;
level.radial_button_group_info[ group_name ][ "player_view_pos" ] = player_view_ent.origin;
level.radial_button_group_info[ group_name ][ "view_angles" ] = player_view_ent.angles;
}
newRadialButton( button_group, button_label, button_ent_name, action_func )
{
assertex( isdefined( level.radial_button_group[ button_group ] ), "Radial button group: " + button_group + " does not exist." );
ent = getent( button_ent_name, "targetname" );
new_button_angle = getRadialAngleFromEnt( button_group, ent );
button = spawnstruct();
button.pos = ent.origin;
button.label = button_label;
button.font_size = 1;
button.font_color = ( 0.5, 0.5, 1 );
button.pos_angle = new_button_angle;
button.action_func = action_func;
button.radius_pos = CONST_default_radial_radius;
level.radial_button_group[ button_group ][ level.radial_button_group[ button_group ].size ] = button;
return button;
}
updateSelectedButton()
{
level endon( "game_ended" );
while ( 1 )
{
if ( !isdefined( level.radial_button_current_group ) )
{
wait 0.05;
continue;
}
last_active_button = level.active_button;
foreach ( button in level.radial_button_group[ level.radial_button_current_group ] )
{
if ( isInRange( button.start_angle, button.end_angle ) )
level.active_button = button;
else
button.font_color = ( 0.5, 0.5, 1 );
}
if ( isdefined ( level.active_button ) )
{
level.active_button.font_color = ( 1, 1, 0.5 );
if ( isdefined( last_active_button ) && last_active_button != level.active_button )
level.observer playsound("mouse_over");
}
wait 0.05;
}
}
watchSelectButtonPress()
{
level endon( "game_ended" );
while ( 1 )
{
if ( !isdefined( level.observer ) )
{
wait 0.05;
continue;
}
button_reset = true;
while ( !( level.observer buttonPressed( "BUTTON_A" ) ) )
wait 0.05;
level.observer playsound("mouse_click");
if ( isdefined( level.active_button ) && button_reset )
{
level.active_button notify( "select_button_pressed" );
[[level.active_button.action_func]]();
button_reset = false;
}
while ( level.observer buttonPressed( "BUTTON_A" ) )
wait 0.05;
}
}
watchBackButtonPress()
{
level endon( "game_ended" );
while ( 1 )
{
if ( !isdefined( level.observer ) )
{
wait 0.05;
continue;
}
button_reset = true;
while ( !( level.observer buttonPressed( "BUTTON_X" ) ) )
wait 0.05;
level.observer playsound("mouse_click");
if ( button_reset )
{
action_back();
button_reset = false;
}
while ( level.observer buttonPressed( "BUTTON_X" ) )
wait 0.05;
}
}
sort_buttons_by_angle( button_group )
{
// button_group is actual array
// bubble sort buttons
for ( i = 0; i < button_group.size - 1; i++ )
{
for ( j = 0; j < button_group.size - 1 - i; j++ )
{
if ( button_group[ j + 1 ].pos_angle < button_group[ j ].pos_angle )
button_switch( button_group[ j ], button_group[ j + 1 ] );
}
}
}
button_switch( button1, button2 )
{
temp_pos = button1.pos;
temp_label = button1.label;
temp_pos_angle = button1.pos_angle;
temp_action_func = button1.action_func;
temp_radius_pos = button1.radius_pos;
button1.pos = button2.pos;
button1.label = button2.label;
button1.pos_angle = button2.pos_angle;
button1.action_func = button2.action_func;
button1.radius_pos = button2.radius_pos;
button2.pos = temp_pos;
button2.label = temp_label;
button2.pos_angle = temp_pos_angle;
button2.action_func = temp_action_func;
button2.radius_pos = temp_radius_pos;
}
draw_radial_buttons( button_group )
{
foreach ( button in level.radial_button_group[ button_group ] )
button thread draw_radial_button( button_group );
}
//print3d(<origin>, <text>, <color>, <alpha>, <scale>, <duration> )
draw_radial_button( button_group )
{
level endon( "game_ended" );
self endon( "remove_button" );
floating_origin = level.radial_button_group_info[ button_group ][ "view_pos" ];
button_radial_pos = floating_origin + radial_angle_to_vector( self.pos_angle, 4 );
while ( 1 )
{
//line( level.radial_button_group_info[ button_group ][ "view_pos" ], self.pos, ( 0, 1, 0 ), 0.05, false );
range_color = ( 1, 0, 0 );
if ( isInRange( self.start_angle, self.end_angle ) )
range_color = ( 1, 1, 0 );
print3d( self.pos, self.label, self.font_color, 0.75, self.font_size, 1 );
if ( isdefined( level.crib_debug ) && level.crib_debug > 0 )
{
print3d( button_radial_pos, ".("+int(self.pos_angle)+")", range_color, 0.75, 0.05, 1 );
line( floating_origin, floating_origin + radial_angle_to_vector( self.start_angle, 2 ), range_color, 0.05 );
line( floating_origin + radial_angle_to_vector( self.start_angle, 2 ), floating_origin + radial_angle_to_vector( self.end_angle, 2 ), range_color, 0.05 );
// right stick debug ling
r_radial_pos = floating_origin + radial_angle_to_vector( level.rs_angle, 2 );
line( floating_origin, r_radial_pos, ( 1, 1, 1 ), 0.05 );
}
print3d( floating_origin - ( 0, 0, 4.5 ), "(A)=Select (X)=Back", (1, 1, 1), 0.5, 0.05, 1 );
wait 0.05;
}
}
Zoom_To_Radial_Menu( button_group, reverse )
{
level.active_button = undefined;
assertex( isdefined( level.observer ), "Missing observer (connected player), can not attach player to view path" );
if ( isdefined( level.radial_button_current_group ) && level.radial_button_current_group != "" )
{
level.radial_button_previous_group = level.radial_button_current_group;
}
else
{
level.radial_button_previous_group = "main";
level.radial_button_current_group = "main";
}
foreach ( button in level.radial_button_group[ level.radial_button_previous_group ] )
button notify( "remove_button" );
//iPrintLnBold( "flying to: " + button_group );
if ( isdefined( reverse ) && reverse )
level.observer go_path_by_targetname_reverse( level.radial_button_group_info[ level.radial_button_previous_group ][ "view_start" ], button_group );
else
level.observer go_path_by_targetname( level.radial_button_group_info[ button_group ][ "view_start" ] );
level thread draw_radial_buttons( button_group );
level.radial_button_current_group = button_group;
}
// ====================================================================================
// == Radial menu - math ==
// ====================================================================================
// edit function with care, returns orientation-sensistive angles
getRadialAngleFromEnt( button_group, ent )
{
assertex( isdefined( level.radial_button_group[ button_group ] ), "getRadialAngleFromEnt: Radial button group does not exist." );
assertex( isdefined( ent ), "getRadialAngleFromEnt: Missing entity to be measured." );
rAngle = level.radial_button_group_info[ button_group ][ "view_angles" ];
rPos = level.radial_button_group_info[ button_group ][ "view_pos" ];
rPos += ( VectorNormalize( AnglesToForward( rAngle ) ) * CONST_radial_center_extrude_dist );
rForward = AnglesToForward( rAngle );
rUpwardNorm = VectorNormalize( AnglesToUp( rAngle ) );
eAngle = ent.angles;
ePos = ent.origin;
projNorm = VectorNormalize( VectorFromLineToPoint( rPos, ( rPos + rForward ), ePos ) );
radial_angle = Acos( VectorDot( projNorm, rUpwardNorm ) );
// vector mirroring
if ( VectorDot( AnglesToRight( rAngle ), projNorm ) < 0 )
radial_angle = 360 - radial_angle;
return radial_angle;
}
// converts projected angle into player's view plane into a vector
radial_angle_to_vector( angle, scaler )
{
b_angles = ( 270 - ( angle ), 0 , 0 ); // 270 degrees offset to face the player
b_vec = AnglesToForward( b_angles );
b_vec_norm = VectorNormalize( b_vec );
b_vec_final = ( b_vec_norm * scaler );
return b_vec_final;
}
getMidAngle( a1, a2 )
{
// 0 -> 360 domain
mid_angle = ( ( a1 + a2 + 720 ) / 2 ) - 360;
return mid_angle;
}
isInRange( start_angle, end_angle )
{
inside_big_angle = ( level.rs_angle > start_angle && level.rs_angle < 360 );
inside_small_angle = ( level.rs_angle > 0 && level.rs_angle < end_angle );
if ( start_angle > end_angle )
in_range = ( inside_big_angle || inside_small_angle );
else
in_range = ( level.rs_angle > start_angle && level.rs_angle < end_angle );
return in_range;
}
// ====================================================================================
// == Button action functions ==
// ====================================================================================
// close radial buttons
action_back()
{
//if ( isdefined( level.radial_button_previous_group ) && level.radial_button_previous_group != "" )
// zoom_to_radial_menu( level.radial_button_previous_group );
/*else*/ if ( isdefined( level.radial_button_current_group ) && level.radial_button_current_group != "main" )
zoom_to_radial_menu( "main", true );
else
return;
}
// ==== main ====
action_weapons_primary()
{
iPrintLnBold( "action_weapons_primary" );
zoom_to_radial_menu( "weapons_primary" );
}
action_weapons_secondary()
{
iPrintLnBold( "action_weapons_secondary" );
zoom_to_radial_menu( "weapons_secondary" );
}
action_gears()
{
iPrintLnBold( "action_gears" );
zoom_to_radial_menu( "gears" );
}
action_killstreak()
{
iPrintLnBold( "action_killstreak" );
zoom_to_radial_menu( "killstreak" );
}
action_leaderboards()
{
iPrintLnBold( "action_leaderboards" );
zoom_to_radial_menu( "leaderboards" );
}
// ====================================================================================
// == Pathing functions ==
// ====================================================================================
view_path_setup()
{
// setup all paths
level.view_paths = [];
// build paths
build_path_by_targetname( "player_view1_start" );
build_path_by_targetname( "player_view2_start" );
build_path_by_targetname( "player_view3_start" );
build_path_by_targetname( "player_view4_start" );
build_path_by_targetname( "player_view5_start" );
}
build_path_by_targetname( path_name )
{
level.view_paths[ path_name ] = [];
path_node = getent( path_name, "targetname" );
level.view_paths[ path_name ][ level.view_paths[ path_name ].size ] = path_node;
while( isdefined( path_node ) && isdefined( path_node.target ) )
{
next_node = getent( path_node.target, "targetname" );
level.view_paths[ path_name ][ level.view_paths[ path_name ].size ] = next_node;
path_node = next_node;
}
}
go_path_by_targetname( path_name )
{
// self is player
if ( !isdefined( level.dummy_mover ) )
{
start_node = level.view_paths[ path_name ][ 0 ];
level.dummy_mover = spawn( "script_model", start_node.origin );
level.dummy_mover.angles = start_node.angles;
//self AllowedStances( "stand" );
self setOrigin( level.dummy_mover.origin - ( 0, 0, 65 ) );
self linkTo( level.dummy_mover );
wait 0.05;
self setplayerangles ( level.dummy_mover.angles );
self thread force_player_angles();
}
/*
travel_time = 1;
dist = 0;
foreach ( idx, node in level.view_paths[ path_name ] )
{
if ( isdefined( level.view_paths[ path_name ][ idx + 1 ] ) )
dist += abs( distance( level.view_paths[ path_name ][ idx ].origin, level.view_paths[ path_name ][ idx + 1 ].origin ) );
}*/
travel_speed = CONST_view_travel_unit_time;
total_distance = abs( distance( level.dummy_mover.origin, level.view_paths[ path_name ][ level.view_paths[ path_name ].size - 1 ].origin ) );
travel_speed *= total_distance / CONST_view_travel_unit_dist;
travel_speed = max( travel_speed, 0.1 ); // due to repeated button presses, the travel distance can be cut to 0 travel speed at times.
blur_time = travel_speed;
if ( !CONST_direct_travel )
blur_time *= travel_speed * ( level.view_paths[ path_name ].size + 1 );
self thread blur_sine( CONST_blur_strength, blur_time );
foreach ( idx, node in level.view_paths[ path_name ] )
{
//travel_speed = travel_time * ( abs( distance( level.dummy_mover.origin, node.origin ) ) / dist );
//travel_speed += 0.05;
if ( CONST_direct_travel )
{
if ( idx != level.view_paths[ path_name ].size - 1 )
continue;
}
//level.dummy_mover MoveTo( node.origin, travel_speed );
level.dummy_mover MoveTo( node.origin, travel_speed, travel_speed * 0.5, 0 );
level.dummy_mover RotateTo( node.angles, travel_speed, travel_speed * 0.5, 0);
wait travel_speed;
}
}
go_path_by_targetname_reverse( path_name, back_to_button_group )
{
assertex( isdefined( level.dummy_mover ), "go_path_by_targetname_reverse called before go_path_by_targetname" );
travel_speed = CONST_view_travel_unit_time;
total_distance = abs( distance( level.dummy_mover.origin, level.radial_button_group_info[ back_to_button_group ][ "player_view_pos" ] ) );
travel_speed *= total_distance / CONST_view_travel_unit_dist;
travel_speed = max( travel_speed, 0.1 ); // due to repeated button presses, the travel distance can be cut to 0 travel speed at times.
blur_time = travel_speed;
if ( !CONST_direct_travel )
blur_time *= travel_speed * ( level.view_paths[ path_name ].size + 1 );
self thread blur_sine( CONST_blur_strength, blur_time );
if ( !CONST_direct_travel )
{
for ( idx = level.view_paths[ path_name ].size - 1; idx >= 0; idx-- )
{
node = level.view_paths[ path_name ][ idx ];
level.dummy_mover MoveTo( node.origin, travel_speed );
level.dummy_mover RotateTo( node.angles, travel_speed );
//self thread travel_view_fx( travel_speed );
wait travel_speed;
}
}
self thread blur_sine( CONST_blur_strength, travel_speed );
pos = level.radial_button_group_info[ back_to_button_group ][ "player_view_pos" ];
angle = level.radial_button_group_info[ back_to_button_group ][ "view_angles" ];
level.dummy_mover MoveTo( pos, travel_speed, travel_speed * 0.5, 0 );
level.dummy_mover RotateTo( angle, travel_speed, travel_speed * 0.5, 0 );
wait travel_speed;
}
travel_view_fx( time )
{
self setblurforplayer( 20, ( time + 0.2 )/2 );
self setblurforplayer( 0, ( time + 0.2 )/2 );
self shellshock( "frag_grenade_mp", time + 0.2 );
}
blur_sine( strength, time )
{
time_scaled = int( time/0.05 );
for( i = 0; i < time_scaled; i ++ )
{
fraction = ( i / ( time_scaled ) );
cos_fraction= sin( 180 * fraction );
blur_amount = strength * cos_fraction;
setdvar( "r_blur", blur_amount );
wait 0.05;
}
setdvar( "r_blur", 0 );
}
force_player_angles()
{
level endon( "game_ended" );
self endon( "disconnect" );
level.dummy_mover endon( "remove_dummy" );
while ( 1 )
{
self setplayerangles ( level.dummy_mover.angles );
wait 0.05;
}
}

137
maps/mp/_defcon.gsc Normal file
View File

@ -0,0 +1,137 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
// if ( game["state"] == "postgame" && game["teamScores"][attacker.team] > game["teamScores"][level.otherTeam[attacker.team]] )
ICONSIZE = 20;
init()
{
if ( !isDefined( level.defconMode ) || level.defconMode == false )
return;
if ( !isDefined( game["defcon"] ) )
game["defcon"] = 4;
SetDvar( "scr_defcon", game["defcon"] );
/# setDevDvarIfUninitialized( "scr_defconStreak", 10 ); #/
level.defconStreakAdd[5] = 0;
level.defconStreakAdd[4] = 0;
level.defconStreakAdd[3] = -1;
level.defconStreakAdd[2] = -1;
level.defconStreakAdd[1] = -1;
level.defconPointMod[5] = 1;
level.defconPointMod[4] = 1;
level.defconPointMod[3] = 1;
level.defconPointMod[2] = 1;
level.defconPointMod[1] = 2;
updateDefcon( game["defcon"] );
thread defconKillstreakThread();
}
defconKillstreakWait( streakCount )
{
for ( ;; )
{
level waittill ( "player_got_killstreak_" + streakCount, player );
level notify ( "defcon_killstreak", streakCount, player );
}
}
defconKillstreakThread()
{
level endon ( "game_ended" );
requiredKillCount = 10;
/#
requiredKillCount = getDvarInt( "scr_defconStreak" );
#/
level thread defconKillstreakWait( requiredKillCount );
level thread defconKillstreakWait( requiredKillCount - 1 );
level thread defconKillstreakWait( requiredKillCount - 2 );
level thread defconKillstreakWait( (requiredKillCount * 2) );
level thread defconKillstreakWait( (requiredKillCount * 2) - 1 );
level thread defconKillstreakWait( (requiredKillCount * 2) - 2 );
level thread defconKillstreakWait( (requiredKillCount * 3) );
level thread defconKillstreakWait( (requiredKillCount * 3) - 1 );
level thread defconKillstreakWait( (requiredKillCount * 3) - 2 );
for ( ;; )
{
level waittill ( "defcon_killstreak", streakCount, changingPlayer );
if ( game["defcon"] <= 1 )
continue;
if ( (streakCount % requiredKillCount) == requiredKillCount - 2 )
{
foreach ( player in level.players )
{
if ( !isAlive( player ) )
continue;
player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "two_from_defcon", changingPlayer );
}
}
else if ( (streakCount % requiredKillCount) == requiredKillCount - 1 )
{
foreach ( player in level.players )
{
if ( !isAlive( player ) )
continue;
player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "one_from_defcon", changingPlayer );
}
}
else
{
updateDefcon( game["defcon"] - 1, changingPlayer, streakCount );
}
}
}
updateDefcon( newDefcon, changingPlayer, streakCount )
{
newDefcon = int( newDefcon );
oldDefcon = game["defcon"];
game["defcon"] = newDefcon;
// level.killStreakMod = level.defconStreakAdd[newDefcon];
level.objectivePointsMod = level.defconPointMod[newDefcon];
setDvar( "scr_defcon", game["defcon"] );
//isdefined used for variable init
if( isDefined( changingPlayer ) )
changingPlayer notify( "changed_defcon" );
if ( newDefcon == oldDefcon )
return;
if ( game["defcon"] == 3 && isDefined( changingPlayer ) )
{
changingPlayer maps\mp\killstreaks\_killstreaks::giveKillstreak( "airdrop_mega" );
changingPlayer thread maps\mp\gametypes\_hud_message::splashNotify( "caused_defcon" , streakCount );
}
foreach ( player in level.players )
{
if ( isAlive( player ) )
{
player thread maps\mp\gametypes\_hud_message::defconSplashNotify( game["defcon"], newDefcon < oldDefcon );
if ( isDefined( changingPlayer ) )
player thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "changed_defcon", changingPlayer );
}
}
}

View File

@ -0,0 +1,82 @@
init()
{
// level.destructableFX = loadfx("fx/breakables/exp_wall_cinderblock_96");
ents = getentarray("destructable", "targetname");
if (getdvar("scr_destructables") == "0")
{
for (i = 0; i < ents.size; i++)
ents[i] delete();
}
else
{
for (i = 0; i < ents.size; i++)
{
ents[i] thread destructable_think();
}
}
}
destructable_think()
{
accumulate = 40;
threshold = 0;
if (isdefined(self.script_accumulate))
accumulate = self.script_accumulate;
if (isdefined(self.script_threshold))
threshold = self.script_threshold;
if (isdefined(self.script_destructable_area)) {
areas = strtok(self.script_destructable_area, " ");
for (i = 0; i < areas.size; i++)
self blockArea(areas[i]);
}
if ( isdefined( self.script_fxid ) )
self.fx = loadfx( self.script_fxid );
dmg = 0;
self setcandamage(true);
while(1)
{
self waittill("damage", amount, other);
if (amount >= threshold)
{
dmg += amount;
if (dmg >= accumulate)
{
self thread destructable_destruct();
return;
}
}
}
}
destructable_destruct()
{
ent = self;
if (isdefined(self.script_destructable_area)) {
areas = strtok(self.script_destructable_area, " ");
for (i = 0; i < areas.size; i++)
self unblockArea(areas[i]);
}
if ( isdefined( ent.fx ) )
playfx( ent.fx, ent.origin + (0,0,6) );
ent delete();
}
blockArea(area)
{
}
blockEntsInArea(ents, area)
{
}
unblockArea(area)
{
}
unblockEntsInArea(ents, area)
{
}

294
maps/mp/_dlcalienegg.gsc Normal file
View File

@ -0,0 +1,294 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
CONST_EGG_ID = "dlcEggStatus";
CONST_ALL_EGG_CHALLENGE = "ch_weekly_1";
init()
{
// this is a terrible hack.
// We are tracking all of the egg state in one 32-bit integer.
// The lower 16 bits track whether the player has shot the egg for that level, 4-bits per map-pack.
// the number of bits shifted should correspond to the order in mapNames.csv
// we'll use this to check completion of player data
level.dlcAlienEggs = [];
// pack 1
level.dlcAlienEggs[ "mp_boneyard_ns" ] = 1 << 0;
level.dlcAlienEggs[ "mp_swamp" ] = 1 << 1;
level.dlcAlienEggs[ "mp_ca_red_river" ] = 1 << 2;
level.dlcAlienEggs[ "mp_ca_rumble" ] = 1 << 3;
// pack 2
level.dlcAlienEggs[ "mp_dome_ns" ] = 1 << 4;
level.dlcAlienEggs[ "mp_battery3" ] = 1 << 5;
level.dlcAlienEggs[ "mp_ca_impact" ] = 1 << 6;
level.dlcAlienEggs[ "mp_ca_behemoth" ] = 1 << 7;
// pack 3. bits 8-11
level.dlcAlienEggs[ "mp_dig" ] = 1 << 8;
level.dlcAlienEggs[ "mp_favela_iw6" ] = 1 << 9;
level.dlcAlienEggs[ "mp_pirate" ] = 1 << 10;
level.dlcAlienEggs[ "mp_zulu" ] = 1 << 11;
// pack 4. bits 12-15
level.dlcAlienEggs[ "mp_conflict" ] = 1 << 12;
level.dlcAlienEggs[ "mp_mine" ] = 1 << 13;
level.dlcAlienEggs[ "mp_zerosub" ] = 1 << 14;
level.dlcAlienEggs[ "mp_shipment_ns" ] = 1 << 15;
// Translate each map name to its pack number (0-based)
level.dlcAliengEggMapToPack[ "mp_boneyard_ns" ] = 0;
level.dlcAliengEggMapToPack[ "mp_swamp" ] = 0;
level.dlcAliengEggMapToPack[ "mp_ca_red_river" ] = 0;
level.dlcAliengEggMapToPack[ "mp_ca_rumble" ] = 0;
level.dlcAliengEggMapToPack[ "mp_dome_ns" ] = 1;
level.dlcAliengEggMapToPack[ "mp_battery3" ] = 1;
level.dlcAliengEggMapToPack[ "mp_ca_impact" ] = 1;
level.dlcAliengEggMapToPack[ "mp_ca_behemoth" ] = 1;
level.dlcAliengEggMapToPack[ "mp_dig" ] = 2;
level.dlcAliengEggMapToPack[ "mp_favela_iw6" ] = 2;
level.dlcAliengEggMapToPack[ "mp_pirate" ] = 2;
level.dlcAliengEggMapToPack[ "mp_zulu" ] = 2;
// pack 4. bits 12-15
level.dlcAliengEggMapToPack[ "mp_conflict" ] = 3;
level.dlcAliengEggMapToPack[ "mp_mine" ] = 3;
level.dlcAliengEggMapToPack[ "mp_zerosub" ] = 3;
level.dlcAliengEggMapToPack[ "mp_shipment_ns" ] = 3;
// # of set bits in 0 - 15
// use to look up how many eggs have been achieved
level.bitCounts = [ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 ];
level._effect[ "vfx_alien_easter_egg_hit" ] = loadfx( "vfx/gameplay/alien/vfx_alien_easter_egg_hit" );
}
setupEggForMap( eggName )
{
if ( level.rankedMatch )
{
init();
flags = level.dlcAlienEggs[ getMapName() ];
AssertEx( IsDefined( flags ), "dlcAlienEggs bit flag not set up for map: " + getMapName() );
egg = GetEnt( eggName, "targetname" );
if ( IsDefined( egg ) )
{
// add flags
// playlistType = GetDvarInt( "scr_playlist_type", 0 );
if ( egg.classname == "script_model" )
{
egg SetCanDamage( true );
}
egg thread eggTrackHits();
}
/#
thread eggDebug();
#/
}
}
eggTrackHits()
{
level endon( "game_ended" );
self.health = 99999;
level.eggHits = [];
while ( true )
{
self waittill( "damage", damage, attacker, direction, point, damageType );
// play a sound and effect?
PlayFX( getfx( "vfx_alien_easter_egg_hit" ), point, AnglesToForward( direction ), AnglesToUp( direction ) );
if ( IsPlayer( attacker ) && !IsAI( attacker ) )
{
attackerNum = attacker getUniqueId();
// we have not hit this egg before
if ( !IsDefined( level.eggHits[ attackerNum ] ) )
{
level.eggHits[ attackerNum ] = 1;
self eggRegisterHit( damage, attacker, direction, point, damageType );
}
}
}
}
eggRegisterHit( damage, attacker, direction, point, type )
{
self.health += damage; // don't let the health drop
if ( !( attacker eggHasCompletedForMap( getMapName() ) ) )
{
attacker eggSetCompletedForMap( getMapName() );
}
else if ( attacker eggAllFound()
&& attacker ch_getState( CONST_ALL_EGG_CHALLENGE ) < 2
)
{
attacker eggAwardPatch();
}
}
eggHasCompletedForMap( mapName ) // self == player
{
eggState = self GetRankedPlayerDataReservedInt( CONST_EGG_ID );
bitFlag = level.dlcAlienEggs[ mapName ];
if ( IsDefined( bitFlag ) &&
(eggState & bitFlag) != 0 )
{
return true;
}
return false;
}
eggSetCompletedForMap( mapName ) // self == player
{
bitFlag = level.dlcAlienEggs[ mapName ];
if ( IsDefined( bitFlag ) )
{
eggState = self GetRankedPlayerDataReservedInt( CONST_EGG_ID );
eggState |= bitFlag;
self SetRankedPlayerDataReservedInt( CONST_EGG_ID, eggState );
packNum = level.dlcAliengEggMapToPack[ mapName ];
AssertEx( IsDefined( packNum ), "MapPack ID not defined for " + mapName );
numCompleted = eggCountCompletedEggsForPack( packNum, eggState );
packNum++; // the splashes are indexed 1-4, instead of 0-3
if ( numCompleted < 4 )
{
self maps\mp\gametypes\_hud_message::playerCardSplashNotify( "dlc_eggFound_" + packNum, self, numCompleted );
}
else
{
// if all the eggs are found, give ultimate award
if ( self eggAllFound()
&& ch_getState( CONST_ALL_EGG_CHALLENGE ) < 2
)
{
self eggAwardPatch();
}
// otherwise give award for this pack
else
{
self maps\mp\gametypes\_hud_message::playerCardSplashNotify( "dlc_eggAllFound_" + packNum, self );
self thread maps\mp\gametypes\_rank::giveRankXP( "dlc_egg_hunt" );
}
}
self PlayLocalSound( "ui_extinction_egg_splash" );
}
}
eggAwardPatch()
{
self maps\mp\gametypes\_hud_message::playerCardSplashNotify( "dlc_eggAllFound", self );
self thread maps\mp\gametypes\_rank::giveRankXP( "dlc_egg_hunt_all" );
ch_setState( CONST_ALL_EGG_CHALLENGE, 2 ); // patch. Weekly challenges are unlocked with state set to 2.
}
eggCountCompletedEggsForPack( packNum, eggState )
{
flags = eggState >> (packnum * 4); // move the bits to the first set of 4
flags &= 15; // mask out everything but the first four bits
return level.bitCounts[ flags ];
}
// packNum is 0-indexed
eggAllFoundForPack( packNum )
{
eggState = self GetRankedPlayerDataReservedInt( CONST_EGG_ID );
packEggState = (eggState >> (packnum *4)) & 15;
return (packEggState != 0);
}
// all 16 eggs found
CONST_ALL_EGGS_MASK = (1 << 16) - 1;
eggAllFound()
{
eggState = self GetRankedPlayerDataReservedInt( CONST_EGG_ID );
return ( eggState == CONST_ALL_EGGS_MASK );
}
/#
eggDebug()
{
level endon( "game_ended" );
level waittill( "connected", player );
player thread eggDebugPlayer();
}
eggDebugPlayer() // self == player
{
level endon( "game_ended" );
SetDvarIfUninitialized( "scr_egg_set", "" );
SetDvarIfUninitialized( "scr_egg_pack_set", 0 );
SetDvarIfUninitialized( "scr_egg_clear", 0 );
while ( true )
{
mapName = GetDvar( "scr_egg_set" );
if ( mapName != "" )
{
self eggSetCompletedForMap( mapName );
SetDvar( "scr_egg_set", "" );
}
if ( GetDvarInt( "scr_egg_clear" ) != 0 )
{
self SetRankedPlayerDataReservedInt( CONST_EGG_ID, 0 );
SetDvar( "scr_egg_clear", 0 );
level.eggHits = [];
ch_setState( CONST_ALL_EGG_CHALLENGE, 0 );
}
// set all the flags for one pack
targetPackNum = GetDvarInt( "scr_egg_pack_set" );
if ( targetPackNum > 0 )
{
targetPackNum--;
foreach ( mapName, packNum in level.dlcAliengEggMapToPack )
{
if ( packNum == targetPackNum && !( self eggHasCompletedForMap( mapName ) ) )
{
self eggSetCompletedForMap( mapName );
wait (3.6); // a little bit more than the duration of the splash
}
}
SetDvar( "scr_egg_pack_set", "" );
}
wait ( 0.25 );
}
}
#/

378
maps/mp/_elevator.gsc Normal file
View File

@ -0,0 +1,378 @@
#include maps\mp\_utility;
#include common_scripts\utility;
// ELEVATOR TEST
ELEVATOR_DOOR_TIME = 2;
ELEVATOR_FLOOR_MOVE_TIME = 5;
ELEVATOR_AUTOCLOSE_TIMEOUT = 10;
ELEVATOR_DOOR_STATE_CLOSED = 0;
ELEVATOR_DOOR_STATE_OPENING = 1;
ELEVATOR_DOOR_STATE_OPEN = 2;
ELEVATOR_DOOR_STATE_CLOSING = 3;
// should scale elevator door speed based on the actual distance moved
// in case of interrupts
init_elevator( config )
{
elevator = GetEnt( config.name, "targetname" );
AssertEx( IsDefined( elevator ), "Could not find an elevator entity named " + config.name );
elevator.unresolved_collision_func = ::handleUnreslovedCollision;
elevator.doors = [];
foreach ( floorname, doorset in config.doors )
{
list = [];
foreach ( doorname in doorset )
{
list[ list.size ] = setupDoor( doorName + "left", false, config.doorMoveDist );
list[ list.size ] = setupDoor( doorName + "right", true, config.doorMoveDist );
}
elevator.doors[ floorname ] = list;
}
elevator.trigBlock = GetEnt( config.trigBlockName, "targetname" );
AssertEx( IsDefined( elevator.trigBlock ), "Could not find an elevator trigger named " + config.trigBlockName );
elevator.curFloor = "floor1";
elevator.requestedFloor = elevator.curFloor;
elevator.doorState = ELEVATOR_DOOR_STATE_CLOSED;
elevator.doorOpenTime = 2.0;
elevator.doorSpeed = config.doorMoveDist / elevator.doorOpenTime;
elevator.moveTime = 5.0;
elevator.autoCloseTimeout = 10.0;
elevator.destinations = [];
elevator.pathBlockers = [];
elevator.buttons = GetEntArray( config.buttons, "targetname" );
foreach ( button in elevator.buttons )
{
button setupButton( elevator );
}
elevatorModels = GetEntArray( "elevator_models", "targetname" );
foreach ( eleModel in elevatorModels )
{
eleModel LinkTo( elevator );
}
elevator thread elevatorThink();
elevator thread openElevatorDoors( elevator.curFloor, false );
}
setupDoor( doorName, isRightSide, moveDistance )
{
door = GetEnt( doorName, "targetname" );
if (IsDefined(door))
{
door.closePos = door.origin;
if (IsDefined(door.target))
{
targetStruct = getstruct( door.target, "targetname" );
door.openPos = targetStruct.origin;
}
else
{
offset = AnglesToForward( door.angles ) * moveDistance;
/*
if (isRightSide)
{
offset *= -1;
}
*/
door.openPos = door.origin + offset;
}
// door.unresolved_collision_func = ::handleUnreslovedCollision;
return door;
}
else
{
AssertEx( IsDefined( door ), "Could not find an elevator door entity named " + doorName );
return;
}
}
setupButton( elevator ) // self == button
{
self.owner = elevator;
if ( IsDefined( self.target ) )
{
destination = getstruct( self.target, "targetname" );
if ( IsDefined( destination ) )
{
elevator.destinations[ self.script_label ] = destination.origin;
if ( IsDefined( destination.target ) )
{
blocker = GetEnt( destination.target, "targetname" );
if ( IsDefined( blocker ) )
{
elevator.pathBlockers[ self.script_label ] = blocker;
}
}
}
}
self enableButton();
}
enableButton() // self == button
{
self SetHintString( &"MP_ELEVATOR_USE" );
self MakeUsable();
self thread buttonThink();
}
disableButton()
{
self MakeUnusable();
}
buttonThink()
{
elevator = self.owner;
elevator endon( "elevator_busy" );
while ( true )
{
self waittill( "trigger" );
if ( self.script_label == "elevator" )
{
// do some stuff
if ( elevator.curFloor == "floor1" )
{
elevator.requestedFloor = "floor2";
}
else
{
elevator.requestedFloor = "floor1";
}
}
else
{
elevator.requestedFloor = self.script_label;
}
elevator notify( "elevator_called" );
}
}
elevatorThink()
{
while ( true )
{
self waittill( "elevator_called" );
foreach ( button in self.buttons )
{
button disableButton();
}
if ( self.curFloor != self.requestedFloor )
{
if ( self.doorState != ELEVATOR_DOOR_STATE_CLOSED )
{
self notify ("elevator_stop_autoclose");
self thread closeElevatorDoors( self.curFloor );
self waittill( "elevator_doors_closed" );
}
self elevatorMoveToFloor( self.requestedFloor );
wait (0.25);
}
self thread openElevatorDoors( self.curFloor, false );
self waittill ( "elevator_doors_open" );
foreach ( button in self.buttons )
{
button enableButton();
}
}
}
elevatorMoveToFloor( targetFloor )
{
self PlaySound( "scn_elevator_startup" );
self PlayLoopSound( "scn_elevator_moving_lp" );
destinationPos = self.destinations[ targetFloor ];
deltaZ = destinationPos[2] - self.origin[2];
// move doors
foreach ( door in self.doors[ "elevator" ] )
{
door MoveZ( deltaZ, self.moveTime );
}
// move the floor
self MoveZ( deltaZ, self.moveTime );
wait ( self.moveTime );
self StopLoopSound ( "scn_elevator_moving_lp" );
self PlaySound ( "scn_elevator_stopping" );
self PlaySound ( "scn_elevator_beep" );
self.curFloor = self.requestedFloor;
}
openElevatorDoors( floorName, autoClose ) // elevator
{
doorset = self.doors[ floorName ];
self.doorState = ELEVATOR_DOOR_STATE_OPENING;
// figre out the time it takes to move 1 door, assume it's the same fo rall
door = doorset[0];
doorDest = (door.openPos[0], door.openPos[1], door.origin[2]);
moveDelta = doorDest - door.origin;
moveDist = Length( moveDelta );
// this might move 0 time / 0 dist
// but we need it to counteract the closing elevator
// wish I could just tell it to stop, instead
movetime = moveDist / self.doorSpeed;
accelTime = 0.25;
if (moveTime == 0.0)
{
moveTime = 0.05;
accelTime = 0.0;
}
else
{
self PlaySound( "scn_elevator_doors_opening" );
accelTime = min(accelTime, moveTime);
}
foreach ( door in doorset )
{
door MoveTo( (door.openPos[0], door.openPos[1], door.origin[2]), movetime, 0.0, accelTime );
}
wait ( movetime );
self.doorState = ELEVATOR_DOOR_STATE_OPEN;
self notify ( "elevator_doors_open" );
self elevatorClearPath( floorName );
if ( autoClose )
{
self thread elevatorDoorsAutoClose();
}
}
closeElevatorDoors( floorName )
{
self endon( "elevator_close_interrupted" );
self thread watchCloseInterrupted( floorName );
doorset = self.doors[ floorName ];
self.doorState = ELEVATOR_DOOR_STATE_CLOSING;
// figre out the time it takes to move 1 door, assume it's the same fo rall
door = doorset[0];
doorDest = (door.closePos[0], door.closePos[1], door.origin[2]);
moveDelta = doorDest - door.origin;
moveDist = Length( moveDelta );
if ( moveDist != 0.0 )
{
movetime = moveDist / self.doorSpeed;
foreach ( door in doorset )
{
// we assume the doors all begin closed,
// so door.closePos should eventually be defined by the time we need it
door MoveTo( (door.closePos[0], door.closePos[1], door.origin[2]), movetime, 0.0, 0.25 );
}
self PlaySound( "scn_elevator_doors_closing" );
wait ( movetime );
}
self.doorState = ELEVATOR_DOOR_STATE_CLOSED;
self elevatorBlockPath( floorName );
self notify( "elevator_doors_closed" );
}
watchCloseInterrupted( floorName )
{
// if the doors have closed successfully, we don't care any more
self endon( "elevator_doors_closed" );
// make sure there is nothing in the way now
nothingBlocking = true;
foreach ( character in level.characters )
{
if ( character isTouchingTrigger( self.trigBlock ) )
{
nothingBlocking = false;
break;
}
}
if ( nothingBlocking )
{
self.trigBlock waittill( "trigger" );
}
self notify( "elevator_close_interrupted" );
self openElevatorDoors( floorName, true );
}
isTouchingTrigger( trigger ) // self == player
{
return ( IsAlive( self ) && self IsTouching( trigger ) );
}
elevatorDoorsAutoClose() // self == elevator
{
self endon( "elevator_doors_closed" );
self endon( "elevator_stop_autoclose" );
wait ( self.autoCloseTimeout );
self closeElevatorDoors( self.curFloor);
}
handleUnreslovedCollision( hitEnt ) // self == mover, hitEnt == player (usually)
{
if ( !IsPlayer( hitEnt ) )
{
hitEnt DoDamage( 1000, hitEnt.origin, self, self, "MOD_CRUSH" );
}
}
elevatorClearPath( floorName ) // self == elevator
{
blocker = self.pathBlockers[ floorName ];
if ( IsDefined( blocker ) )
{
blocker ConnectPaths();
blocker Hide();
blocker NotSolid();
}
}
elevatorBlockPath( floorName )
{
blocker = self.pathBlockers[ floorName ];
if ( IsDefined( blocker ) )
{
blocker Show();
blocker Solid();
blocker DisconnectPaths();
}
}

468
maps/mp/_elevator_v2.gsc Normal file
View File

@ -0,0 +1,468 @@
#include maps\mp\_utility;
#include common_scripts\utility;
// _elevator_v2: used in mp_mines.gsc (original was used in mp_fahrenheit).
// Making adjustments to allow for multiple types of elevators
// ELEVATOR TEST
ELEVATOR_DOOR_TIME = 2;
ELEVATOR_FLOOR_MOVE_TIME = 5;
ELEVATOR_AUTOCLOSE_TIMEOUT = 10;
ELEVATOR_DOOR_STATE_CLOSED = 0;
ELEVATOR_DOOR_STATE_OPENING = 1;
ELEVATOR_DOOR_STATE_OPEN = 2;
ELEVATOR_DOOR_STATE_CLOSING = 3;
// should scale elevator door speed based on the actual distance moved
// in case of interrupts
init_elevator( config )
{
elevator = GetEnt( config.name, "targetname" );
AssertEx( IsDefined( elevator ), "Could not find an elevator entity named " + config.name );
elevator.unresolved_collision_func = ::handleUnreslovedCollision;
elevator.doors = [];
if ( IsDefined( config.doors ) )
{
foreach ( floorname, doorset in config.doors )
{
list = [];
foreach ( doorname in doorset )
{
list[ list.size ] = setupDoor( doorName + "left", false, config.doorMoveDist );
list[ list.size ] = setupDoor( doorName + "right", true, config.doorMoveDist );
}
elevator.doors[ floorname ] = list;
}
if ( IsDefined( config.doorOpenTime ) )
elevator.doorOpenTime = config.doorOpenTime;
else
elevator.doorOpenTime = ELEVATOR_DOOR_TIME;
elevator.doorSpeed = config.doorMoveDist / elevator.doorOpenTime;
if ( IsDefined( config.autoCloseTimeout ) )
elevator.autoCloseTimeout = config.autoCloseTimeout;
else
elevator.autoCloseTimeout = ELEVATOR_AUTOCLOSE_TIMEOUT;
elevator.trigBlock = GetEnt( config.trigBlockName, "targetname" );
AssertEx( IsDefined( elevator.trigBlock ), "Could not find an elevator trigger named " + config.trigBlockName );
if ( IsDefined( config.autoCloseTimeout ) )
elevator.autoCloseTimeout = config.autoCloseTimeout;
else
elevator.autoCloseTimeout = ELEVATOR_AUTOCLOSE_TIMEOUT;
elevator.doorOpenSfx = config.doorOpenSfx; // scn_elevator_doors_opening
elevator.doorCloseSfx = config.doorCloseSfx; // scn_elevator_doors_closing
}
if ( IsDefined( config.moveTime ) )
elevator.moveTime = config.moveTime;
else
elevator.moveTime = ELEVATOR_FLOOR_MOVE_TIME;
elevator.destinations = [];
elevator.pathBlockers = [];
elevator.buttons = GetEntArray( config.buttons, "targetname" );
foreach ( button in elevator.buttons )
{
button setupButton( elevator );
}
// set up destinations
destinationStructs = getstructarray( config.destinations, "targetname" );
foreach ( destination in destinationStructs )
{
elevator setupDestination( destination );
}
elevator.destinationNames = config.destinationNames;
elevator.curFloor = config.destinationNames[0]; // "floor1"; should this be determined from destinations?
elevator.requestedFloor = elevator.curFloor;
elevator.doorState = ELEVATOR_DOOR_STATE_CLOSED;
if ( IsDefined( config.models ) )
{
elevatorModels = GetEntArray( config.models, "targetname" );
if ( IsDefined( elevatorModels ) )
{
foreach ( eleModel in elevatorModels )
{
eleModel LinkTo( elevator );
}
}
}
elevator thread elevatorThink();
if (elevator.doors.size > 0)
{
elevator thread openElevatorDoors( elevator.curFloor, false );
}
// sounds
elevator.startSfx = config.startSfx; // "scn_elevator_startup"
elevator.stopSfx = config.stopSfx; // "scn_elevator_stopping"
elevator.loopSfx = config.loopSfx; // "scn_elevator_moving_lp"
elevator.beepSfx = config.beepSfx; // "scn_elevator_beep"
// callback on init
elevator.onMoveCallback = config.onMoveCallback;
elevator.onArrivedCallback = config.onArrivedCallback;
return elevator;
}
setupDoor( doorName, isRightSide, moveDistance )
{
door = GetEnt( doorName, "targetname" );
if (IsDefined(door))
{
door.closePos = door.origin;
if (IsDefined(door.target))
{
targetStruct = getstruct( door.target, "targetname" );
door.openPos = targetStruct.origin;
}
else
{
offset = AnglesToForward( door.angles ) * moveDistance;
/*
if (isRightSide)
{
offset *= -1;
}
*/
door.openPos = door.origin + offset;
}
// door.unresolved_collision_func = ::handleUnreslovedCollision;
return door;
}
else
{
AssertEx( IsDefined( door ), "Could not find an elevator door entity named " + doorName );
return;
}
}
setupButton( elevator ) // self == button
{
self.owner = elevator;
if ( IsDefined( self.target ) )
{
destination = getstruct( self.target, "targetname" );
self setupDestination( destination );
}
self enableButton();
}
setupDestination( destination ) // self == elevator
{
if ( IsDefined( destination ) )
{
self.destinations[ destination.script_label ] = destination.origin;
if ( IsDefined( destination.target ) )
{
blocker = GetEnt( destination.target, "targetname" );
if ( IsDefined( blocker ) )
{
self.pathBlockers[ destination.script_label ] = blocker;
}
}
}
}
enableButton() // self == button
{
self SetHintString( &"MP_ELEVATOR_USE" );
self MakeUsable();
self thread buttonThink();
}
disableButton()
{
self MakeUnusable();
}
buttonThink()
{
elevator = self.owner;
elevator endon( "elevator_busy" );
while ( true )
{
self waittill( "trigger" );
if ( !IsDefined( self.script_label ) || self.script_label == "elevator" )
{
// do some stuff
if ( elevator.curFloor == elevator.destinationNames[0] )
{
elevator.requestedFloor = elevator.destinationNames[1];
}
else
{
elevator.requestedFloor = elevator.destinationNames[0];
}
}
else
{
elevator.requestedFloor = self.script_label;
}
elevator notify( "elevator_called" );
}
}
elevatorThink()
{
hasDoors = self.doors.size > 0;
while ( true )
{
self waittill( "elevator_called" );
foreach ( button in self.buttons )
{
button disableButton();
}
if ( self.curFloor != self.requestedFloor )
{
if ( self.doorState != ELEVATOR_DOOR_STATE_CLOSED )
{
self notify ("elevator_stop_autoclose");
self thread closeElevatorDoors( self.curFloor );
self waittill( "elevator_doors_closed" );
}
else if ( !hasDoors )
{
self elevatorBlockPath( self.curFloor );
}
self elevatorMoveToFloor( self.requestedFloor );
wait (0.25);
}
if ( hasDoors )
{
self thread openElevatorDoors( self.curFloor, false );
self waittill ( "elevator_doors_open" );
}
else
{
self elevatorClearPath( self.curFloor );
}
foreach ( button in self.buttons )
{
button enableButton();
}
}
}
elevatorMoveToFloor( targetFloor )
{
//self PlaySound( self.startSfx );
//self PlayLoopSound( self.loopSfx );
destinationPos = self.destinations[ targetFloor ];
deltaZ = destinationPos[2] - self.origin[2]; // may need to change this to full vector later
if ( IsDefined( self.doors[ "elevator" ] ) )
{
// move doors
foreach ( door in self.doors[ "elevator" ] )
{
door MoveZ( deltaZ, self.moveTime );
}
}
// move the floor
self MoveZ( deltaZ, self.moveTime );
if ( IsDefined( self.onMoveCallback ) )
{
self thread [[ self.onMoveCallback ]]( targetFloor );
}
wait ( self.moveTime );
//self StopLoopSound ( self.loopSfx );
//self PlaySound ( self.stopSfx );
if ( IsDefined( self.beepSfx ) )
self PlaySound ( self.beepSfx );
self.curFloor = self.requestedFloor;
if ( IsDefined( self.onArrivedCallback ) )
{
self thread [[ self.onArrivedCallback ]]( self.curFloor );
}
}
openElevatorDoors( floorName, autoClose ) // elevator
{
doorset = self.doors[ floorName ];
self.doorState = ELEVATOR_DOOR_STATE_OPENING;
// figre out the time it takes to move 1 door, assume it's the same fo rall
door = doorset[0];
doorDest = (door.openPos[0], door.openPos[1], door.origin[2]);
moveDelta = doorDest - door.origin;
moveDist = Length( moveDelta );
// this might move 0 time / 0 dist
// but we need it to counteract the closing elevator
// wish I could just tell it to stop, instead
movetime = moveDist / self.doorSpeed;
accelTime = 0.25;
if (moveTime == 0.0)
{
moveTime = 0.05;
accelTime = 0.0;
}
else
{
self PlaySound( self.doorOpenSfx );
accelTime = min(accelTime, moveTime);
}
foreach ( door in doorset )
{
door MoveTo( (door.openPos[0], door.openPos[1], door.origin[2]), movetime, 0.0, accelTime );
}
wait ( movetime );
self.doorState = ELEVATOR_DOOR_STATE_OPEN;
self notify ( "elevator_doors_open" );
self elevatorClearPath( floorName );
if ( autoClose )
{
self thread elevatorDoorsAutoClose();
}
}
closeElevatorDoors( floorName )
{
self endon( "elevator_close_interrupted" );
self thread watchCloseInterrupted( floorName );
doorset = self.doors[ floorName ];
self.doorState = ELEVATOR_DOOR_STATE_CLOSING;
// figre out the time it takes to move 1 door, assume it's the same fo rall
door = doorset[0];
doorDest = (door.closePos[0], door.closePos[1], door.origin[2]);
moveDelta = doorDest - door.origin;
moveDist = Length( moveDelta );
if ( moveDist != 0.0 )
{
movetime = moveDist / self.doorSpeed;
foreach ( door in doorset )
{
// we assume the doors all begin closed,
// so door.closePos should eventually be defined by the time we need it
door MoveTo( (door.closePos[0], door.closePos[1], door.origin[2]), movetime, 0.0, 0.25 );
}
self PlaySound( self.doorCloseSfx );
wait ( movetime );
}
self.doorState = ELEVATOR_DOOR_STATE_CLOSED;
self elevatorBlockPath( floorName );
self notify( "elevator_doors_closed" );
}
watchCloseInterrupted( floorName )
{
// if the doors have closed successfully, we don't care any more
self endon( "elevator_doors_closed" );
// make sure there is nothing in the way now
nothingBlocking = true;
foreach ( character in level.characters )
{
if ( character isTouchingTrigger( self.trigBlock ) )
{
nothingBlocking = false;
break;
}
}
if ( nothingBlocking )
{
self.trigBlock waittill( "trigger" );
}
self notify( "elevator_close_interrupted" );
self openElevatorDoors( floorName, true );
}
isTouchingTrigger( trigger ) // self == player
{
return ( IsAlive( self ) && self IsTouching( trigger ) );
}
elevatorDoorsAutoClose() // self == elevator
{
self endon( "elevator_doors_closed" );
self endon( "elevator_stop_autoclose" );
wait ( self.autoCloseTimeout );
self closeElevatorDoors( self.curFloor);
}
handleUnreslovedCollision( hitEnt ) // self == mover, hitEnt == player (usually)
{
if ( !IsPlayer( hitEnt ) )
{
hitEnt DoDamage( 1000, hitEnt.origin, self, self, "MOD_CRUSH" );
}
}
elevatorClearPath( floorName ) // self == elevator
{
blocker = self.pathBlockers[ floorName ];
if ( IsDefined( blocker ) )
{
blocker ConnectPaths();
blocker Hide();
blocker NotSolid();
}
}
elevatorBlockPath( floorName )
{
blocker = self.pathBlockers[ floorName ];
if ( IsDefined( blocker ) )
{
blocker Show();
blocker Solid();
blocker DisconnectPaths();
}
}

171
maps/mp/_empgrenade.gsc Normal file
View File

@ -0,0 +1,171 @@
#include maps\mp\_utility;
#include common_scripts\utility;
#include maps\mp\killstreaks\_emp_common;
init()
{
thread onPlayerConnect();
}
onPlayerConnect()
{
for(;;)
{
level waittill("connected", player);
player thread onPlayerSpawned();
}
}
onPlayerSpawned()
{
self endon("disconnect");
for(;;)
{
self waittill( "spawned_player" );
self thread monitorEMPGrenade();
}
}
monitorEMPGrenade()
{
self endon("death");
self endon("disconnect");
self endon("faux_spawn");
self.empEndTime = 0;
while(1)
{
// self waittill( "emp_grenaded", attacker );
self waittill( "emp_damage", attacker, duration );
if ( !IsAlive( self )
|| IsDefined( self.usingRemote )
|| ( self _hasPerk( "specialty_empimmune" ) ) //MW3 emp resistance perk
|| !IsDefined( attacker )
)
{
continue;
}
hurtVictim = true;
hurtAttacker = false;
assert( IsDefined(self.pers["team"]) );
if ( level.teamBased
&& attacker != self
&& IsDefined(attacker.pers["team"])
&& attacker.pers["team"] == self.pers["team"]
)
{
if(level.friendlyfire == 0) // no FF
{
continue;
}
else if(level.friendlyfire == 1) // FF
{
hurtattacker = false;
hurtvictim = true;
}
else if(level.friendlyfire == 2) // reflect
{
hurtvictim = false;
hurtattacker = true;
}
else if(level.friendlyfire == 3) // share
{
hurtattacker = true;
hurtvictim = true;
}
}
else
{
attacker notify( "emp_hit" );
if( attacker != self )
{
attacker maps\mp\gametypes\_missions::processChallenge( "ch_onthepulse" );
}
}
if ( hurtvictim && IsDefined(self) )
{
self thread applyEMP( duration );
}
if ( hurtattacker )
{
attacker thread applyEMP( duration );
}
}
}
applyEMP( duration )
{
self notify( "applyEmp" );
self endon( "applyEmp" );
self endon( "disconnect" );
self endon( "death" );
wait .05;
self.empGrenaded = true;
self shellshock( "flashbang_mp", 1 );
self.empEndTime = GetTime() + (duration * 1000);
self applyPerPlayerEMPEffects_OnDetonate();
self applyPerPlayerEMPEffects();
self thread empRumbleLoop( .75 );
self thread empGrenadeDeathWaiter();
wait ( duration );
self notify( "empGrenadeTimedOut" );
self checkToTurnOffEmp();
}
empGrenadeDeathWaiter()
{
self notify( "empGrenadeDeathWaiter" );
self endon( "empGrenadeDeathWaiter" );
self endon( "empGrenadeTimedOut" );
self waittill( "death" );
self checkToTurnOffEmp();
}
checkToTurnOffEmp()
{
self.empGrenaded = false;
if ( !(self shouldPlayerBeAffectedByEMP()) )
{
self removePerPlayerEMPEffects();
}
}
empRumbleLoop( duration )
{
self endon("emp_rumble_loop");
self notify("emp_rumble_loop");
goalTime = GetTime() + duration * 1000;
while ( GetTime() < goalTime )
{
self PlayRumbleOnEntity( "damage_heavy" );
wait( 0.05 );
}
}
// 2013-06-30 wallace: is isEMPGrenaded being used any more? Not sure if we even need the timestamp
isEMPGrenaded()
{
return isDefined( self.empEndTime ) && gettime() < self.empEndTime;
}

View File

@ -0,0 +1,331 @@
#include maps\mp\_utility;
#include common_scripts\utility;
#include maps\mp\gametypes\_hud_util;
init()
{
if (isdefined(level.initedEntityHeadIcons))
return;
level.initedEntityHeadIcons = true;
if( level.multiTeamBased )
{
foreach ( teamName in level.teamNameList )
{
str_team_headicon = "entity_headicon_" + teamName;
game[ str_team_headicon ] = maps\mp\gametypes\_teams::MT_getTeamHeadIcon( teamName );
precacheShader( game[ str_team_headicon ] );
}
}
else
{
game["entity_headicon_allies"] = maps\mp\gametypes\_teams::getTeamHeadIcon( "allies" );
game["entity_headicon_axis"] = maps\mp\gametypes\_teams::getTeamHeadIcon( "axis" );
precacheShader( game["entity_headicon_allies"] );
precacheShader( game["entity_headicon_axis"] );
}
}
// This can show to single players or to teams. Showing to a single player destroys instances of
// the icon that are shown to their team. Showing to a team destroys instances of the icon that
// are shown to players on that team
setHeadIcon( showTo, icon, offset, width, height, archived, delay, constantSize, pinToScreenEdge, fadeOutPinnedIcon, is3D )
{
if ( IsGameParticipant( showTo ) && !IsPlayer( showTo ) )
return; // Doesn't work for Agents, etc.
if ( !isDefined( self.entityHeadIcons ) )
self.entityHeadIcons = [];
if( !IsDefined( archived ) )
archived = true;
if( !IsDefined( delay ) )
delay = 0.05;
if( !IsDefined( constantSize ) )
constantSize = true;
if( !IsDefined( pinToScreenEdge ) )
pinToScreenEdge = true;
if( !IsDefined( fadeOutPinnedIcon ) )
fadeOutPinnedIcon = false;
if( !IsDefined( is3D ) )
is3D = true;
if ( !isPlayer( showTo ) && showTo == "none" )
{
foreach ( key, headIcon in self.entityHeadIcons )
{
// TODO: remove and fix properly after ship
if ( isDefined( headIcon ) )
headIcon destroy();
self.entityHeadIcons[ key ] = undefined;
}
return;
}
if ( isPlayer( showTo ) )
{
if ( isDefined( self.entityHeadIcons[ showTo.guid ] ) )
{
self.entityHeadIcons[ showTo.guid ] destroy();
self.entityHeadIcons[ showTo.guid ] = undefined;
}
if ( icon == "" )
return;
if ( isDefined(showTo.team) )
{
// remove from team or we'd have two icons
if ( isDefined( self.entityHeadIcons[ showTo.team ] ) )
{
self.entityHeadIcons[ showTo.team ] destroy();
self.entityHeadIcons[ showTo.team ] = undefined;
}
}
headIcon = newClientHudElem( showTo );
self.entityHeadIcons[ showTo.guid ] = headIcon;
}
else
{
assert( showTo == "axis" || showTo == "allies" || isSubStr( showTo, "team_" ));
assert( level.teamBased );
if ( isDefined( self.entityHeadIcons[ showTo ] ) )
{
self.entityHeadIcons[ showTo ] destroy();
self.entityHeadIcons[ showTo ] = undefined;
}
if ( icon == "" )
return;
foreach ( key, hudIcon in self.entityHeadIcons )
{
if ( key == "axis" || key == "allies" )
continue;
player = getPlayerForGuid( key );
if ( player.team == showTo )
{
self.entityHeadIcons[ key ] destroy();
self.entityHeadIcons[ key ] = undefined;
}
}
headIcon = newTeamHudElem( showTo );
self.entityHeadIcons[ showTo ] = headIcon;
}
if ( !isDefined( width ) || !isDefined( height ) )
{
width = 10;
height = 10;
}
headIcon.archived = archived;
headIcon.x = self.origin[0] + offset[0];
headIcon.y = self.origin[1] + offset[1];
headIcon.z = self.origin[2] + offset[2];
headIcon.alpha = 0.85;
headIcon setShader( icon, width, height );
headIcon setWaypoint( constantSize, pinToScreenEdge, fadeOutPinnedIcon, is3D );
headIcon thread keepPositioned( self, offset, delay );
self thread destroyIconsOnDeath();
if ( isPlayer( showTo ) )
headIcon thread destroyOnOwnerDisconnect( showTo );
if ( isPlayer( self ) )
headIcon thread destroyOnOwnerDisconnect( self );
return headIcon;
}
destroyOnOwnerDisconnect( owner )
{
self endon ( "death" );
owner waittill ( "disconnect" );
self destroy();
}
destroyIconsOnDeath()
{
self notify ( "destroyIconsOnDeath" );
self endon ( "destroyIconsOnDeath" );
self waittill ( "death" );
if ( !isDefined( self.entityHeadIcons ) )
return;
foreach ( key, headIcon in self.entityHeadIcons )
{
// TODO: remove and fix properly after ship
if( !isDefined(headIcon) ) //needed for FFA host migration (when host has active head icons)
continue;
headIcon destroy();
}
}
keepPositioned( owner, offset, delay )
{
self endon ( "death" );
owner endon ( "death" );
owner endon ( "disconnect" );
allowCodeLink = ( IsDefined(owner.classname) && !isOwnerCarePakage(owner) );
if( allowCodeLink )
{
self LinkWaypointToTargetWithOffset( owner, offset );
}
for ( ;; )
{
if( !IsDefined( owner ) )
return;
if( !allowCodeLink )
{
pos = owner.origin;
self.x = pos[0] + offset[0];
self.y = pos[1] + offset[1];
self.z = pos[2] + offset[2];
}
if ( delay > 0.05 )
{
self.alpha = 0.85;
self FadeOverTime( delay );
self.alpha = 0;
}
wait delay;
}
}
isOwnerCarePakage( owner )
{
return ( IsDefined(owner.targetname) && ( owner.targetname == "care_package" ) );
}
setTeamHeadIcon( team, offset ) // "allies", "axis", "all", "none"
{
if ( !level.teamBased )
return;
if ( !isDefined( self.entityHeadIconTeam ) )
{
self.entityHeadIconTeam = "none";
self.entityHeadIcon = undefined;
}
shader = game["entity_headicon_" + team];
self.entityHeadIconTeam = team;
if ( isDefined( offset ) )
self.entityHeadIconOffset = offset;
else
self.entityHeadIconOffset = (0,0,0);
self notify( "kill_entity_headicon_thread" );
if ( team == "none" )
{
if ( isDefined( self.entityHeadIcon ) )
self.entityHeadIcon destroy();
return;
}
headIcon = newTeamHudElem( team );
headIcon.archived = true;
headIcon.x = self.origin[0] + self.entityHeadIconOffset[0];
headIcon.y = self.origin[1] + self.entityHeadIconOffset[1];
headIcon.z = self.origin[2] + self.entityHeadIconOffset[2];
headIcon.alpha = .8;
headIcon setShader( shader, 10, 10 );
headIcon setWaypoint( false, false, false, true );
self.entityHeadIcon = headIcon;
self thread keepIconPositioned();
self thread destroyHeadIconsOnDeath();
}
setPlayerHeadIcon( player, offset ) // "allies", "axis", "all", "none"
{
if ( level.teamBased )
return;
if ( !isDefined( self.entityHeadIconTeam ) )
{
self.entityHeadIconTeam = "none";
self.entityHeadIcon = undefined;
}
self notify( "kill_entity_headicon_thread" );
if ( !isDefined( player ) )
{
if ( isDefined( self.entityHeadIcon ) )
self.entityHeadIcon destroy();
return;
}
team = player.team;
self.entityHeadIconTeam = team;
if ( isDefined( offset ) )
self.entityHeadIconOffset = offset;
else
self.entityHeadIconOffset = (0,0,0);
shader = game["entity_headicon_" + team];
headIcon = newClientHudElem( player );
headIcon.archived = true;
headIcon.x = self.origin[0] + self.entityHeadIconOffset[0];
headIcon.y = self.origin[1] + self.entityHeadIconOffset[1];
headIcon.z = self.origin[2] + self.entityHeadIconOffset[2];
headIcon.alpha = .8;
headIcon setShader( shader, 10, 10 );
headIcon setWaypoint( false, false, false, true );
self.entityHeadIcon = headIcon;
self thread keepIconPositioned();
self thread destroyHeadIconsOnDeath();
}
keepIconPositioned()
{
self.entityHeadIcon LinkWaypointToTargetWithOffset( self, self.entityHeadIconOffset );
}
destroyHeadIconsOnDeath()
{
self endon( "kill_entity_headicon_thread" );
self waittill ( "death" );
// TODO: remove and fix properly after ship
if( !isDefined(self.entityHeadIcon) )
return;
self.entityHeadIcon destroy();
}

984
maps/mp/_events.gsc Normal file
View File

@ -0,0 +1,984 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
init()
{
// load all of the scoring data for the current game mode
game_type_col = [];
game_type_col[ "dm" ] = 3; // free for all
game_type_col[ "war" ] = 4; // team deathmatch
game_type_col[ "sd" ] = 5; // search and destroy
game_type_col[ "dom" ] = 6; // domination
game_type_col[ "conf" ] = 7; // kill confirmed
game_type_col[ "sr" ] = 8; // search and rescue
game_type_col[ "bnty" ] = 9; // bounty
game_type_col[ "grind" ] = 10; // grind
game_type_col[ "blitz" ] = 11; // blitz
game_type_col[ "cranked" ] = 12; // cranked
game_type_col[ "infect" ] = 13; // infected
game_type_col[ "sotf" ] = 14; // survival of the fittest
game_type_col[ "sotf_ffa" ] = 15; // survival of the fittest FFA
game_type_col[ "horde" ] = 16; // horde
game_type_col[ "mugger" ] = 17; // mugger
game_type_col[ "aliens" ] = 18; // aliens
game_type_col[ "gun" ] = 19; // gun game
game_type_col[ "grnd" ] = 20; // drop zone
game_type_col[ "siege" ] = 21; // reinforce
game_type = level.gameType;
if( !IsDefined( game_type ) )
game_type = GetDvar( "g_gametype" );
row = 0;
while( true )
{
value = TableLookupByRow( "mp/xp_event_table.csv", row, game_type_col[ game_type ] );
if( !IsDefined( value ) || value == "" )
break;
ref = TableLookupByRow( "mp/xp_event_table.csv", row, 0 );
if( ref == "win" || ref == "loss" || ref == "tie" )
value = float( value );
else
value = int( value );
if( value != -1 )
maps\mp\gametypes\_rank::registerScoreInfo( ref, value );
row++;
}
// end scoring data
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "damage", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "heavy_damage", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "damaged", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "kill", 1 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "killed", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "healed", 0);
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "headshot", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "melee", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "backstab", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "longshot", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "pointblank", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "assistedsuicide", 0);
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "defender", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "avenger", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "execution", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "comeback", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "revenge", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "buzzkill", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "double", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "triple", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "multi", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "assist", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "firstBlood", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "capture", 1 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "assistedCapture", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "plant", 1 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "defuse", 1 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "vehicleDestroyed", 1);
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "3streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "4streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "5streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "6streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "7streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "8streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "9streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "10streak", 0 );
maps\mp\killstreaks\_killstreaks::registerAdrenalineInfo( "regen", 0 );
precacheShader( "crosshair_red" );
level._effect["money"] = loadfx ("fx/props/cash_player_drop");
level.numKills = 0;
level thread onPlayerConnect();
}
onPlayerConnect()
{
for(;;)
{
level waittill( "connected", player );
player.killedPlayers = [];
player.killedPlayersCurrent = [];
player.ch_extremeCrueltyComplete = false; // setting a player var to throttle challenge completion rate
player.ch_tangoDownComplete = false; // for iw7 we should handle this in the challenge table
player.killedBy = [];
player.lastKilledBy = undefined;
player.greatestUniquePlayerKills = 0;
player.recentKillCount = 0;
player.lastKillTime = 0;
player.lastKillDogTime = 0;
player.damagedPlayers = [];
player thread monitorCrateJacking();
player thread monitorObjectives();
player thread monitorHealed();
}
}
damagedPlayer( victim, damage, weapon )
{
if ( damage < 50 && damage > 10 )
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "damage" );
else
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "heavy_damage" );
}
//notifies killed player over necessary frames
killedPlayerNotifySys( killId, victim, weapon, meansOfDeath )
{
self endon ( "disconnect" );
level endon ( "game_ended" );
self notify ( "killedPlayerNotify" );
self endon ( "killedPlayerNotify" );
if( !isDefined( self.killsInAFrameCount ) )
self.killsInAFrameCount = 0;
self.killsInAFrameCount++;
wait ( 0.05 );
if ( self.killsInAFrameCount > 1 )
self thread notifyKilledPlayer( killId, victim, weapon, meansOfDeath, self.killsInAFrameCount );
else
self notify( "got_a_kill", victim, weapon, meansOfDeath );
self.killsInAFrameCount = 0;
}
//possible loss of proper killID etc here. Using last killed properties
notifyKilledPlayer( killId, victim, weapon, meansOfDeath, numKills )
{
for( i = 0; i < numKills; i++ )
{
//used by intel
self notify( "got_a_kill", victim, weapon, meansOfDeath );
wait ( 0.05 );
}
}
killedPlayer( killId, victim, weapon, meansOfDeath )
{
victimGuid = victim.guid;
myGuid = self.guid;
curTime = getTime();
self thread killedPlayerNotifySys( killId, victim, weapon, meansOfDeath );
self thread updateRecentKills( killId );
self.lastKillTime = getTime();
self.lastKilledPlayer = victim;
self.modifiers = [];
level.numKills++;
// a player is either damaged, or killed; never both
self.damagedPlayers[victimGuid] = undefined;
if ( !isKillstreakWeapon( weapon ) && !self isJuggernaut() && !self _hasPerk( "specialty_explosivebullets" ) )
{
if ( weapon == "none" )
return false;
// added a failsafe here because this could be the victim killing themselves with something like the dead man's hand deathstreak
if ( victim.attackers.size == 1 && !IsDefined( victim.attackers[victim.guid] ) )
{
/#
if ( !isDefined( victim.attackers[self.guid] ) )
{
println("Weapon: " + weapon );
println("meansOfDeath: " + meansOfDeath );
println("Attacker GUID: " + self.guid + " (name: " + self.name + ")" );
i = 0;
foreach ( key,value in victim.attackers )
{
println( "victim.attackers " + i + " GUID: " + key + " (name: " + value.name + ")" );
i++;
}
}
#/
assertEx( isDefined( victim.attackers[self.guid] ), "See console log for details" );
weaponClass = getWeaponClass( weapon );
if( weaponClass == "weapon_sniper" &&
meansOfDeath != "MOD_MELEE" &&
getTime() == victim.attackerData[self.guid].firstTimeDamaged )
{
self.modifiers["oneshotkill"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "one_shot_kill" );
}
}
if ( isDefined( victim.throwingGrenade ) && victim.throwingGrenade == "frag_grenade_mp" )
self.modifiers["cooking"] = true;
if ( isDefined(self.assistedSuicide) && self.assistedSuicide )
self assistedSuicide( killId, weapon, meansOfDeath );
if ( level.numKills == 1 )
self firstBlood( killId, weapon, meansOfDeath );
if ( self.pers["cur_death_streak"] > 3 )
self comeBack( killId, weapon, meansOfDeath );
if ( meansOfDeath == "MOD_HEAD_SHOT" )
{
if ( isDefined( victim.lastStand ) )
execution( killId, weapon, meansOfDeath );
else
headShot( killId, weapon, meansOfDeath );
}
if ( isDefined(self.wasti) && self.wasti && getTime() - self.spawnTime <= 5000 )
self.modifiers["jackintheboxkill"] = true;
if ( !isAlive( self ) && self.deathtime + 800 < getTime() )
postDeathKill( killId );
if ( level.teamBased && curTime - victim.lastKillTime < 500 )
{
if ( victim.lastkilledplayer != self )
self avengedPlayer( killId, weapon, meansOfDeath );
}
if ( IsDefined( victim.lastKillDogTime ) && curTime - victim.lastKillDogTime < 2000 )
{
self avengedDog( killId, weapon, meansOfDeath );
}
foreach ( guid, damageTime in victim.damagedPlayers )
{
if ( guid == self.guid )
continue;
if ( level.teamBased && curTime - damageTime < 500 )
self defendedPlayer( killId, weapon, meansOfDeath );
}
if ( isDefined( victim.attackerPosition ) )
attackerPosition = victim.attackerPosition;
else
attackerPosition = self.origin;
if ( isPointBlank ( self, weapon, meansOfDeath, attackerPosition, victim ) )
self thread pointblank( killId, weapon, meansOfDeath );
else if( isLongShot( self, weapon, meansOfDeath, attackerPosition, victim ) )
self thread longshot( killId, weapon, meansOfDeath );
victim_pers_cur_kill_streak = victim.pers[ "cur_kill_streak" ];
if ( victim_pers_cur_kill_streak > 0 && isDefined( victim.killstreaks[ victim_pers_cur_kill_streak + 1 ] ) )
{
// playercard splash for the killstreak stopped
self buzzKill( killId, victim, weapon, meansOfDeath );
}
self thread checkMatchDataKills( killId, victim, weapon, meansOfDeath);
}
else if( weapon == "guard_dog_mp" )
{
if( !isAlive( self ) && self.deathtime < GetTime() )
postDeathDogKill();
}
if ( !isDefined( self.killedPlayers[victimGuid] ) )
self.killedPlayers[victimGuid] = 0;
if ( !isDefined( self.killedPlayersCurrent[victimGuid] ) )
self.killedPlayersCurrent[victimGuid] = 0;
if ( !isDefined( victim.killedBy[myGuid] ) )
victim.killedBy[myGuid] = 0;
self.killedPlayers[victimGuid]++;
//this sets player stat for routine customer award
if ( self.killedPlayers[victimGuid] > self.greatestUniquePlayerKills )
self setPlayerStat( "killedsameplayer", self.killedPlayers[victimGuid] );
self.killedPlayersCurrent[victimGuid]++;
victim.killedBy[myGuid]++;
victim.lastKilledBy = self;
}
isLongShot( attacker, weapon, meansOfDeath, attackerPosition, victim )
{
if( isAlive( attacker ) &&
!attacker isUsingRemote() &&
( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_HEAD_SHOT" ) &&
!isKillstreakWeapon( weapon ) && !isDefined( attacker.assistedSuicide ) )
{
// check depending on the weapon being used to kill
thisWeaponClass = getWeaponClass( weapon );
switch( thisWeaponClass )
{
case "weapon_pistol":
weapDist = 800;
break;
case "weapon_smg":
weapDist = 1200;
break;
case "weapon_dmr":
case "weapon_assault":
case "weapon_lmg":
weapDist = 1500;
break;
case "weapon_sniper":
weapDist = 2000;
break;
case "weapon_shotgun":
weapDist = 500;
break;
case "weapon_projectile":
default:
weapDist = 1536; // the old number
break;
}
weapDistSq = weapDist * weapDist;
if( DistanceSquared( attackerPosition, victim.origin ) > weapDistSq )
{
if( attacker IsItemUnlocked( "specialty_holdbreath" ) && attacker _hasPerk( "specialty_holdbreath" ) )
attacker maps\mp\gametypes\_missions::processChallenge( "ch_longdistance" );
return true;
}
}
return false;
}
isPointBlank( attacker, weapon, meansOfDeath, attackerPosition, victim )
{
if( isAlive( attacker ) &&
!attacker isUsingRemote() &&
( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" || meansOfDeath == "MOD_HEAD_SHOT" ) &&
!isKillstreakWeapon( weapon ) && !isDefined( attacker.assistedSuicide ) )
{
// point blank is the same for all classes of weapons, about 8'
weapDistSq = 96 * 96;
if( DistanceSquared( attackerPosition, victim.origin ) < weapDistSq )
{
return true;
}
}
return false;
}
checkMatchDataKills( killId, victim, weapon, meansOfDeath )
{
weaponClass = getWeaponClass( weapon );
alreadyUsed = false;
self thread camperCheck();
if ( isDefined( self.lastKilledBy ) && self.lastKilledBy == victim )
{
self.lastKilledBy = undefined;
self revenge( killId );
}
if ( victim.iDFlags & level.iDFLAGS_PENETRATION )
self incPlayerStat( "bulletpenkills", 1 );
self_pers_rank = self.pers["rank"];
victim_pers_rank = victim.pers["rank"];
if ( self_pers_rank < victim_pers_rank )
self incPlayerStat( "higherrankkills", 1 );
if ( self_pers_rank > victim_pers_rank )
self incPlayerStat( "lowerrankkills", 1 );
if ( isDefined( self.inFinalStand ) && self.inFinalStand )
self incPlayerStat( "laststandkills", 1 );
if ( isDefined( victim.inFinalStand ) && victim.inFinalStand )
self incPlayerStat( "laststanderkills", 1 );
if ( self getCurrentWeapon() != self.primaryWeapon && self getCurrentWeapon() != self.secondaryWeapon )
self incPlayerStat( "otherweaponkills", 1 );
timeAlive = getTime() - victim.spawnTime ;
if( !matchMakingGame() )
victim setPlayerStatIfLower( "shortestlife", timeAlive );
victim setPlayerStatIfGreater( "longestlife", timeAlive );
if( meansOfDeath != "MOD_MELEE" )
{
switch( weaponClass )
{
case "weapon_pistol":
case "weapon_smg":
case "weapon_assault":
case "weapon_projectile":
case "weapon_dmr":
case "weapon_sniper":
case "weapon_shotgun":
case "weapon_lmg":
self checkMatchDataWeaponKills( victim, weapon, meansOfDeath, weaponClass );
break;
case "weapon_grenade":
case "weapon_explosive":
self checkMatchDataEquipmentKills( victim, weapon, meansOfDeath );
break;
default:
break;
}
}
}
// Need to make sure these only apply to kills of an enemy, not friendlies or yourself
checkMatchDataWeaponKills( victim, weapon, meansOfDeath, weaponType )
{
attacker = self;
kill_ref = undefined;
headshot_ref = undefined;
death_ref = undefined;
switch( weaponType )
{
case "weapon_pistol":
kill_ref = "pistolkills";
headshot_ref = "pistolheadshots";
break;
case "weapon_smg":
kill_ref = "smgkills";
headshot_ref = "smgheadshots";
break;
case "weapon_assault":
kill_ref = "arkills";
headshot_ref = "arheadshots";
break;
case "weapon_projectile":
if ( weaponClass( weapon ) == "rocketlauncher" )
kill_ref = "rocketkills";
break;
case "weapon_dmr":
kill_ref = "dmrkills";
headshot_ref = "dmrheadshots";
break;
case "weapon_sniper":
kill_ref = "sniperkills";
headshot_ref = "sniperheadshots";
break;
case "weapon_shotgun":
kill_ref = "shotgunkills";
headshot_ref = "shotgunheadshots";
death_ref = "shotgundeaths";
break;
case "weapon_lmg":
kill_ref = "lmgkills";
headshot_ref = "lmgheadshots";
break;
default:
break;
}
if ( isDefined ( kill_ref ) )
attacker incPlayerStat( kill_ref, 1 );
if ( isDefined ( headshot_ref ) && meansOfDeath == "MOD_HEAD_SHOT" )
attacker incPlayerStat( headshot_ref, 1 );
if ( isDefined ( death_ref ) && !matchMakingGame() )
victim incPlayerStat( death_ref, 1 );
if ( attacker isPlayerAds() )
{
attacker incPlayerStat( "adskills", 1 );
isThermal = IsSubStr( weapon, "thermal" );
// If weapon sniper, or acog or scope. Scope covers weapon_dmr with default scope
if ( isThermal || IsSubStr( weapon, "acog" ) || IsSubStr( weapon, "scope" ) )
attacker incPlayerStat( "scopedkills", 1 );
if ( isThermal )
attacker incPlayerStat( "thermalkills", 1 );
}
else
{
attacker incPlayerStat( "hipfirekills", 1 );
}
}
// Need to make sure these only apply to kills of an enemy, not friendlies or yourself
checkMatchDataEquipmentKills( victim, weapon, meansOfDeath )
{
attacker = self;
// equipment kills
switch( weapon )
{
case "frag_grenade_mp":
attacker incPlayerStat( "fragkills", 1 );
attacker incPlayerStat( "grenadekills", 1 );
isEquipment = true;
break;
case "c4_mp":
attacker incPlayerStat( "c4kills", 1 );
isEquipment = true;
break;
case "semtex_mp":
attacker incPlayerStat( "semtexkills", 1 );
attacker incPlayerStat( "grenadekills", 1 );
isEquipment = true;
break;
case "claymore_mp":
attacker incPlayerStat( "claymorekills", 1 );
isEquipment = true;
break;
case "throwingknife_mp":
attacker incPlayerStat( "throwingknifekills", 1 );
self thread maps\mp\gametypes\_rank::xpEventPopup( "knifethrow" );
isEquipment = true;
break;
default:
isEquipment = false;
break;
}
if ( isEquipment )
attacker incPlayerStat( "equipmentkills", 1 );
}
camperCheck()
{
self.lastKillWasCamping = false;
if ( !isDefined ( self.lastKillLocation ) )
{
self.lastKillLocation = self.origin;
self.lastCampKillTime = getTime();
return;
}
if ( Distance( self.lastKillLocation, self.origin ) < 512 && getTime() - self.lastCampKillTime > 5000 )
{
self incPlayerStat( "mostcamperkills", 1 );
self.lastKillWasCamping = true;
}
self.lastKillLocation = self.origin;
self.lastCampKillTime = getTime();
}
consolation( killId )
{
/*
value = int( maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 0.25 );
self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "consolation", value );
self thread maps\mp\gametypes\_rank::giveRankXP( "consolation", value );
*/
}
proximityAssist( killId )
{
self.modifiers["proximityAssist"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "proximityassist" );
self thread maps\mp\gametypes\_rank::giveRankXP( "proximityassist" );
//self thread maps\mp\_matchdata::logKillEvent( killId, "proximityAssist" );
}
proximityKill( killId )
{
self.modifiers["proximityKill"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "proximitykill" );
self thread maps\mp\gametypes\_rank::giveRankXP( "proximitykill" );
//self thread maps\mp\_matchdata::logKillEvent( killId, "proximityKill" );
}
longshot( killId, weapon, meansOfDeath )
{
self.modifiers["longshot"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "longshot" );
self thread maps\mp\gametypes\_rank::giveRankXP( "longshot", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "longshot" );
self incPlayerStat( "longshots", 1 );
self thread maps\mp\_matchdata::logKillEvent( killId, "longshot" );
}
pointblank( killId, weapon, meansOfDeath )
{
self.modifiers["pointblank"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "pointblank" );
self thread maps\mp\gametypes\_rank::giveRankXP( "pointblank", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "pointblank" );
// self incPlayerStat( "pointblank", 1 );
self thread maps\mp\_matchdata::logKillEvent( killId, "pointblank" );
}
execution( killId, weapon, meansOfDeath )
{
self.modifiers["execution"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "execution" );
self thread maps\mp\gametypes\_rank::giveRankXP( "execution", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "execution" );
self thread maps\mp\_matchdata::logKillEvent( killId, "execution" );
}
headShot( killId, weapon, meansOfDeath )
{
self.modifiers["headshot"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "headshot" );
self thread maps\mp\gametypes\_rank::giveRankXP( "headshot", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "headshot" );
self thread maps\mp\_matchdata::logKillEvent( killId, "headshot" );
}
avengedPlayer( killId, weapon, meansOfDeath )
{
self.modifiers["avenger"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "avenger" );
self thread maps\mp\gametypes\_rank::giveRankXP( "avenger", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "avenger" );
self thread maps\mp\_matchdata::logKillEvent( killId, "avenger" );
self incPlayerStat( "avengekills", 1 );
}
avengedDog( killId, weapon, meansOfDeath )
{
self thread maps\mp\gametypes\_rank::xpEventPopup( "dog_avenger" );
self thread maps\mp\gametypes\_rank::giveRankXP( "dog_avenger", undefined, weapon, meansOfDeath );
}
assistedSuicide( killId, weapon, meansOfDeath )
{
self.modifiers["assistedsuicide"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "assistedsuicide" );
self thread maps\mp\gametypes\_rank::giveRankXP( "assistedsuicide", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "assistedsuicide" );
self thread maps\mp\_matchdata::logKillEvent( killId, "assistedsuicide" );
}
defendedPlayer( killId, weapon, meansOfDeath )
{
self.modifiers["defender"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "defender" );
self thread maps\mp\gametypes\_rank::giveRankXP( "defender", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "defender" );
self thread maps\mp\_matchdata::logKillEvent( killId, "defender" );
self incPlayerStat( "rescues", 1 );
}
postDeathKill( killId )
{
self.modifiers[ "posthumous" ] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "posthumous" );
self thread maps\mp\gametypes\_rank::giveRankXP( "posthumous" );
self thread maps\mp\_matchdata::logKillEvent( killId, "posthumous" );
}
postDeathDogKill()
{
self thread maps\mp\gametypes\_rank::xpEventPopup( "martyrdog" );
self thread maps\mp\gametypes\_rank::giveRankXP( "martyrdog" );
}
backStab( killId )
{
self iPrintLnBold( "backstab" );
}
revenge( killId )
{
self.modifiers["revenge"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "revenge" );
self thread maps\mp\gametypes\_rank::giveRankXP( "revenge" );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "revenge" );
self thread maps\mp\_matchdata::logKillEvent( killId, "revenge" );
self incPlayerStat( "revengekills", 1 );
}
multiKill( killId, killCount )
{
assert( killCount > 1 );
if ( killCount == 2 )
{
self thread maps\mp\gametypes\_rank::xpEventPopup( "double" );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "double" );
}
else if ( killCount == 3 )
{
self thread maps\mp\gametypes\_rank::xpEventPopup( "triple" );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "triple" );
thread teamPlayerCardSplash( "callout_3xkill", self );
}
else
{
self thread maps\mp\gametypes\_rank::xpEventPopup( "multi" );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "multi" );
thread teamPlayerCardSplash( "callout_3xpluskill", self );
}
self thread maps\mp\_matchdata::logMultiKill( killId, killCount );
// update player multikill record
self setPlayerStatIfGreater( "multikill", killCount );
// update player multikill count
self incPlayerStat( "mostmultikills", 1 );
}
firstBlood( killId, weapon, meansOfDeath )
{
self.modifiers["firstblood"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "firstblood" );
self thread maps\mp\gametypes\_rank::giveRankXP( "firstblood", undefined, weapon, meansOfDeath );
self thread maps\mp\_matchdata::logKillEvent( killId, "firstblood" );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "firstBlood" );
thread teamPlayerCardSplash( "callout_firstblood", self );
self maps\mp\gametypes\_missions::processChallenge( "ch_bornready" );
}
winningShot( killId )
{
}
buzzKill( killId, victim, weapon, meansOfDeath )
{
self.modifiers["buzzkill"] = victim.pers["cur_kill_streak"];
self thread maps\mp\gametypes\_rank::xpEventPopup( "buzzkill" );
self thread maps\mp\gametypes\_rank::giveRankXP( "buzzkill", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "buzzkill" );
self thread maps\mp\_matchdata::logKillEvent( killId, "buzzkill" );
}
comeBack( killId, weapon, meansOfDeath )
{
self.modifiers["comeback"] = true;
self thread maps\mp\gametypes\_rank::xpEventPopup( "comeback" );
self thread maps\mp\gametypes\_rank::giveRankXP( "comeback", undefined, weapon, meansOfDeath );
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "comeback" );
self thread maps\mp\_matchdata::logKillEvent( killId, "comeback" );
self incPlayerStat( "comebacks", 1 );
}
disconnected()
{
myGuid = self.guid;
for ( entry = 0; entry < level.players.size; entry++ )
{
if ( isDefined( level.players[entry].killedPlayers[myGuid] ) )
level.players[entry].killedPlayers[myGuid] = undefined;
if ( isDefined( level.players[entry].killedPlayersCurrent[myGuid] ) )
level.players[entry].killedPlayersCurrent[myGuid] = undefined;
if ( isDefined( level.players[entry].killedBy[myGuid] ) )
level.players[entry].killedBy[myGuid] = undefined;
}
}
monitorHealed()
{
level endon( "end_game" );
self endon( "disconnect" );
for (;;)
{
self waittill( "healed");
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "healed" );
}
}
updateRecentKills( killId )
{
self endon ( "disconnect" );
level endon ( "game_ended" );
self notify ( "updateRecentKills" );
self endon ( "updateRecentKills" );
self.recentKillCount++;
wait ( 1.0 );
if ( self.recentKillCount > 1 )
self multiKill( killId, self.recentKillCount );
self.recentKillCount = 0;
}
monitorCrateJacking()
{
level endon( "end_game" );
self endon( "disconnect" );
for( ;; )
{
self waittill( "hijacker", crateType, owner );
self thread maps\mp\gametypes\_rank::xpEventPopup( "hijacker" );
self thread maps\mp\gametypes\_rank::giveRankXP( "hijacker" );
splashName = "hijacked_airdrop";
challengeName = "ch_hijacker";
switch( crateType )
{
case "sentry":
splashName = "hijacked_sentry";
break;
case "juggernaut":
splashName = "hijacked_juggernaut";
break;
case "maniac":
splashname = "hijacked_maniac";
break;
case "juggernaut_swamp_slasher":
splashname = "hijacked_juggernaut_swamp_slasher";
break;
case "juggernaut_predator":
splashname = "hijacked_juggernaut_predator";
break;
case "juggernaut_death_mariachi":
splashname = "hijacked_juggernaut_death_mariachi";
break;
case "remote_tank":
splashName = "hijacked_remote_tank";
break;
case "mega":
case "emergency_airdrop":
splashName = "hijacked_emergency_airdrop";
challengeName = "ch_newjack";
break;
default:
break;
}
if( IsDefined( owner ) )
owner maps\mp\gametypes\_hud_message::playerCardSplashNotify( splashName, self );
self notify( "process", challengeName );
}
}
monitorObjectives()
{
level endon( "end_game" );
self endon( "disconnect" );
for (;;)
{
self waittill( "objective", objType );
switch( objType )
{
case "captured":
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "capture" );
if ( isDefined( self.lastStand ) && self.lastStand )
{
self thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "heroic", maps\mp\gametypes\_rank::getScoreInfoValue( "reviver" ) );
self thread maps\mp\gametypes\_rank::giveRankXP( "reviver" );
}
break;
case "plant":
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "plant" );
break;
case "defuse":
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "defuse" );
break;
}
}
}
// this gets called directly from the game mode gscs instead of leaning on the above notify system
giveObjectivePointStreaks()
{
halfTick_activate = true; // turn this to true in ffotd / patch to activate the objective point system
if ( halfTick_activate )
{
// DM - 5/2/14 - make sure this isn't getting applied to squadmates
if( !IsAgent( self ) )
{
self.pers["objectivePointStreak"]++;
// for every two objective points earned, give 1 killstreak tick
should_give_point = ( self.pers["objectivePointStreak"] % 2 == 0 );
if ( should_give_point )
{
self maps\mp\killstreaks\_killstreaks::giveAdrenaline( "kill" );
}
// if this results false, set a half killstreak tick in lua
// NOTE: this gets overridden in KillstreakHud.lua if the player is using specialist and is maxed to avoid showing the half tick
self SetClientOmnvar( "ui_half_tick", !should_give_point );
}
}
}

176
maps/mp/_flashgrenades.gsc Normal file
View File

@ -0,0 +1,176 @@
#include maps\mp\_utility;
main()
{
}
startMonitoringFlash()
{
self thread monitorFlash();
}
stopMonitoringFlash(disconnected)
{
self notify("stop_monitoring_flash");
}
flashRumbleLoop( duration )
{
self endon("stop_monitoring_flash");
self endon("flash_rumble_loop");
self notify("flash_rumble_loop");
goalTime = getTime() + duration * 1000;
while ( getTime() < goalTime )
{
self PlayRumbleOnEntity( "damage_heavy" );
wait( 0.05 );
}
}
monitorFlash()
{
self endon("disconnect");
self notify("monitorFlash");
self endon("monitorFlash");
self.flashEndTime = 0;
durationMultiplier = 1; // how long the flash lasts
while(1)
{
self waittill( "flashbang", origin, percent_distance, percent_angle, attacker, teamName, extraDuration );
if ( !IsAlive( self ) )
break;
if ( IsDefined( self.usingRemote ) )
continue;
// an agent killstreak should not be flashed by its owner
if( IsDefined(self.owner) && IsDefined(attacker) && (attacker == self.owner) )
continue;
if( !IsDefined( extraDuration ) )
extraDuration = 0;
hurtattacker = false;
hurtvictim = true;
// with this being the 9-bang we shouldn't consider angle as a variable because of the multiple blasts
//if ( percent_angle < 0.25 )
// percent_angle = 0.25;
//else if ( percent_angle > 0.8 )
percent_angle = 1;
duration = percent_distance * percent_angle * durationMultiplier;
duration += extraDuration;
// MW3 stun resistance perk
duration = maps\mp\perks\_perkfunctions::applyStunResistence( duration );
if ( duration < 0.25 )
continue;
rumbleduration = undefined;
if ( duration > 2 )
rumbleduration = 0.75;
else
rumbleduration = 0.25;
assert(IsDefined(self.team));
if (level.teamBased && IsDefined(attacker) && IsDefined(attacker.team) && attacker.team == self.team && attacker != self)
{
if(level.friendlyfire == 0) // no FF
{
continue;
}
else if(level.friendlyfire == 1) // FF
{
}
else if(level.friendlyfire == 2) // reflect
{
duration = duration * .5;
rumbleduration = rumbleduration * .5;
hurtvictim = false;
hurtattacker = true;
}
else if(level.friendlyfire == 3) // share
{
duration = duration * .5;
rumbleduration = rumbleduration * .5;
hurtattacker = true;
}
}
else if( IsDefined(attacker) )
{
attacker notify( "flash_hit" );
if( attacker != self )
attacker maps\mp\gametypes\_missions::processChallenge( "ch_indecentexposure" );
}
if ( hurtvictim && IsDefined(self) )
{
self thread applyFlash(duration, rumbleduration);
if ( IsDefined(attacker) && attacker != self )
{
attacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "flash" );
// need this here because there are instances where you can not take damage from a flashbang but still get flashed
// since you don't take damage the recon perk won't paint you when it should
// show the victim on the minimap for N seconds
victim = self;
if( IsPlayer( attacker ) && attacker IsItemUnlocked( "specialty_paint" ) && attacker _hasPerk( "specialty_paint" ) )
{
if( !victim maps\mp\perks\_perkfunctions::isPainted() )
attacker maps\mp\gametypes\_missions::processChallenge( "ch_paint_pro" );
victim thread maps\mp\perks\_perkfunctions::setPainted( attacker );
}
}
}
if ( hurtattacker && IsDefined(attacker) )
{
attacker thread applyFlash(duration, rumbleduration);
}
}
}
applyFlash(duration, rumbleduration)
{
// wait for the highest flash duration this frame,
// and apply it in the following frame
if (!IsDefined(self.flashDuration) || duration > self.flashDuration)
self.flashDuration = duration;
if (!IsDefined(self.flashRumbleDuration) || rumbleduration > self.flashRumbleDuration)
self.flashRumbleDuration = rumbleduration;
wait .05;
if (IsDefined(self.flashDuration)) {
self shellshock( "flashbang_mp", self.flashDuration ); // TODO: avoid shellshock overlap
self.flashEndTime = getTime() + (self.flashDuration * 1000);
}
if (IsDefined(self.flashRumbleDuration)) {
self thread flashRumbleLoop( self.flashRumbleDuration ); //TODO: Non-hacky rumble.
}
self.flashDuration = undefined;
self.flashRumbleDuration = undefined;
}
isFlashbanged()
{
return IsDefined( self.flashEndTime ) && gettime() < self.flashEndTime;
}

272
maps/mp/_fx.gsc Normal file
View File

@ -0,0 +1,272 @@
#include common_scripts\utility;
#include common_scripts\_fx;
#include common_scripts\_createfx;
#include maps\mp\_utility;
#include maps\mp\_createfx;
/*
****************************************************************************************************************
OneShotfx: Fires an effect once.
maps\mp\_fx::OneShotfx( effectname, (x y z), predelay);
Example:
maps\mp\_fx::OneShotfx(level.medFire, // Medium fire effect
(-701, -18361, 148), // Origin
5); // Wait 5 seconds before doing effect
****************************************************************************************************************
****************************************************************************************************************
Loopfx: Loops an effect with a waittime.
maps\mp\_fx::loopfx( effectname, (x y z), delay_between_shots);
Example:
maps\mp\_fx::loopfx(level.medFire, // Medium fire effect
(-701, -18361, 148), // Origin
0.3); // Wait 0.3 seconds between shots
****************************************************************************************************************
****************************************************************************************************************
GunFireLoopfx: Simulates bursts of fire.
maps\mp\_fx::gunfireloopfx(fxId, fxPos, shotsMin, shotsMax, shotdelayMin, shotdelayMax, betweenSetsMin, betweenSetsMax)
Example:
maps\mp\_fx::gunfireloopfx (level.medFire, // Medium fire effect
(-701, -18361, 148), // Origin
10, 15, // 10 to 15 shots
0.1, 0.3, // 0.1 to 0.3 seconds between shots
2.5, 9); // 2.5 to 9 seconds between sets of shots.
****************************************************************************************************************
****************************************************************************************************************
GrenadeExplosionfx: Creates a grenade explosion with view jitter.
maps\mp\_fx::GrenadeExplosionfx((x y z));
Example:
maps\mp\_fx::GrenadeExplosionfx( (-701, -18361, 148) ); // origin
****************************************************************************************************************
*/
script_print_fx()
{
if ( ( !isdefined( self.script_fxid ) ) || ( !isdefined( self.script_fxcommand ) ) || ( !isdefined( self.script_delay ) ) )
{
println( "Effect at origin ", self.origin, " doesn't have script_fxid/script_fxcommand/script_delay" );
self delete();
return;
}
if ( isdefined( self.target ) )
org = getent( self.target ).origin;
else
org = "undefined";
// println ("^a Command:", self.script_fxcommand, " Effect:", self.script_fxID, " Delay:", self.script_delay, " ", self.origin);
if ( self.script_fxcommand == "OneShotfx" )
println( "maps\mp\_fx::OneShotfx(\"" + self.script_fxid + "\", " + self.origin + ", " + self.script_delay + ", " + org + ");" );
if ( self.script_fxcommand == "loopfx" )
println( "maps\mp\_fx::LoopFx(\"" + self.script_fxid + "\", " + self.origin + ", " + self.script_delay + ", " + org + ");" );
if ( self.script_fxcommand == "loopsound" )
println( "maps\mp\_fx::LoopSound(\"" + self.script_fxid + "\", " + self.origin + ", " + self.script_delay + ", " + org + ");" );
}
GrenadeExplosionfx( pos )
{
playfx( level._effect[ "mechanical explosion" ], pos );
earthquake( 0.15, 0.5, pos, 250 );
// TODO: Add explosion effect and view jitter
// println("The script command grenadeExplosionEffect has been removed. maps\\mp\\_fx::GrenadeExplosionfx must be set up to make an effect and jitter the view.");
}
soundfx( fxId, fxPos, endonNotify )
{
org = spawn( "script_origin", ( 0, 0, 0 ) );
org.origin = fxPos;
org playloopsound( fxId );
if ( isdefined( endonNotify ) )
org thread soundfxDelete( endonNotify );
/*
ent = level thread createfx_showOrigin ( fxId, fxPos, undefined, undefined, "soundfx" );
ent.delay = 0;
ent endon ("effect deleted");
ent.soundfx = org;
*/
}
soundfxDelete( endonNotify )
{
level waittill( endonNotify );
self delete();
}
func_glass_handler()
{
// FuncGlassIndex [ Index ]
// FuncGlassDecals [ Glass Index ] [ Attached SINGLE Decal ]
// Funcglass.Targetname == Decal.Script_noteworthy
funcglass_indexies = [];
funcglass_decals = [];
temp_decals = GetEntArray("vfx_custom_glass","targetname");
foreach ( decal in temp_decals)
{
if (IsDefined(decal.script_noteworthy))
{
attached_glass = GetGlass(decal.script_noteworthy);
if (IsDefined (attached_glass))
{
funcglass_decals[attached_glass] = decal;
funcglass_indexies[funcglass_indexies.size] = attached_glass;
}
}
}
funcglass_alive_count = funcglass_indexies.size;
funcglass_count = funcglass_indexies.size;
// Run up to 5 times on each frame, avoid too much going on
max_iterations = 5;
current_index = 0;
while(funcglass_alive_count!=0)
{
max_index = current_index+max_iterations-1;
if (max_index > funcglass_count)
max_index = funcglass_count;
if (current_index ==funcglass_count)
current_index = 0;
for (; current_index < max_index ; current_index++ )
{
glass_index = funcglass_indexies[current_index];
decal = funcglass_decals[glass_index];
// Decal is defined, glass isn't destroyed yet (here)
if (IsDefined(decal))
{
// Glass is destroyed in the world
if (IsGlassDestroyed(glass_index))
{
decal delete();
funcglass_alive_count--;
funcglass_decals[glass_index] = undefined;
}
}
}
wait(.05);
}
}
/*rainfx( fxId, fxId2, fxPos )
{
org = spawn( "script_origin", ( 0, 0, 0 ) );
org.origin = fxPos;
org thread rainLoop( fxId, fxId2 );
//ent = level thread createfx_showOrigin( fxId, fxPos, undefined, undefined, "rainfx", undefined, fxId2 );
//ent.delay = 0;
//ent endon ("effect deleted");
//ent.soundfx = org;
}
rainLoop( hardRain, lightRain )
{
// org playloopsound (fxId);
self endon( "death" );
blend = spawn( "sound_blend", ( 0.0, 0.0, 0.0 ) );
blend.origin = self.origin;
self thread blendDelete( blend );
blend2 = spawn( "sound_blend", ( 0.0, 0.0, 0.0 ) );
blend2.origin = self.origin;
self thread blendDelete( blend2 );
// lerp of 0 will play _null only
blend setSoundBlend( lightRain + "_null", lightRain, 0 );
blend2 setSoundBlend( hardRain + "_null", hardRain, 1 );
rain = "hard";
blendTime = undefined;
for ( ;; )
{
level waittill( "rain_change", change, blendTime );
blendTime *= 20;// internal framerate
assert( change == "hard" || change == "light" || change == "none" );
assert( blendtime > 0 );
if ( change == "hard" )
{
if ( rain == "none" )
{
blendTime *= 0.5;// gotta do 2 blends to go from none to hard
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, i / blendtime );
wait( 0.05 );
}
rain = "light";
}
if ( rain == "light" )
{
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, 1 - ( i / blendtime ) );
blend2 setSoundBlend( hardRain + "_null", hardRain, i / blendtime );
wait( 0.05 );
}
}
}
if ( change == "none" )
{
if ( rain == "hard" )
{
blendTime *= 0.5;// gotta do 2 blends to go from hard to none
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, ( i / blendtime ) );
blend2 setSoundBlend( hardRain + "_null", hardRain, 1 - ( i / blendtime ) );
wait( 0.05 );
}
rain = "light";
}
if ( rain == "light" )
{
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, 1 - ( i / blendtime ) );
wait( 0.05 );
}
}
}
if ( change == "light" )
{
if ( rain == "none" )
{
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, i / blendtime );
wait( 0.05 );
}
}
if ( rain == "hard" )
{
for ( i = 0;i < blendtime;i++ )
{
blend setSoundBlend( lightRain + "_null", lightRain, i / blendtime );
blend2 setSoundBlend( hardRain + "_null", hardRain, 1 - ( i / blendtime ) );
wait( 0.05 );
}
}
}
rain = change;
}
}*/
blendDelete( blend )
{
self waittill( "death" );
blend delete();
}

50
maps/mp/_global_fx.gsc Normal file
View File

@ -0,0 +1,50 @@
#include maps\mp\_global_fx_code;
// This script automaticly plays a users specified oneshot effect on all prefabs that have the
// specified "script_struct" and "targetname" It also excepts angles from the "script_struct"
// but will set a default angle of ( 0, 0, 0 ) if none is defined.
main()
{
// targetname fxFile
global_FX( "ch_streetlight_02_FX_origin" , "fx/misc/lighthaze" );
global_FX( "me_streetlight_01_FX_origin" , "fx/misc/lighthaze_bog_a" );
global_FX( "ch_street_light_01_on" , "fx/misc/light_glow_white" );
global_FX( "lamp_post_globe_on" , "fx/misc/light_glow_white" );
global_FX( "highway_lamp_post" , "fx/misc/lighthaze_villassault" );
global_FX( "cs_cargoship_spotlight_on_FX_origin" , "fx/misc/lighthaze" );
global_FX( "com_tires_burning01_FX_origin" , "fx/fire/tire_fire_med" );
global_FX( "icbm_powerlinetower_FX_origin" , "fx/misc/power_tower_light_red_blink" );
global_FX( "icbm_mainframe_FX_origin" , "fx/props/icbm_mainframe_lightblink" );
global_FX( "lighthaze_oilrig_FX_origin" , "fx/misc/lighthaze_oilrig" );
global_FX( "lighthaze_white_FX_origin" , "fx/misc/lighthaze_white" );
global_FX( "light_glow_walllight_white_FX_origin", "fx/misc/light_glow_walllight_white" );
global_FX( "fluorescent_glow_FX_origin" , "fx/misc/fluorescent_glow" );
global_FX( "light_glow_industrial_FX_origin" , "fx/misc/light_glow_industrial" );
global_FX( "highrise_blinky_tower" , "fx/misc/power_tower_light_red_blink_large" );
global_FX( "light_glow_white_bulb_FX_origin" , "fx/misc/light_glow_white_bulb" );
global_FX( "light_glow_white_lamp_FX_origin" , "fx/misc/light_glow_white_lamp" );
global_FX( "mp_snow_light_on" , "vfx/ambient/lights/vfx_bulb_prismatic_mp_snow" );
global_FX( "vfx_fog_water_mp" , "vfx/ambient/atmospheric/vfx_fog_water_mp" );
global_FX( "vfx_mp_handflare" , "vfx/ambient/props/vfx_handflare_sov" );
global_FX( "vfx_mp_sov_ceiling_light" , "vfx/ambient/lights/vfx_glow_ceil_light_sov" );
// targetname fxFile delay
global_FX( "light_red_steady_FX_origin" , "fx/misc/tower_light_red_steady" , -2 );
global_FX( "light_blue_steady_FX_origin" , "fx/misc/tower_light_blue_steady" , -2 );
global_FX( "light_orange_steady_FX_origin" , "fx/misc/tower_light_orange_steady" , -2 );
global_FX( "glow_stick_pile_FX_origin" , "fx/misc/glow_stick_glow_pile" , -2 );
global_FX( "glow_stick_orange_pile_FX_origin", "fx/misc/glow_stick_glow_pile_orange" , -2 );
global_FX( "light_pulse_red_FX_origin" , "fx/misc/light_glow_red_generic_pulse" , -2 );
global_FX( "light_pulse_red_FX_origin" , "fx/misc/light_glow_red_generic_pulse" , -2 );
global_FX( "light_pulse_orange_FX_origin" , "fx/misc/light_glow_orange_generic_pulse", -2 );
global_FX( "light_red_blink_FX_origin" , "fx/misc/power_tower_light_red_blink" , -2 );
// targetname fxFile delay fxName soundalias
global_FX( "flare_ambient_FX_origin" , "fx/misc/flare_ambient" , undefined, undefined, "emt_road_flare_burn" );
global_FX( "me_dumpster_fire_FX_origin", "fx/fire/firelp_med_pm" , undefined, undefined, "fire_dumpster_medium" );
global_FX( "barrel_fireFX_origin" , "fx/fire/firelp_barrel_pm", undefined, undefined, "fire_barrel_temp" );
}

Some files were not shown because too many files have changed in this diff Show More