iw6-scripts-dev/maps/mp/mp_fahrenheit.gsc
2024-12-11 11:28:08 +01:00

759 lines
19 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
SIDE_LEFT = 1;
SIDE_RIGHT = 2;
SIDE_NONE = 3;
main()
{
maps\mp\mp_fahrenheit_precache::main();
maps\createart\mp_fahrenheit_art::main();
maps\mp\mp_fahrenheit_fx::main();
// maps\mp\_water::waterShallowFx();
precache();
maps\mp\_load::main();
flag_init( "stop_dynamic_events" );
level.rainScriptables = [];
level.rainScriptables = GetScriptableArray( "rain_scriptable", "targetname" );
level.round_start_fraction = 0;
level.round_end_fraction = 1;
level.storm_stage = 0; // 0 is clear. 1 is light rain fx. 2 is heavy rain fx and audio
level.stage_1_fraction = 0.4;
level.stage_2_fraction= 0.7;
round_time = getTimeLimit() * 60;
if ( round_time <= 0 )
{
round_time = 600; // 10 minutes
}
level.assumed_match_length = round_time;
maps\mp\_compass::setupMiniMap( "compass_map_mp_fahrenheit" );
setdvar("r_reactiveMotionWindAmplitudeScale", .5);
setdvar("r_reactiveMotionWindFrequencyScale", .5);
if( ( level.ps3 ) || ( level.xenon ) )
{
setdvar( "sm_sunShadowScale", "0.8" ); // optimization
}
setdvar_cg_ng( "r_specularColorScale", 3, 9 );
setdvar_cg_ng( "r_diffuseColorScale", 1.6, 2.2 );
setdvar( "r_ssaorejectdepth", 1500);
setdvar( "r_ssaofadedepth", 1200);
setdvar( "r_sky_fog_intensity","1" );
setdvar( "r_sky_fog_min_angle","56.6766" );
setdvar( "r_sky_fog_max_angle","75" );
setdvar( "r_lightGridEnableTweaks", 1 );
setdvar( "r_lightGridIntensity", 1.33 );
game[ "attackers" ] = "allies";
game[ "defenders" ] = "axis";
flag_init( "begin_storm" );
// maps\mp\_water::waterShallowInit();
level thread plant_anims();
// level thread visiontest();
waitframe();
if( isRoundBased() )
{
compute_round_based_percentages( round_time ); // sets level.round_start_fraction, level.round_end_fraction, level.assumed_match_length
}
level thread sky_and_visionsets( level.assumed_match_length, level.round_start_fraction, level.round_end_fraction );
level thread connect_watch();
// level thread fx_test();
/#
level thread exploder_test();
#/
// elevator test
thread setupElevator();
level thread initExtraCollision();
}
initExtraCollision()
{
collision1 = GetEnt( "clip128x128x8", "targetname" );
collision1Ent = spawn( "script_model", (-2352, -1938, 512) );
collision1Ent.angles = ( 0, 0, 0);
collision1Ent CloneBrushmodelToScriptmodel( collision1 );
collision2 = GetEnt( "clip32x32x256", "targetname" );
collision2Ent = spawn( "script_model", (176, -2420, 848) );
collision2Ent.angles = ( 0, 0, 0);
collision2Ent CloneBrushmodelToScriptmodel( collision2 );
collision3 = GetEnt( "clip32x32x256", "targetname" );
collision3Ent = spawn( "script_model", (176, -2452, 848) );
collision3Ent.angles = ( 0, 0, 0);
collision3Ent CloneBrushmodelToScriptmodel( collision3 );
collision4 = GetEnt( "clip32x32x256", "targetname" );
collision4Ent = spawn( "script_model", (666, -1824, 868) );
collision4Ent.angles = ( 0, 0, 0);
collision4Ent CloneBrushmodelToScriptmodel( collision4 );
//11/8/13
collision5 = GetEnt( "clip256x256x8", "targetname" );
collision5Ent = spawn( "script_model", (-1372, -3232, 784) );
collision5Ent.angles = ( 0, 0, 0);
collision5Ent CloneBrushmodelToScriptmodel( collision5 );
//11/13/13
collision6 = GetEnt( "clip64x64x256", "targetname" );
collision6Ent = spawn( "script_model", (-1928, 624, 680) );
collision6Ent.angles = ( 0, 0, -90 );
collision6Ent CloneBrushmodelToScriptmodel( collision6 );
//11/13/13
collision7 = GetEnt( "clip256x256x8", "targetname" );
collision7Ent = spawn( "script_model", (-1808, 760, 648) );
collision7Ent.angles = ( 0, 0, 0 );
collision7Ent CloneBrushmodelToScriptmodel( collision7 );
//gryphon kill trigger
gryphonTrig1Ent = spawn( "trigger_radius", (-1216, 80, 496), 0, 864, 110 );
gryphonTrig1Ent.radius = 864;
gryphonTrig1Ent.height = 110;
gryphonTrig1Ent.angles = (0,0,0);
gryphonTrig1Ent.targetname = "gryphonDeath";
//gryphon kill trigger2
gryphonTrig2Ent = spawn( "trigger_radius", (576, -3104, 312), 0, 2240, 75 );
gryphonTrig2Ent.radius = 2240;
gryphonTrig2Ent.height = 75;
gryphonTrig2Ent.angles = (0,0,0);
gryphonTrig2Ent.targetname = "gryphonDeath";
//gryphon kill trigger 3
gryphonTrig3Ent = spawn( "trigger_radius", (-1080, -4136, 520), 0, 176, 528 );
gryphonTrig3Ent.radius = 176;
gryphonTrig3Ent.height = 528;
gryphonTrig3Ent.angles = (0,0,0);
gryphonTrig3Ent.targetname = "gryphonDeath";
//gryphon kill trigger 4
gryphonTrig4Ent = spawn( "trigger_radius", (-1184, -3808, 416), 0, 176, 96 );
gryphonTrig4Ent.radius = 176;
gryphonTrig4Ent.height = 96;
gryphonTrig4Ent.angles = (0,0,0);
gryphonTrig4Ent.targetname = "gryphonDeath";
//anti foliage trigger
antiFoliageEnt = spawn( "trigger_radius", (448, -2144, 896), 0, 400, 128 );
antiFoliageEnt.radius = 400;
antiFoliageEnt.height = 128;
antiFoliageEnt.angles = (0,0,0);
antiFoliageEnt.targetname = "antiFoliage";
level thread watchAntiFoliage( antiFoliageEnt );
//player kill trigger
level thread killTrigger( (-194, 198, 352), 700, 256 );
level thread killTrigger( (-2148, -340, 718), 96, 6 );
}
watchAntiFoliage( trigger )
{
level endon( "game_ended" );
for( ;; )
{
foreach ( player in level.players )
{
wait( 0.05 );
if( !isDefined( player ) )
continue;
if( player IsTouching( trigger ) )
{
if ( isDefined( player.wasInAntiFoliage ) && player.wasInAntiFoliage )
continue;
player SetIgnoreFoliageSightingMe( 1 );
player.wasInAntiFoliage = true;
}
else if( isDefined( player.wasInAntiFoliage ) && player.wasInAntiFoliage )
{
player SetIgnoreFoliageSightingMe( 0 );
player.wasInAntiFoliage = false;
}
}
wait( .1 );
}
}
precache()
{
}
setupElevator()
{
if( level.gametype == "horde" )
return;
elevatorCfg = SpawnStruct();
elevatorCfg.name = "elevator";
elevatorCfg.doors = [];
elevatorCfg.doors[ "floor1" ] = [ "e_door_floor1_", "e_door_elevator_1_" ];
elevatorCfg.doors[ "floor2" ] = [ "e_door_floor2_", "e_door_elevator_2_" ];
// need to know which doors move with the elevator, but this does create a little extra data
elevatorCfg.doors[ "elevator" ] = [ "e_door_elevator_1_", "e_door_elevator_2_" ];
elevatorCfg.doorMoveDist = 35;
elevatorCfg.buttons = "elevator_button";
elevatorCfg.trigBlockName = "elevator_door_checker";
maps\mp\_elevator::init_elevator( elevatorCfg );
}
compute_round_based_percentages( round_time )
{
// In a gametype with a winlimit, we'll set the weather based on the leading team's score as a percentage of the winlimit
// If the gametype doesn't have a winlimit, but has a roundlimit, we'll simply set the weather based on the percentage the current round is of the roundlimit.
// If the game has neither, we'll just use timeLimit.
round_limit = getWatchedDvar( "roundlimit" );
win_limit = getWatchedDvar( "winlimit" );
if( win_limit > 0 )
{
level.assumed_match_length = win_limit * round_time;
if( isFirstRound() )
{
winning_team_round = 0;
}
else
{
winning_team_round = max( game[ "roundsWon" ][ "allies" ], game[ "roundsWon" ][ "axis" ] );
}
level.round_start_fraction = ( winning_team_round / win_limit );
level.round_end_fraction = ( winning_team_round + 1 ) / win_limit;
}
else if( round_limit > 0 )
{
level.assumed_match_length = round_limit * round_time;
level.round_start_fraction = game[ "roundsPlayed" ] / round_limit;
level.round_end_fraction = ( game[ "roundsPlayed" ] + 1 ) / round_limit;
}
}
/#
exploder_test()
{
while(1)
{
SetDevDvar("test_exploder", "-1");
while(GetDvarInt("test_exploder")<0)
{
wait .05;
}
exploder(GetDvarInt("test_exploder"));
}
}
#/
plant_anims()
{
level.plants = GetScriptableArray("storm_plant", "targetname");
level waittill("storm_stage_1");
plant_set_stage_directional("stage_1", 180, 6, 1);
}
plant_set_stage_directional(stage, angle, time, rand)
{
forward = AnglesToForward((0,angle,0));
right = AnglesToRight((0,angle,0));
min_dist = undefined;
max_dist = undefined;
foreach(plant in level.plants)
{
dist = DistToLine(plant.origin, (0,0,0), right);
if( LRTest(plant.origin, (0,0,0), right ) == SIDE_RIGHT )
dist *= -1;
if(!IsDefined(min_dist) || dist < min_dist )
min_dist = dist;
if(!IsDefined(max_dist) || dist > max_dist)
max_dist = dist;
plant.temp_dist = dist;
}
foreach(plant in level.plants)
{
frac = (plant.temp_dist - min_dist)/(max_dist - min_dist);
delay = time*frac;
if(IsDefined(rand) && rand>0)
delay += RandomFloatRange(0,rand);
level thread plant_set_stage(plant, stage, delay);
}
}
plant_set_stage(plant, stage, delay)
{
if(IsDefined(delay) && delay>0)
wait delay;
plant SetScriptablePartState("storm_plant", stage);
}
rainFXStage( number )
{
if ( !IsDefined( number ) )
{
number = 0;
}
if ( number > 2 )
{
number = 0;
}
if ( IsDefined( level.rainscriptables ) )
{
foreach ( scriptable in level.rainscriptables )
{
scriptable SetScriptablePartState( 0, number );
}
}
}
visiontest()
{
wait( 20 );
current_stage = 0;
MAX_STAGES = 2;
sign = -1;
// level.sky = GetEnt( "sky", "targetname" );
level.skydome = GetEnt( "skydome", "targetname" );
// while ( true )
{
current_stage = current_stage + 1;
if ( current_stage >= MAX_STAGES )
{
current_stage = 0;
}
IPrintLnBold( "CHANGING VISIONSETS to:" + current_stage );
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, current_stage ) ), 3 );
}
level.skydome RotatePitch( sign * 45, 3 ); // TODO: the current skydome isn't the final size. need to readjust it to fit when it's completed.
sign = sign * -1;
rainFXStage( 1 );
wait 6;
}
}
fx_test()
{
scriptables = [];
scriptables = GetScriptableArray( "rain_scriptable", "targetname" );
while ( 1 )
{
scriptables[ 0 ] SetScriptablePartState( 0, 0 );
wait( 5 );
scriptables[ 0 ] SetScriptablePartState( 0, 1 );
wait( 5 );
scriptables[ 0 ] SetScriptablePartState( 0, 2 );
wait( 5 );
scriptables[ 0 ] SetScriptablePartState( 0, 3 );
wait( 5 );
}
}
sky_and_visionsets( match_duration, start_fraction, end_fraction )
{
level.volmods = [];
if(flag("stop_dynamic_events"))
return;
level endon("stop_dynamic_events");
/#
// Was only used in development so lighters could test the different weather states - no longer enabled
//level thread watch_storm_dvar();
#/
clear_stage = 0;
transition_time = 10;
gameFlagWait( "prematch_done" );
level.storm_stage = 0;
current_fraction = start_fraction;
if( start_fraction < level.stage_1_fraction )
{
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), 0.1 );
}
remaining_time = ( level.stage_1_fraction * match_duration ) - ( current_fraction * match_duration );
wait( remaining_time );
current_fraction = level.stage_1_fraction;
}
if( start_fraction < level.stage_2_fraction )
{
level notify("storm_stage_1");
level.storm_stage = 1;
exploder (1);
level thread storm_sound_stage("storm_sound_stage_1");
level.rainEmitEnt = Spawn( "script_origin", (0,0,0) );
storm_sounds_volMod("scripted2", 0 , 0);
wait (0.05);
level.rainEmitEnt playLoopSound( "amb_fah_rain_light_loop" );
storm_sounds_volMod("scripted2", 1 , 3);
sun_scriptables = GetScriptableArray("sun_scriptable","targetname");
foreach(sun in sun_scriptables)
{
sun SetScriptablePartState(0, "storm_stage_1");
}
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), transition_time );
}
wait( transition_time );
rainFXStage( level.storm_stage );
remaining_time = ( level.stage_2_fraction * match_duration ) - ( ( current_fraction * match_duration ) + transition_time );
wait( remaining_time );
current_fraction = level.stage_2_fraction;
}
level notify("storm_stage_2");
level.storm_stage = 2;
exploder (1);
level thread storm_sound_stage("storm_sound_stage_2");
level.heavyRainEmitEnt = Spawn( "script_origin", (0,0,0) );
storm_sounds_volMod("scripted3", 0 , 0);
wait (0.05);
level.heavyRainEmitEnt playLoopSound( "amb_fah_rain_heavy_loop" );
storm_sounds_volMod("scripted3", 1, 3);
wait (0.05);
storm_sounds_volMod("scripted2", 0 , 3);
rainFXStage( level.storm_stage );
if( start_fraction >= level.stage_2_fraction )
{
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), 0.1 );
}
}
else
{
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), transition_time );
}
}
}
storm_sound_stage(origin_targetname)
{
time_between_sounds = .9;
sound_origins = GetEntArray(origin_targetname, "targetname");
foreach(org in sound_origins)
{
sound_name = org.script_noteworthy;
if(isDefined(sound_name))
{
org PlayLoopSound(sound_name);
}
else
{
AssertMsg("Storm Sound @"+ org.origin+" missing script_noteworthy sound name.");
}
wait time_between_sounds;
}
}
storm_sounds_volMod(volmod, value, time)
{
level.volmods[volmod] = value;
foreach(player in level.players)
{
player SetVolMod(volmod, value, time);
}
}
/#
watch_storm_dvar()
{
dvar_name = "storm_stage";
default_stage = 0;
SetDevDvarIfUninitialized( dvar_name, default_stage );
while( 1 )
{
value = GetDvarInt( dvar_name, default_stage );
if( value == level.storm_stage )
{
waitframe();
}
else
{
if( ( value > 2 ) || (value < 0 ) )
{
println( "Invalid storm stage. Valid values are 0, 1, 2." );
}
else
{
SetDvar( dvar_name, value );
level.storm_stage = value;
rainFXStage( level.storm_stage );
foreach ( player in level.players )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), 0.1 );
}
level notify( "stop_dynamic_events" ); // if you're messing with the storm value, we stop the game's natural progression
}
waitframe();
}
}
}
#/
rotate_skydome( start_fraction, end_fraction, rotation_time )
{
min_angle = 0;
max_angle = -70;
start_fraction = min( 1, start_fraction / level.stage_1_fraction );
end_fraction = min( 1, end_fraction / level.stage_1_fraction );
level.skydome RotatePitch( 180, 0.1 );
wait( 0.1 );
level.skydome RotatePitch( start_fraction * max_angle, 0.1 );
gameFlagWait( "prematch_done" );
level.skydome RotatePitch( ( end_fraction - start_fraction ) * max_angle, max( 0.1, ( end_fraction - start_fraction ) * rotation_time ) );
}
connect_watch()
{
while ( 1 )
{
level waittill( "connected", player );
if ( IsDefined( level.storm_stage ) )
{
player VisionSetStage( Int( min( 1, level.storm_stage ) ), 0.1 );
}
foreach(volmod,value in level.volmods)
{
player SetVolMod(volmod, value);
}
}
}
////////////////////////////////////////////////////////////////////////////////////
// Area Of The Parallel Pipid (2D)
//
// Given two more points, this function calculates the area of the parallel pipid
// formed.
//
// Note: This function CAN return a negative "area" if (C) is above or right of
// (A) and (B)... We do not take the abs because the sign of the "area" is needed
// for the left right test (see below)
//
//
// ___---( ... )
// (A)---/ /
// / /
// / /
// / /
// / ___---(B)
// (C)---/
//
////////////////////////////////////////////////////////////////////////////////////
AreaParallelPipid(A, B, C)
{
return ((A[0]*B[1] - A[1]*B[0]) +
(B[0]*C[1] - C[0]*B[1]) +
(C[0]*A[1] - A[0]*C[1]));
}
////////////////////////////////////////////////////////////////////////////////////
// Area Of The Triangle (2D)
//
// Given two more points, this function calculates the area of the triangle formed.
//
// (A)
// / \__
// / \__
// / \_
// / ___---(B)
// (C)----/
//
////////////////////////////////////////////////////////////////////////////////////
AreaTriange(A, B, C)
{
return (AreaParallelPipid(A, B, C) * 0.5);
}
////////////////////////////////////////////////////////////////////////////////////
// The Left Right Test (2D)
//
// Given a line segment (Start->End) and a tolerance for *right on*, this function
// evaluates which side the point is of the line. (Side_Left in this example)
//
//
//
// (Test) ___---/(End)
// ___---/
// ___---/
// (Start)/
//
////////////////////////////////////////////////////////////////////////////////////
LRTest(Test, Start, End, Tolerance)
{
if(!IsDefined(Tolerance))
Tolerance = 0.0;
Area = AreaParallelPipid(Start, End, Test);
if (Area>Tolerance)
{
return SIDE_LEFT;
}
if (Area<(Tolerance*-1))
{
return SIDE_RIGHT;
}
return SIDE_NONE;
}
////////////////////////////////////////////////////////////////////////////////////
// Project
//
// Standard projection function. Take (V) and project it onto the vector
// (U). Imagine drawing a line perpendicular to U from the endpoint of the (V)
// Vector. That then becomes the new vector.
//
// The values returned are the [NewVector, Scale]. The scale of the new vector with respect to
// the one passed to the function. If the scale is less than (1.0) then the new vector is
// shorter than (U). If the scale is negative, then the vector is going in the opposite
// direction of (U).
//
// _ (U)
// /|
// / _ (New)
// / RESULTS-> /|
// / /
// / __\ (V) /
// /___--- / /
//
////////////////////////////////////////////////////////////////////////////////////
Project(V, U)
{
Scale = (VectorDot(V,U) / LengthSquared(U));
return [U*Scale, Scale];
}
////////////////////////////////////////////////////////////////////////////////////
// Project To Line
//
// This function takes two other points in space as the start and end of a line
// segment and projects the (this) point onto the line defined by (Start)->(Stop)
//
// RETURN VALUES:
// (-INF, 0.0) : (this) landed on the line before (Start)
// (0.0, 1.0) : (this) landed in the line segment between (Start) and (Stop)
// (1.0, INF) : (this) landed on the line beyond (End)
//
// (Stop)
// /
// /
// o _
// / |\
// / (Point)
// /
// (Start)
//
////////////////////////////////////////////////////////////////////////////////////
ProjectToLine(Point, Start, Stop)
{
Point -= Start;
[Point, Scale] = Project(Point, Stop - Start);
Point += Start;
return [Point, Scale];
}
////////////////////////////////////////////////////////////////////////////////////
// Project To Line Seg
//
// Same As Project To Line, Except It Will Clamp To Start And Stop
////////////////////////////////////////////////////////////////////////////////////
ProjectToLineSeg(Point, Start, Stop)
{
[Point, Scale] = ProjectToLine(Point, Start, Stop);
if (Scale<0.0)
{
Point = Start;
}
else if (Scale>1.0)
{
Point = Stop;
}
return [Point, Scale];
}
////////////////////////////////////////////////////////////////////////////////////
// Distance To Line
//
// Uses project to line and than calculates distance to the new point
////////////////////////////////////////////////////////////////////////////////////
DistToLine(Point, Start, Stop)
{
[PointOnLine, Scale] = ProjectToLine(Point, Start, Stop);
return Distance(PointOnLine, Point);
}