2023-04-13 17:30:38 +02:00

593 lines
22 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\sound_shared;
#using scripts\shared\util_shared;
#namespace tabun;
function init_shared()
{
level.tabunInitialGasShockDuration = GetDvarInt( "scr_tabunInitialGasShockDuration", "7");
level.tabunWalkInGasShockDuration = GetDvarInt( "scr_tabunWalkInGasShockDuration", "4");
level.tabunGasShockRadius = GetDvarInt( "scr_tabun_shock_radius", "185" );
level.tabunGasShockHeight = GetDvarInt( "scr_tabun_shock_height", "20" );
level.tabunGasPoisonRadius = GetDvarInt( "scr_tabun_effect_radius", "185" );
level.tabunGasPoisonHeight = GetDvarInt( "scr_tabun_shock_height", "20" );
level.tabunGasDuration = GetDvarInt( "scr_tabunGasDuration", "8" ); // in seconds, after initial shock if you enter, you will get cough, blurred vision if you stay in this length
level.poisonDuration = GetDvarInt( "scr_poisonDuration", "8" ); // in seconds you will get poison full screen effect for
level.poisonDamage = GetDvarInt( "scr_poisonDamage", "13" ); // how much damage will the poison do each tick
level.poisonDamageHardcore = GetDvarInt( "scr_poisonDamageHardcore", "5" ); // how much damage will the poison do each tick
level.fx_tabun_0 = "tabun_tiny_mp";
level.fx_tabun_1 = "tabun_small_mp";
level.fx_tabun_2 = "tabun_medium_mp";
level.fx_tabun_3 = "tabun_large_mp";
level.fx_tabun_single = "tabun_center_mp";
level.fx_tabun_radius0 = GetDvarInt( "scr_fx_tabun_radius0", 55 );
level.fx_tabun_radius1 = GetDvarInt( "scr_fx_tabun_radius1", 55 );
level.fx_tabun_radius2 = GetDvarInt( "scr_fx_tabun_radius2", 50 );
level.fx_tabun_radius3 = GetDvarInt( "scr_fx_tabun_radius3", 25 );
level.sound_tabun_start = "wpn_gas_hiss_start";
level.sound_tabun_loop = "wpn_gas_hiss_lp";
level.sound_tabun_stop = "wpn_gas_hiss_end";
level.sound_shock_tabun_start = "";
level.sound_shock_tabun_loop = "";
level.sound_shock_tabun_stop = "";
/#
level thread checkDvarUpdates();
#/
}
function checkDvarUpdates()
{
while(true)
{
level.tabunGasPoisonRadius = GetDvarInt( "scr_tabun_effect_radius", level.tabunGasPoisonRadius );
level.tabunGasPoisonHeight = GetDvarInt( "scr_tabun_shock_height", level.tabunGasPoisonHeight );
level.tabunGasShockRadius = GetDvarInt( "scr_tabun_shock_radius", level.tabunGasShockRadius );
level.tabunGasShockHeight = GetDvarInt( "scr_tabun_shock_height", level.tabunGasShockHeight );
level.tabunInitialGasShockDuration = GetDvarInt( "scr_tabunInitialGasShockDuration", level.tabunInitialGasShockDuration);
level.tabunWalkInGasShockDuration = GetDvarInt( "scr_tabunWalkInGasShockDuration", level.tabunWalkInGasShockDuration);
level.tabunGasDuration = GetDvarInt( "scr_tabunGasDuration", level.tabunGasDuration);
level.poisonDuration = GetDvarInt( "scr_poisonDuration", level.poisonDuration );
level.poisonDamage = GetDvarInt( "scr_poisonDamage", level.poisonDamage );
level.poisonDamageHardcore = GetDvarInt( "scr_poisonDamageHardcore", level.poisonDamageHardcore );
level.fx_tabun_radius0 = GetDvarInt( "scr_fx_tabun_radius0", level.fx_tabun_radius0 );
level.fx_tabun_radius1 = GetDvarInt( "scr_fx_tabun_radius1", level.fx_tabun_radius1 );
level.fx_tabun_radius2 = GetDvarInt( "scr_fx_tabun_radius2", level.fx_tabun_radius2 );
level.fx_tabun_radius3 = GetDvarInt( "scr_fx_tabun_radius3", level.fx_tabun_radius3 );
wait(1.0);
}
}
function watchTabunGrenadeDetonation( owner )
{
self endon( "trophy_destroyed" );
self waittill( "explode", position, surface );
// AE 10-27-09: if it's in water then no need to continue
if( !isdefined(level.water_duds) || level.water_duds == true)
{
if( isdefined(surface) && surface == "water" )
{
return;
}
}
//level thread sound::play_in_space( "wpn_tabun_explode", position );
if ( GetDvarInt ( "scr_enable_new_tabun", 1 ) )
generateLocations( position, owner );
else
singleLocation( position, owner );
}
function damageEffectArea ( owner, position, radius, height, killCamEnt )
{
// AE 10-27-09: rewritting this so it makes more sense and is more effecient
// this fixed a bug where if you stood on the tabun it would kill you instantly
// spawn trigger radius for the effect areas
shockEffectArea = spawn( "trigger_radius", position, 0, radius, height );
gasEffectArea = spawn( "trigger_radius", position, 0, radius, height );
/#
if( GetDvarint( "scr_draw_triggers" ) )
level thread util::drawcylinder( position, radius, height, undefined, "tabun_draw_cylinder_stop" );
#/
// dog stuff
if ( isdefined( level.dogsOnFlashDogs ) )
{
owner thread [[level.dogsOnFlashDogs]]( shockEffectArea );
owner thread [[level.dogsOnFlashDogs]]( gasEffectArea );
}
// loop variables
loopWaitTime = 0.5;
durationOfTabun = level.tabunGasDuration;
// loop for the duration of the effect
while (durationOfTabun > 0)
{
players = GetPlayers();
for (i = 0; i < players.size; i++)
{
// if this is not hardcore then don't affect teammates
if ( level.friendlyfire == 0 )
{
if ( players[i] != owner )
{
if (!isdefined (owner) || !isdefined(owner.team) )
continue;
if( level.teambased && players[i].team == owner.team )
continue;
}
}
// see if we're not in the poison area
if ((!isdefined (players[i].inPoisonArea)) || (players[i].inPoisonArea == false) )
{
// since we're not in the pioson area, now see if we're in the poison area
if (players[i] istouching(gasEffectArea) && players[i].sessionstate == "playing")
{
// check for the gas mask perk
if ( ! ( players[i] hasPerk ("specialty_proximityprotection") ) )
{
trace = bullettrace( position, players[i].origin + (0,0,12), false, players[i] );
if ( trace["fraction"] == 1 )
{
players[i].lastPoisonedBy = owner;
players[i] thread damageInPoisonArea( shockEffectArea, killcament, trace, position );
}
}
// battle chatter for gas
// players[i] thread battlechatter::incoming_special_grenade_tracking( "gas" );
}
}
}
wait (loopWaitTime);
durationOfTabun -= loopWaitTime;
}
// if the durations are different, wait for the difference
if ( level.tabunGasDuration < level.poisonDuration )
wait ( level.poisonDuration - level.tabunGasDuration );
// clean up
shockEffectArea delete();
gasEffectArea delete();
/#
if( GetDvarint( "scr_draw_triggers" ) )
level notify( "tabun_draw_cylinder_stop" );
#/
}
function damageInPoisonArea( gasEffectArea, killcament, trace, position ) // self == player in poison area
{
self endon( "disconnect" );
self endon( "death" );
self thread watch_death();
self.inPoisonArea = true;
self startPoisoning();
tabunShockSound = spawn ("script_origin",(0,0,1));
tabunShockSound thread deleteEntOnOwnerDeath( self );
tabunShockSound.origin = position;
tabunShockSound playsound( level.sound_shock_tabun_start );
tabunShockSound playLoopSound ( level.sound_shock_tabun_loop );
timer = 0;
while ( (trace["fraction"] == 1 ) && (isdefined (gasEffectArea) ) && self istouching(gasEffectArea) && self.sessionstate == "playing"&& isdefined (self.lastPoisonedBy) )
{
// NOTE: DoDamage( <health>, <source position>, <attacker>, <inflictor>, <hitloc>, <mod>, <dflags>, <weapon> )
damage = level.poisonDamage;
if( level.hardcoreMode )
{
damage = level.poisonDamageHardcore;
}
self DoDamage( damage, gasEffectArea.origin, self.lastPoisonedBy, killCamEnt, "none", "MOD_GAS", 0, GetWeapon( "tabun_gas" ) );
if ( self util::mayApplyScreenEffect() )
{
// try to do a stumble effect by having one shellshock slow and the other speed up slightly
switch( timer )
{
case 0:
self ShellShock( "tabun_gas_mp", 1.0 );
break;
case 1:
self ShellShock( "tabun_gas_nokick_mp", 1.0 );
break;
default:
break;
}
timer++;
if( timer >= 2 )
{
timer = 0;
}
self hide_hud();
}
wait(1.0);
trace = bullettrace( position, self.origin + (0,0,12), false, self );
}
tabunShockSound StopLoopSound( 0.5 );
wait( 0.5 );
thread sound::play_in_space( level.sound_shock_tabun_stop, position );
// have a little delay before we give back
wait( 0.5 );
tabunShockSound notify( "delete" );
tabunShockSound delete();
self show_hud();
self stopPoisoning();
self.inPoisonArea = false;
}
function deleteEntOnOwnerDeath( owner )
{
self endon( "delete" );
owner waittill( "death" );
self delete();
}
function watch_death() // self == player
{
// fail safe stuff for if the player dies
self waittill("death");
self show_hud();
}
function hide_hud() // self == player
{
self util::show_hud( 0 );
}
function show_hud() // self == player
{
self util::show_hud( 1 );
}
function generateLocations( position, owner )
{
oneFoot = ( 0, 0, 12 );
startPos = position + oneFoot;
/#
level.tabun_debug = GetDvarInt( "scr_tabun_debug", 0 );
if ( level.tabun_debug )
{
black = ( 0.2, 0.2, 0.2 );
debugstar(startPos, 2 * 1000, black);
}
#/
spawnAllLocs( owner, startPos );
}
function singleLocation( position, owner )
{
SpawnTimedFX( level.fx_tabun_single, position );
killCamEnt = spawn( "script_model", position + (0,0,60) );
killCamEnt util::deleteAfterTime( 15.0 );
killCamEnt.startTime = gettime();
damageEffectArea ( owner, position, level.tabunGasPoisonRadius, level.tabunGasPoisonHeight, killcament );
}
function hitPos( start, end, color )
{
trace = bullettrace( start, end, false, undefined );
/#
level.tabun_debug = GetDvarInt( "scr_tabun_debug", 0 );
if ( level.tabun_debug )
{
debugstar(trace["position"], 2 * 1000, color);
}
thread tabun_debug_line( start, trace["position"], color, true, 80 );
#/
return trace["position"];
}
function spawnAllLocs( owner, startPos )
{
defaultDistance = GetDvarInt( "scr_defaultDistanceTabun", 220 );
cos45 = .707;
negCos45 = -.707;
red = ( 0.9, 0.2, 0.2 );
blue = ( 0.2, 0.2, 0.9 );
green = ( 0.2, 0.9, 0.2 );
white = ( 0.9, 0.9, 0.9 );
north = startPos + ( defaultDistance, 0, 0 );
south = startPos - ( defaultDistance, 0, 0 );
east = startPos + ( 0, defaultDistance, 0 );
west = startPos - ( 0, defaultDistance, 0 );
nw = startPos + ( cos45 * defaultDistance, negCos45 * defaultDistance, 0 );
ne = startPos + ( cos45 * defaultDistance, cos45 * defaultDistance, 0 );
sw = startPos + ( negCos45 * defaultDistance, negCos45 * defaultDistance, 0 );
se = startPos + ( negCos45 * defaultDistance, cos45 * defaultDistance, 0 );
locations = [];
locations["color"] = [];
locations["loc"] = [];
locations["tracePos"] = [];
locations["distSqrd"] = [];
locations["fxtoplay"] = [];
locations["radius"] = [];
locations["color"][0] = red;
locations["color"][1] = red;
locations["color"][2] = blue;
locations["color"][3] = blue;
locations["color"][4] = green;
locations["color"][5] = green;
locations["color"][6] = white;
locations["color"][7] = white;
locations["point"][0] = north;
locations["point"][1] = ne;
locations["point"][2] = east;
locations["point"][3] = se;
locations["point"][4] = south;
locations["point"][5] = sw;
locations["point"][6] = west;
locations["point"][7] = nw;
for ( count = 0; count < 8; count++ )
{
trace = hitPos( startPos, locations["point"][count], locations["color"][count] );
locations["tracePos"][count] = trace;
locations["loc"][count] = startPos/2 + trace/2;
locations["loc"][count] = locations["loc"][count] - ( 0, 0, 12 );
locations["distSqrd"][count] = distancesquared( startPos, trace );
}
centroid = getCenterOfLocations( locations );
killCamEnt = spawn( "script_model", centroid + (0,0,60) );
killCamEnt util::deleteAfterTime( 15.0 );
killCamEnt.startTime = gettime();
center = getcenter( locations );
for ( i = 0; i < 8; i++ )
{
fxToPlay = setUpTabunFx( owner, locations, i);
switch ( fxToPlay )
{
case 0:
{
locations["fxtoplay"][i] = level.fx_tabun_0;
locations["radius"][i] = level.fx_tabun_radius0;
}
break;
case 1:
{
locations["fxtoplay"][i] = level.fx_tabun_1;
locations["radius"][i] = level.fx_tabun_radius1;
}
break;
case 2:
{
locations["fxtoplay"][i] = level.fx_tabun_2;
locations["radius"][i] = level.fx_tabun_radius2;
}
break;
case 3:
{
locations["fxtoplay"][i] = level.fx_tabun_3;
locations["radius"][i] = level.fx_tabun_radius3;
}
break;
default:
{
locations["fxtoplay"][i] = undefined;
locations["radius"][i] = 0;
}
}
}
singleEffect = true;
freepassUsed = false;
// check can we just play one large effect
for ( i = 0; i < 8; i++ )
{
if ( locations["radius"][i] != level.fx_tabun_radius0 )
{
if (freePassUsed == false && locations["radius"][i] == level.fx_tabun_radius1 )
{
freePassUsed = true;
}
else
{
singleEffect = false;
}
}
}
oneFoot = ( 0, 0, 12 );
startPos = startPos - oneFoot;
thread playTabunSound( startPos );
if ( singleEffect == true )
{
singleLocation( startPos, owner );
}
else
{
SpawnTimedFX( level.fx_tabun_3, startPos );
for ( count = 0; count < 8; count++ )
{
if ( isdefined ( locations["fxtoplay"][count] ) )
{
SpawnTimedFX( locations["fxtoplay"][count], locations["loc"][count] );
thread damageEffectArea ( owner, locations["loc"][count], locations["radius"][count], locations["radius"][count], killCamEnt );
}
}
}
}
function playTabunSound( position )
{
tabunSound = spawn ("script_origin",(0,0,1));
tabunSound.origin = position;
tabunSound playsound( level.sound_tabun_start );
tabunSound playLoopSound ( level.sound_tabun_loop );
wait( level.tabunGasDuration );
thread sound::play_in_space( level.sound_tabun_stop, position );
tabunSound StopLoopSound( .5);
wait(.5);
tabunSound delete();
}
function setUpTabunFx( owner, locations, count )
{
fxToPlay = undefined;
previous = count - 1;
if ( previous < 0 )
previous = previous + locations["loc"].size;
next = count + 1;
if ( next >= locations["loc"].size )
next = next - locations["loc"].size;
effect0Dist = level.fx_tabun_radius0 * level.fx_tabun_radius0;
effect1Dist = level.fx_tabun_radius1 * level.fx_tabun_radius1;
effect2Dist = level.fx_tabun_radius2 * level.fx_tabun_radius2;
effect3Dist = level.fx_tabun_radius3 * level.fx_tabun_radius3;
effect4Dist = level.fx_tabun_radius3;
fxToPlay = -1;
if ( locations["distSqrd"][count] > effect0Dist && locations["distSqrd"][previous] > effect1Dist && locations["distSqrd"][next] > effect1Dist )
{
fxToPlay = 0;
}
else if ( locations["distSqrd"][count] > effect1Dist && locations["distSqrd"][previous] > effect2Dist && locations["distSqrd"][next] > effect2Dist )
{
fxToPlay = 1;
}
else if ( locations["distSqrd"][count] > effect2Dist && locations["distSqrd"][previous] > effect3Dist && locations["distSqrd"][next] > effect3Dist )
{
fxToPlay = 2;
}
else if ( locations["distSqrd"][count] > effect3Dist && locations["distSqrd"][previous] > effect4Dist && locations["distSqrd"][next] > effect4Dist )
{
fxToPlay = 3;
}
return fxToPlay;
}
function getCenterOfLocations( locations )
{
centroid = ( 0, 0, 0 );
for ( i = 0; i < locations["loc"].size; i++ )
{
centroid = centroid + ( locations["loc"][i] / locations["loc"].size );
}
/#
level.tabun_debug = GetDvarInt( "scr_tabun_debug", 0 );
if ( level.tabun_debug )
{
purple = ( 0.9, 0.2, 0.9 );
debugstar(centroid, 2 * 1000, purple);
}
#/
return centroid;
}
function getcenter( locations )
{
center = ( 0, 0, 0 );
curX = locations["tracePos"][0][0];
curY = locations["tracePos"][0][1];
minX = curX;
maxX = curX;
minY = curY;
maxY = curY;
for ( i = 1; i < locations["tracePos"].size; i++ )
{
curX = locations["tracePos"][i][0];
curY = locations["tracePos"][i][1];
if ( curX > maxX )
maxX = curX;
else if ( curX < minX )
minX = curX;
if ( curY > maxY )
maxY = curY;
else if ( curY < minY )
minY = curY;
}
avgX = ( maxX + minX ) / 2;
avgY = ( maxY + minY ) / 2;
center = ( avgX, avgY, locations["tracePos"][0][2] );
/#
level.tabun_debug = GetDvarInt( "scr_tabun_debug", 0 );
if ( level.tabun_debug )
{
cyan = ( 0.2, 0.9, 0.9 );
debugstar(center, 2 * 1000, cyan);
}
#/
//fxToPlay = level.fx_tabun_1;
//SpawnTimedFX( fxToPlay, center );
return center;
}
/#
function tabun_debug_line( from, to, color, depthTest, time )
{
debug_rcbomb = GetDvarInt( "scr_tabun_debug", 0 );
if ( debug_rcbomb == "1" )
{
if ( !isdefined(time) )
{
time = 100;
}
if ( !isdefined(depthTest) )
{
depthTest = true;
}
Line( from, to, color, 1, depthTest, time);
}
}
#/