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

646 lines
18 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
main()
{
maps\mp\mp_sovereign_precache::main();
maps\createart\mp_sovereign_art::main();
maps\mp\mp_sovereign_fx::main();
level thread walkway_collapse(); //Before load::main so it can be seen in createfx
level thread maps\mp\mp_sovereign_events::assembly_line_precache();
level thread maps\mp\_movable_cover::init();
level.mapCustomCrateFunc = ::sovereignCustomCrateFunc;
level.mapCustomKillstreakFunc = ::sovereignCustomKillstreakFunc;
level.mapCustomBotKillstreakFunc = ::sovereignCustomBotKillstreakFunc;
maps\mp\_load::main();
thread maps\mp\_fx::func_glass_handler(); // Text on glass
maps\mp\_compass::setupMiniMap( "compass_map_mp_sovereign" );
if( ( level.ps3 ) || ( level.xenon ) )
{
setdvar( "sm_sunShadowScale", "0.5" ); // optimization
}
setdvar( "r_lightGridEnableTweaks", 1 );
setdvar( "r_lightGridIntensity", 1.33 );
SetDvar("r_sky_fog_intensity","1");
SetDvar("r_sky_fog_min_angle","60");
SetDvar("r_sky_fog_max_angle","85");
SetDvar( "r_ssaofadedepth", 1200 );
setdvar_cg_ng( "r_specularColorScale", 3.5, 5 );
setdvar_cg_ng( "r_diffuseColorScale", 1.5, 1.2 );
game["attackers"] = "allies";
game["defenders"] = "axis";
level thread maps\mp\mp_sovereign_events::assembly_line();
level thread maps\mp\mp_sovereign_events::halon_system();
level thread robot_arm();
level thread malfunctioning_crane();
level thread update_bot_maxsightdistsqrd();
}
update_bot_maxsightdistsqrd()
{
halon_maxsightdists = 1200;
halon_maxsightdistssqrd = halon_maxsightdists*halon_maxsightdists;
while(!IsDefined(level.participants))
waitframe();
while(1)
{
players_in_fog = [];
foreach(participant in level.participants)
{
if(!IsPlayer(participant))
continue;
in_fog = level.halon_fog_on && (participant GetEye())[2]<280;
if(in_fog)
{
players_in_fog[players_in_fog.size] = participant;
}
if(isBot(participant))
{
if(!IsDefined(participant.default_maxsightdistsqrd))
participant.default_maxsightdistsqrd = participant.maxsightdistsqrd;
if(in_fog)
{
participant.maxsightdistsqrd = halon_maxsightdistssqrd;
}
else
{
participant.maxsightdistsqrd = participant.default_maxsightdistsqrd;
}
}
}
if(players_in_fog.size)
{
//Screen fx exploder
exploder(39, players_in_fog);
}
wait .5;
}
}
is_dynamic_path()
{
return IsDefined(self.spawnflags) && self.spawnflags&1;
}
is_ai_sight_line()
{
return IsDefined(self.spawnflags) && self.spawnflags&2;
}
#using_animtree("animated_props");
walkway_collapse()
{
flag_init("walkway_collasped");
if ( getdvar( "r_reflectionProbeGenerate" ) == "1" )
return;
PrecacheMpAnim("mp_sovereign_walkway_collapse_top");
PrecacheMpAnim("mp_sovereign_walkway_collapse_bottom");
PrecacheMpAnim("mp_sovereign_walkway_collapse_top_idle");
PrecacheMpAnim("mp_sovereign_walkway_collapse_bottom_idle");
waitframe(); //Allow structs to be init
collapse_top_length = GetAnimLength( %mp_sovereign_walkway_collapse_top );
collapse_bottom_length = GetAnimLength( %mp_sovereign_walkway_collapse_bottom );
swap_time = GetNotetrackTimes( %mp_sovereign_walkway_collapse_top, "bottom_anim_begin")[0];
swap_time *= collapse_top_length;
walkway_trigger_damage = GetEnt("walkway_trigger_damage", "targetname");
animated_walkway_tank = GetEnt("walkway_tank_animated", "targetname");
animated_walkway_tank ScriptModelPlayAnimDeltaMotion("mp_sovereign_walkway_collapse_top_idle");
if(IsDefined(animated_walkway_tank.target))
{
animated_walkway_tank.clip = GetEnt(animated_walkway_tank.target, "targetname");
if(IsDefined(animated_walkway_tank.clip))
{
animated_walkway_tank.clip LinkTo(animated_walkway_tank, "j_canister_main");
killcam_ent = spawn("script_model", (568, -722, 568));
animated_walkway_tank.clip.killCamEnt = killcam_ent;
}
}
//walkway_tank_end = GetEnt("walkway_tank_end", "targetname");
//walkway_tank_end Hide();
walkway_clip_end = GetEntArray("walkway_clip_end", "targetname");
array_thread(walkway_clip_end, ::walkway_collapse_clip_hide);
walkway_tank_trigger_hurt = GetEnt("walkway_tank_trigger_hurt", "targetname");
if(IsDefined(walkway_tank_trigger_hurt))
{
//walkway_tank_trigger_hurt EnableLinkTo();
//walkway_tank_trigger_hurt LinkTo(animated_walkway_tank, "j_canister_main");
walkway_tank_trigger_hurt Delete();
}
animated_walkway = GetEnt("walkway_animated", "targetname");
animated_walkway ScriptModelPlayAnimDeltaMotion("mp_sovereign_walkway_collapse_bottom_idle");
animated_walkway Hide();
walkway_non_destroyed = walkway_collapse_group("walkway_non_destroyed");
walkway_destroyed = walkway_collapse_group("walkway_destroyed");
walkway_destroyed walkway_collapse_hide();
walkway_tank_fx = [];
hose1_start_notetracks = GetNotetrackTimes( %mp_sovereign_walkway_collapse_top, "hose1_start");
hose2_start_notetracks = GetNotetrackTimes( %mp_sovereign_walkway_collapse_top, "hose2_start");
hose3_start_notetracks = GetNotetrackTimes( %mp_sovereign_walkway_collapse_top, "hose3_start");
if(hose1_start_notetracks.size>0)
{
hose1_start = hose1_start_notetracks[0] * collapse_top_length;
hose2_start = hose2_start_notetracks[0] * collapse_top_length;
hose3_start = hose3_start_notetracks[0] * collapse_top_length;
walkway_tank_fx[0] = ["tag_fx_canister_1", "vfx_can_afterleak", hose1_start];
walkway_tank_fx[1] = ["tag_fx_canister_2", "vfx_can_afterleak", hose2_start];
walkway_tank_fx[2] = ["tag_fx_canister_3", "vfx_can_afterleak", hose3_start];
walkway_tank_fx[3] = ["tag_fx_cables_1", "vfx_can_jet", hose1_start];
walkway_tank_fx[4] = ["tag_fx_cables_2", "vfx_can_jet", hose2_start];
walkway_tank_fx[5] = ["tag_fx_cables_3", "vfx_can_jet", hose3_start];
}
while(1)
{
activate_player = walkway_wait(walkway_trigger_damage);
flag_set("walkway_collasped");
exploder(2);
animated_walkway_tank.clip PlaySoundOnMovingEnt("scn_catwalk_break_away");
noself_delayCall(swap_time, ::playSoundAtPos, (136, -412, 360), "scn_catwalk_impact");
noself_delayCall(4.13, ::playSoundAtPos, (242, -326, 322), "scn_catwalk_steam_burst1" );
noself_delayCall(4.46, ::playSoundAtPos, (277, -283, 256), "scn_catwalk_steam_burst2");
animated_walkway_tank ScriptModelPlayAnimDeltaMotion("mp_sovereign_walkway_collapse_top");
foreach(fx_set in walkway_tank_fx)
thread walkway_play_fx(fx_set[2], animated_walkway_tank, fx_set[1], fx_set[0]);
//walkway_tank_trigger_hurt thread walkway_collapse_hurt_trigger();
level delayThread(swap_time, ::exploder, 3);
animated_walkway delayCall(swap_time, ::Show);
animated_walkway delayCall(swap_time, ::ScriptModelPlayAnimDeltaMotion, "mp_sovereign_walkway_collapse_bottom");
walkway_non_destroyed delayThread(swap_time, ::walkway_collapse_hide);
array_thread(walkway_clip_end, ::delayThread, swap_time, ::walkway_collapse_clip_show);
//walkway_tank_trigger_hurt delayThread( swap_time+collapse_bottom_length, ::walkway_collapse_hurt_trigger_stop);
walkway_destroyed delayThread(swap_time+collapse_bottom_length, ::walkway_collapse_show);
if(IsDefined(animated_walkway_tank.clip))
{
animated_walkway_tank.clip thread maps\mp\_movers::player_pushed_kill(0);
animated_walkway_tank.clip delayThread(swap_time+collapse_bottom_length, ::walkway_collapse_clip_hide );
animated_walkway_tank.clip.unresolved_collision_kill = true;
animated_walkway_tank.clip.unresolved_collision_notify_min = 1;
animated_walkway_tank.clip.owner = activate_player;
}
wait swap_time+collapse_bottom_length;
if(IsDefined(animated_walkway_tank.clip))
{
animated_walkway_tank.clip maps\mp\_movers::stop_player_pushed_kill();
animated_walkway_tank.clip.unresolved_collision_kill = false;
animated_walkway_tank.clip.unresolved_collision_notify_min = undefined;
animated_walkway_tank.clip.owner = undefined;
}
walkway_wait();
flag_clear("walkway_collasped");
animated_walkway_tank Show();
animated_walkway ScriptModelPlayAnimDeltaMotion("mp_sovereign_walkway_collapse_bottom_idle");
//walkway_tank_end Hide();
animated_walkway Hide();
array_thread(walkway_clip_end, ::walkway_collapse_clip_hide);
walkway_non_destroyed walkway_collapse_show();
walkway_destroyed walkway_collapse_hide();
if(IsDefined(animated_walkway_tank.clip))
{
animated_walkway_tank.clip walkway_collapse_clip_show();
}
wait 1; //TODO: Don't know why I need a wait here to make this anim play. and waitframe() is not enough
animated_walkway_tank ScriptModelPlayAnimDeltaMotion("mp_sovereign_walkway_collapse_top_idle");
}
}
walkway_play_fx(delay, model, fx_name, joint)
{
wait delay;
PlayFXOnTag(level._effect[ fx_name ], model, joint);
}
walkway_collapse_hurt_trigger_stop()
{
self notify("stop_walkway_collapse_hurt_trigger");
}
walkway_collapse_hurt_trigger(activate_player)
{
self endon("stop_walkway_collapse_hurt_trigger");
while(1)
{
self waittill("trigger", player);
if ( isPlayer( player ) )
{
player DoDamage( 1000, player.origin );
}
}
}
walkway_wait(trigger)
{
level thread walkway_wait_dvar();
if(IsDefined(trigger))
level thread walkway_wait_trigger(trigger);
level waittill("activate_walkway", player);
return player;
}
walkway_wait_trigger(trigger)
{
level endon("activate_walkway");
trigger waittill("trigger", attacker);
level notify("activate_walkway",attacker);
}
walkway_wait_dvar()
{
level endon("activate_walkway");
SetDevDvarIfUninitialized("trigger_walkway", "0");
while(GetDvarInt("trigger_walkway")==0)
wait .05;
SetDevDvar("trigger_walkway", "0");
level notify("activate_walkway");
}
walkway_collapse_hide()
{
if(isDefined(self.walkway_collapse_hide) && self.walkway_collapse_hide)
return;
self.walkway_collapse_hide = true;
self.origin -= (0,0,1000);
foreach(ent in self.clip)
{
ent walkway_collapse_clip_hide();
}
self DontInterpolate();
foreach(node in self.traverse_nodes)
{
DisconnectNodePair(node, node.connected_to);
}
foreach(node in self.nodes)
{
node DisconnectNode();
}
}
walkway_collapse_clip_hide()
{
if(self is_dynamic_path())
self ConnectPaths();
if(self is_ai_sight_line())
self SetAISightLineVisible(false);
self.old_contents = self SetContents(0);
self NotSolid();
self Hide();
}
walkway_collapse_show()
{
if(isDefined(self.walkway_collapse_hide) && !self.walkway_collapse_hide)
return;
self.walkway_collapse_hide = false;
self.origin += (0,0,1000);
foreach(ent in self.clip)
{
ent walkway_collapse_clip_show();
}
self DontInterpolate();
foreach(node in self.traverse_nodes)
{
ConnectNodePair(node, node.connected_to);
}
foreach(node in self.nodes)
{
node ConnectNode();
}
}
walkway_collapse_clip_show()
{
self Solid();
self SetContents(self.old_contents);
self Show();
if(self is_dynamic_path())
self DisconnectPaths();
if(self is_ai_sight_line())
self SetAISightLineVisible(true);
}
walkway_collapse_group(targetname)
{
struct = GetStruct(targetname, "targetname");
if(!IsDefined(struct))
return undefined;
parent = Spawn("script_model", struct.origin);
parent SetModel("tag_origin");
parent.clip = [];
parent.linked = [];
ents = struct get_linked_ents();
foreach(ent in ents)
{
if(ent.classname == "script_brushmodel")
{
parent.clip[parent.clip.size] = ent;
}
else
{
parent.linked[parent.linked.size] = ent;
ent LinkTo(parent);
//ent WillNeverChange();
}
}
nodes = struct getLinkNameNodes();
parent.traverse_nodes = [];
parent.nodes = [];
foreach(node in nodes)
{
if(IsDefined(node.targetname) && node.targetname == "traverse")
{
node.connected_to = GetNode(node.target, "targetname");
parent.traverse_nodes[parent.traverse_nodes.size] = node;
}
else
{
parent.nodes[parent.nodes.size] = node;
}
}
return parent;
}
#using_animtree("animated_props");
malfunctioning_crane()
{
arm = GetEnt("malfunctioning_crane_arm","targetname");
arm_clip = GetEnt("malfunctioning_crane_arm_clip","targetname");
anim_length = GetAnimLength( %mp_sovereign_malfunctioning_crane_arm );
if( !IsDefined(arm) )
return;
if(IsDefined(arm_clip))
{
arm_clip EnableLinkTo();
arm_clip LinkTo(arm, "basetwist_jnt", (0,0,0), (180,0,0));
}
sound_ent = spawn("script_model", arm.origin);
sound_ent SetModel("tag_origin");
sound_ent LinkTo(arm, "basetwist_jnt");
arm ScriptModelPlayAnimDeltaMotion("mp_sovereign_malfunctioning_crane_arm");
while(1)
{
sound_ent PlaySoundOnMovingEnt("scn_sov_yellow_crane");
wait anim_length;
}
}
robot_arm()
{
robot_arm_anim = "mp_sovereign_robot_arm_malfunction";
PrecacheMpAnim(robot_arm_anim);
waitframe(); //Allow Struct to init
//This function makes assumptions about the robot arm moving axis aligned and
//that the track moves N/S and the arm moves E/W
robot_arm = GetEnt("robot_arm", "targetname");
if(!IsDefined(robot_arm))
return;
if(IsDefined(robot_arm.target))
{
clip = GetEnt(robot_arm.target, "targetname");
clip LinkTo(robot_arm, "j_anim_001");
}
robot_arm_parent = spawn("script_model", robot_arm.origin);
robot_arm_parent SetModel("tag_origin");
robot_arm_parent.angles = robot_arm.angles;
robot_arm LinkTo(robot_arm_parent);
robot_arm.ends = [];
links = robot_arm get_links();
foreach(link in links)
{
end = getstruct(link, "script_linkname");
robot_arm.ends[robot_arm.ends.size] = end;
}
robot_arm_top = GetEnt("robot_arm_top", "targetname");
robot_arm_top LinkTo(robot_arm_parent);
robot_track = GetEnt("robot_arm_track", "targetname");
robot_track.ends = [];
links = robot_track get_links();
foreach(link in links)
{
end = getstruct(link, "script_linkname");
robot_track.ends[robot_track.ends.size] = end;
}
robot_x_min = min(robot_arm.ends[0].origin[0], robot_arm.ends[1].origin[0]);
robot_x_max = max(robot_arm.ends[0].origin[0], robot_arm.ends[1].origin[0]);
robot_y_min = min(robot_track.ends[0].origin[1], robot_track.ends[1].origin[1]);
robot_y_max = max(robot_track.ends[0].origin[1], robot_track.ends[1].origin[1]);
robot_mins = (robot_x_min, robot_y_min, 0);
robot_maxs = (robot_x_max, robot_y_max, 0);
corners = getStructArray("robot_arm_corner", "targetname");
map_x_min = min(corners[0].origin[0], corners[1].origin[0]);
map_x_max = max(corners[0].origin[0], corners[1].origin[0]);
map_y_min = min(corners[0].origin[1], corners[1].origin[1]);
map_y_max = max(corners[0].origin[1], corners[1].origin[1]);
map_mins = (map_x_min, map_y_min, 0);
map_maxs = (map_x_max, map_y_max, 0);
robot_arm PlayLoopSound("scn_sov_single_robot_arm_lp");
robot_arm ScriptModelPlayAnimDeltaMotion(robot_arm_anim);
move_speed = 80;
while(1)
{
topPlayer = maps\mp\gametypes\_gamescore::getHighestScoringPlayer();
if(IsDefined(topPlayer))
{
new_pos = robot_arm_get_scaled_position(robot_mins, robot_maxs, map_mins, map_maxs, topPlayer.origin);
new_pos_arm = (new_pos[0], new_pos[1], robot_arm.origin[2]);
new_pos_track = (robot_track.origin[0], new_pos[1], robot_track.origin[2]);
dist = Distance(robot_arm.origin, new_pos_arm);
if(dist>10)
{
new_yaw = VectorToYaw(topPlayer.origin - robot_arm.origin);
move_time = dist/move_speed;
robot_arm_parent MoveTo(new_pos_arm, move_time);
robot_arm_parent RotateTo((robot_arm.angles[0], new_yaw, robot_arm.angles[2]), move_time/2);
robot_track MoveTo(new_pos_track, move_time);
wait max(move_time, 6);
continue;
}
}
wait 3;
}
}
robot_arm_get_scaled_position(robot_mins, robot_maxs, map_mins, map_maxs, pos)
{
robot_size = robot_maxs - robot_mins;
map_size = map_maxs - map_mins;
map_size = (map_size[0], map_size[1], 1); //Avoid divide by zero
scale = (pos - map_mins)/map_size;
scale = (clamp(scale[0],0,1), clamp(scale[1],0,1),0);
return (robot_size*scale) + robot_mins;
}
SOVEREIGN_GAS_WEIGHT = 55;
sovereignCustomCrateFunc()
{
if(!IsDefined(game["player_holding_level_killstrek"]))
game["player_holding_level_killstrek"] = false;
allow_level_killstreak = level.gametype!="sotf" && level.gametype!="infect" && level.gametype!="horde";
if(!allow_level_killstreak || game["player_holding_level_killstrek"])
return;
maps\mp\killstreaks\_airdrop::addCrateType( "airdrop_assault", "sovereign_gas", SOVEREIGN_GAS_WEIGHT, maps\mp\killstreaks\_airdrop::killstreakCrateThink, maps\mp\killstreaks\_airdrop::get_friendly_crate_model(), maps\mp\killstreaks\_airdrop::get_enemy_crate_model(), &"KILLSTREAKS_HINTS_SOVEREIGN_GAS" );
level thread watch_for_sovereign_gas_crate();
}
watch_for_sovereign_gas_crate()
{
while(1)
{
level waittill("createAirDropCrate", dropCrate);
if(IsDefined(dropCrate) && IsDefined(dropCrate.crateType) && dropCrate.crateType=="sovereign_gas")
{
disable_sovereign_gas();
captured = wait_for_capture(dropCrate);
if(!captured)
{
//reEnable Soveign Gas care packages if it expires with out anyone picking it up
maps\mp\killstreaks\_airdrop::changeCrateWeight("airdrop_assault", "sovereign_gas", SOVEREIGN_GAS_WEIGHT);
}
else
{
//Once its picked up it needs to remain off.
game["player_holding_level_killstrek"] = true;
break;
}
}
}
}
//death and capture are sent on the same frame but death is processed first :(
wait_for_capture(dropCrate)
{
result = watch_for_air_drop_death(dropCrate);
return !IsDefined(result); //If !isdefined the captured notify was also sent.
}
watch_for_air_drop_death(dropCrate)
{
dropCrate endon("captured");
dropCrate waittill("death");
waittillframeend;
return true;
}
disable_sovereign_gas()
{
maps\mp\killstreaks\_airdrop::changeCrateWeight("airdrop_assault", "sovereign_gas", 0);
}
sovereignCustomKillstreakFunc()
{
AddDebugCommand("devgui_cmd \"MP/Killstreak/Level Event:5/Care Package/Sovereign Gas\" \"set scr_devgivecarepackage sovereign_gas; set scr_devgivecarepackagetype airdrop_assault\"\n");
AddDebugCommand("devgui_cmd \"MP/Killstreak/Level Event:5/Sovereign Gas\" \"set scr_givekillstreak sovereign_gas\"\n");
level.killStreakFuncs[ "sovereign_gas" ] = ::tryUseSovereignGas;
level.killstreakWeildWeapons["sovereign_gas_mp"] ="sovereign_gas";
}
sovereignCustomBotKillstreakFunc()
{
AddDebugCommand("devgui_cmd \"MP/Bots(Killstreak)/Level Events:5/Sovereign Gas\" \"set scr_testclients_givekillstreak sovereign_gas\"\n");
maps\mp\bots\_bots_ks::bot_register_killstreak_func( "sovereign_gas", maps\mp\bots\_bots_ks::bot_killstreak_simple_use, maps\mp\mp_sovereign_events::bot_clear_of_gas );
}
tryUseSovereignGas(lifeId, streakName)
{
game["player_holding_level_killstrek"] = false;
level notify("sovereign_gas_killstreak", self);
return true;
}