#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); }