1665 lines
39 KiB
Plaintext
1665 lines
39 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
#include maps\mp\gametypes\_hud_util;
|
|
|
|
main()
|
|
{
|
|
maps\mp\mp_prisonbreak_precache::main();
|
|
maps\createart\mp_prisonbreak_art::main();
|
|
maps\mp\mp_prisonbreak_fx::main();
|
|
|
|
// level thread rock_slides();
|
|
level thread log_piles();
|
|
|
|
maps\mp\_load::main();
|
|
|
|
maps\mp\_compass::setupMiniMap( "compass_map_mp_prisonbreak" );
|
|
|
|
setdvar("r_reactiveMotionWindAmplitudeScale", .3);
|
|
setdvar("r_reactiveMotionWindFrequencyScale", .5);
|
|
|
|
setdvar( "r_lightGridEnableTweaks", 1 );
|
|
setdvar( "r_lightGridIntensity", 1.33 );
|
|
setdvar_cg_ng( "r_diffusecolorscale", 1.5, 1.8 );
|
|
setdvar_cg_ng( "r_specularcolorscale", 3.0, 6.0 );
|
|
SetDvar( "r_ssaofadedepth", 1089 );
|
|
SetDvar( "r_ssaorejectdepth", 1200 );
|
|
|
|
if ( level.ps3 )
|
|
{
|
|
setdvar( "sm_sunShadowScale", "0.6" ); // ps3 optimization
|
|
}
|
|
else if ( level.xenon )
|
|
{
|
|
setdvar( "sm_sunShadowScale", "0.7" );
|
|
}
|
|
|
|
if ( level.ps4 ) // Not needed on PC due to already increased shadow tile resolution (ex. "R_SHADOW_TILE_RES_LARGE_HIGH")
|
|
{
|
|
setdvar( "sm_sunSampleSizeNear", 0.33 ); // default = 0.25
|
|
}
|
|
else if ( level.xb3 )
|
|
{
|
|
setdvar( "sm_sunSampleSizeNear", 0.38 ); // default = 0.25
|
|
}
|
|
|
|
game["attackers"] = "allies";
|
|
game["defenders"] = "axis";
|
|
|
|
if ( level.gametype == "sd"
|
|
|| level.gameType == "sr" )
|
|
{
|
|
level.srKillCamOverridePosition = [];
|
|
level.srKillCamOverridePosition["_a"] = (-1158, 952, 1139);
|
|
|
|
//level thread initPrisoners();
|
|
level thread setOnBombTimerEnd();
|
|
}
|
|
|
|
// cut for now, will try with anim support later
|
|
//initInsertionVehicles();
|
|
//level thread onAttackerSpawn();
|
|
|
|
level thread tree_bridges();
|
|
level thread falling_rocks();
|
|
level thread initPatchModels();
|
|
|
|
// cut because it takes up a streaming channel
|
|
// waitframe();
|
|
// level thread tower_radio();
|
|
}
|
|
|
|
initPatchModels()
|
|
{
|
|
blackThing1 = spawn( "script_model", (-74, 120, 1038) );
|
|
blackThing1 setModel( "defaultvehicle" );
|
|
blackThing1.angles = (359.24, 258.983, -8.0374);
|
|
|
|
collision1 = GetEnt( "clip128x128x128", "targetname" );
|
|
collision1Ent = spawn( "script_model", (1112, 1859.07, 949.574) );
|
|
collision1Ent.angles = ( 0, 325, 45 );
|
|
collision1Ent CloneBrushmodelToScriptmodel( collision1 );
|
|
}
|
|
|
|
setOnBombTimerEnd()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
level.sd_onBombTimerEnd = ::onBombTimerEnd;
|
|
|
|
level waittill( "bomb_planted", destroyedObj );
|
|
|
|
if ( destroyedObj maps\mp\gametypes\_gameobjects::getLabel() == "_b" )
|
|
level.sd_onBombTimerEnd = undefined;
|
|
}
|
|
|
|
|
|
onBombTimerEnd()
|
|
{
|
|
door1 = getEnt( "prisondoor1", "targetname" );
|
|
door2 = getEnt( "prisondoor2", "targetname" );
|
|
|
|
door1 RotateYaw( -70, 0.5 );
|
|
door1 PlaySound( "scn_prison_gate_right" );
|
|
door2 RotateYaw( 70, 0.5 );
|
|
door1 PlaySound( "scn_prison_gate_left" );
|
|
|
|
wait( 1 );
|
|
level notify( "sd_free_prisoners" );
|
|
}
|
|
|
|
|
|
initPrisoners()
|
|
{
|
|
initPrisonerLoadout();
|
|
|
|
level.sd_prisonerObjective = getEnt( "sd_prisonerObjective", "targetname" );
|
|
|
|
// time needed for bot system initialization?
|
|
wait( 3 );
|
|
|
|
// override _playerlogic::Callback_PlayerConnect() call to bot think
|
|
level.bot_funcs["think"] = maps\mp\gametypes\_globallogic::blank;
|
|
|
|
spawnPoints = getEntArray( "mp_spawn", "classname" );
|
|
foreach( spawnPoint in spawnPoints )
|
|
level thread createPrisoner( spawnPoint );
|
|
}
|
|
|
|
|
|
createPrisoner( spawnPoint )
|
|
{
|
|
bot = AddTestClient();
|
|
bot.pers[ "isBot" ] = true;
|
|
bot.equipment_enabled = true;
|
|
bot.bot_team = game["attackers"];
|
|
|
|
while(!isdefined(bot.pers["team"]))
|
|
wait( 0.05 );
|
|
|
|
bot notify( "menuresponse", game["menu_team"], game["attackers"] );
|
|
wait( 0.5 );
|
|
|
|
bot.pers["gamemodeLoadout"] = level.sd_loadouts["prisoner"];
|
|
|
|
spawnPoint.playerSpawnPos = spawnPoint.origin;
|
|
spawnPoint.notTI = true;
|
|
bot.setSpawnPoint = spawnPoint;
|
|
|
|
bot notify( "menuresponse", "changeclass", "gamemode" );
|
|
|
|
bot thread holdPrisoner();
|
|
}
|
|
|
|
|
|
holdPrisoner()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "disconnect" );
|
|
|
|
self waittill( "spawned_player" );
|
|
|
|
// wait for prematch to finish
|
|
gameFlagWait( "prematch_done" );
|
|
|
|
self _disableWeapon();
|
|
anchor = spawn( "script_origin", self.origin );
|
|
self playerLinkTo( anchor );
|
|
|
|
level waittill( "sd_free_prisoners" );
|
|
|
|
self unlink();
|
|
//self _enableWeapon();
|
|
anchor delete();
|
|
|
|
while( true )
|
|
{
|
|
self BotClearScriptGoal();
|
|
self BotSetScriptGoal( level.sd_prisonerObjective.origin, 64, "critical" );
|
|
|
|
msg = self waittill_any_return( "goal", "bad_path" );
|
|
if ( msg == "goal" )
|
|
break;
|
|
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
|
|
initPrisonerLoadout()
|
|
{
|
|
// bot
|
|
level.sd_loadouts["prisoner"]["loadoutPrimary"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutPrimaryAttachment"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutPrimaryAttachment2"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutPrimaryBuff"] = "specialty_null";
|
|
level.sd_loadouts["prisoner"]["loadoutPrimaryCamo"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutPrimaryReticle"] = "none";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutSecondary"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutSecondaryAttachment"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutSecondaryAttachment2"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutSecondaryBuff"] = "specialty_null";
|
|
level.sd_loadouts["prisoner"]["loadoutSecondaryCamo"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutSecondaryReticle"] = "none";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutEquipment"] = "specialty_null";
|
|
level.sd_loadouts["prisoner"]["loadoutOffhand"] = "none";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutPerk1"] = "specialty_null";
|
|
level.sd_loadouts["prisoner"]["loadoutPerk2"] = "specialty_null";
|
|
level.sd_loadouts["prisoner"]["loadoutPerk3"] = "specialty_null";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutStreakType"] = "assault";
|
|
level.sd_loadouts["prisoner"]["loadoutKillstreak1"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutKillstreak2"] = "none";
|
|
level.sd_loadouts["prisoner"]["loadoutKillstreak3"] = "none";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutDeathstreak"] = "specialty_null";
|
|
|
|
level.sd_loadouts["prisoner"]["loadoutJuggernaut"] = false;
|
|
}
|
|
|
|
|
|
// script prototype
|
|
initInsertionVehicles()
|
|
{
|
|
level.sd_insertionVehicles = [];
|
|
starts = getEntArray( "sd_vehStart", "targetname" );
|
|
foreach ( start in starts )
|
|
{
|
|
vehicle = spawn( "script_model", start.origin );
|
|
vehicle.origin = start.origin;
|
|
vehicle.angles = start.angles;
|
|
vehicle setModel( "vehicle_hummer_open_top_noturret" );
|
|
|
|
path = [];
|
|
waypoint = getEnt( start.target, "targetname" );
|
|
while ( isDefined( waypoint ) )
|
|
{
|
|
path[path.size] = waypoint;
|
|
if ( isDefined( waypoint.target ) )
|
|
waypoint = getEnt( waypoint.target, "targetname" );
|
|
else
|
|
break;
|
|
}
|
|
|
|
level.sd_insertionVehicles[start.script_count] = spawnStruct();
|
|
level.sd_insertionVehicles[start.script_count].index = start.script_count;
|
|
level.sd_insertionVehicles[start.script_count].vehicle = vehicle;
|
|
level.sd_insertionVehicles[start.script_count].start = start;
|
|
level.sd_insertionVehicles[start.script_count].path = path;
|
|
level.sd_insertionVehicles[start.script_count].driver = false;
|
|
level.sd_insertionVehicles[start.script_count].passenger = false;
|
|
level.sd_insertionVehicles[start.script_count].arrived = false;
|
|
}
|
|
|
|
level.sd_insertionStarted = undefined;
|
|
}
|
|
|
|
|
|
onAttackerSpawn()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
while( true )
|
|
{
|
|
level waittill( "player_spawned", player );
|
|
|
|
if ( game["state"] != "postgame" && player.pers["team"] == game["attackers"] )
|
|
player thread attackerRide();
|
|
}
|
|
}
|
|
|
|
|
|
attackerRide()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
|
|
self _disableWeapon();
|
|
|
|
// first spawn triggers vehicles to start moving
|
|
if ( !isDefined( level.sd_insertionStarted ) )
|
|
{
|
|
level.sd_insertionStarted = true;
|
|
level thread startInsertionVehicles();
|
|
}
|
|
|
|
// find a seat, search front to back vehicle, driver then passenger seats
|
|
vehIndex = -1;
|
|
isDriver = false;
|
|
exitTag = "";
|
|
vehicle = undefined;
|
|
for ( i=0; i<level.sd_insertionVehicles.size; i++ )
|
|
{
|
|
vehicle = level.sd_insertionVehicles[i].vehicle;
|
|
if ( !level.sd_insertionVehicles[i].driver )
|
|
{
|
|
vehIndex = i;
|
|
isDriver = true;
|
|
level.sd_insertionVehicles[i].driver = true;
|
|
self playerLinkToDelta( vehicle, "tag_driver", 1, 30, 30, 30, 30, 1 );
|
|
self setStance( "crouch" );
|
|
|
|
if ( i==2 )
|
|
exitTag = "tag_walker3";
|
|
else
|
|
exitTag = "tag_walker0";
|
|
|
|
break;
|
|
}
|
|
else if ( !level.sd_insertionVehicles[i].passenger )
|
|
{
|
|
vehIndex = i;
|
|
level.sd_insertionVehicles[i].passenger = true;
|
|
self playerLinkToDelta( vehicle, "tag_passenger", 1, 30, 30, 30, 30, 1 );
|
|
self setStance( "crouch" );
|
|
|
|
if ( i==2 )
|
|
exitTag = "tag_walker1";
|
|
else
|
|
exitTag = "tag_walker2";
|
|
|
|
break;
|
|
}
|
|
}
|
|
if ( vehIndex < 0 )
|
|
assertMsg( "Couldn't find seat for attacker in insertion vehicles!" );
|
|
|
|
// wait for ride to end
|
|
wait( 0.05 );
|
|
while ( !level.sd_insertionVehicles[vehIndex].arrived )
|
|
wait( 0.05 );
|
|
|
|
// unlink from vehicle
|
|
self unlink();
|
|
self setStance( "stand" );
|
|
|
|
// create carrier to move player out of vehicle
|
|
carrier = spawn( "script_model", self.origin );
|
|
carrier.origin = self.origin;
|
|
carrier.angles = self.angles;
|
|
carrier setModel( "tag_player" );
|
|
self playerLinkToDelta( carrier, "tag_player", 1, 30, 30, 30, 30, 1 );
|
|
|
|
// move player to the exit tag
|
|
exitPos = vehicle getTagOrigin( exitTag );
|
|
exitAngles = vehicle getTagAngles( exitTag );
|
|
time = distance( carrier.origin, exitPos ) / 100;
|
|
carrier moveTo( exitPos, time, time/2, time/2 );
|
|
carrier rotateTo( exitAngles, time, time/2, time/2 );
|
|
|
|
wait( time );
|
|
self unlink();
|
|
carrier delete();
|
|
|
|
self _enableWeapon();
|
|
|
|
// free up the seat (late spawns and suicides before end of grace period spawn in vehicle at arrival position)
|
|
if ( isDriver )
|
|
level.sd_insertionVehicles[vehIndex].driver = false;
|
|
else
|
|
level.sd_insertionVehicles[vehIndex].passenger = false;
|
|
}
|
|
|
|
|
|
startInsertionVehicles()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
for ( i=0; i<level.sd_insertionVehicles.size; i++ )
|
|
{
|
|
level thread vehicleMove( i );
|
|
wait( 0.3 );
|
|
}
|
|
}
|
|
|
|
|
|
vehicleMove( vehicleIndex )
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
gameFlagWait( "prematch_done" );
|
|
|
|
vehicle = level.sd_insertionVehicles[vehicleIndex].vehicle;
|
|
path = level.sd_insertionVehicles[vehicleIndex].path;
|
|
|
|
for ( i=0; i<path.size; i++ )
|
|
{
|
|
time = distance( vehicle.origin, path[i].origin ) / 550;
|
|
accelTime = 0;
|
|
decelTime = 0;
|
|
if ( i == 0 )
|
|
accelTime = time/2;
|
|
else if ( i == path.size-1 )
|
|
decelTime = time/2;
|
|
|
|
vehicle moveTo( path[i].origin, time, accelTime, decelTime );
|
|
vehicle rotateTo( path[i].angles, time );
|
|
|
|
wait( time );
|
|
}
|
|
|
|
level.sd_insertionVehicles[vehicleIndex].arrived = true;
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Utility
|
|
////////////////////////////////
|
|
normalize_angles_180(angles)
|
|
{
|
|
return (angle_180(angles[0]), angle_180(angles[1]), angle_180(angles[2]));
|
|
}
|
|
|
|
angle_180(ang)
|
|
{
|
|
while(ang>180)
|
|
ang -= 360;
|
|
while(ang<-180)
|
|
ang += 360;
|
|
return ang;
|
|
}
|
|
|
|
is_explosive( cause )
|
|
{
|
|
if(!IsDefined(cause))
|
|
return false;
|
|
|
|
cause = tolower( cause );
|
|
switch( cause )
|
|
{
|
|
case "mod_grenade_splash":
|
|
case "mod_projectile_splash":
|
|
case "mod_explosive":
|
|
case "splash":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/////////////
|
|
// Common trap code - used by multiple events
|
|
/////////
|
|
trap_init(remove)
|
|
{
|
|
if( getDvar( "r_reflectionProbeGenerate" ) == "1" )
|
|
return;
|
|
|
|
if(!IsDefined(remove))
|
|
remove = false;
|
|
|
|
targets = GetEntArray(self.target, "targetname");
|
|
|
|
foreach(target in targets)
|
|
{
|
|
if(!IsDefined(target.script_noteworthy))
|
|
continue;
|
|
|
|
switch(target.script_noteworthy)
|
|
{
|
|
case "activate_trigger":
|
|
if(remove)
|
|
{
|
|
target Delete();
|
|
}
|
|
else
|
|
{
|
|
self.activate_trigger = target;
|
|
}
|
|
break;
|
|
case "use_model":
|
|
if(remove)
|
|
{
|
|
target Delete();
|
|
}
|
|
else
|
|
{
|
|
self.use_model = target;
|
|
}
|
|
break;
|
|
case "use_trigger":
|
|
if(remove)
|
|
{
|
|
target Delete();
|
|
}
|
|
else
|
|
{
|
|
self.use_trigger = target;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(IsDefined(self.activate_trigger) && IsDefined(self.use_model) && IsDefined(self.use_trigger))
|
|
{
|
|
self thread trap_use_watch();
|
|
self thread trap_delete_visuals();
|
|
}
|
|
}
|
|
|
|
trap_delete_visuals()
|
|
{
|
|
self waittill("trap_activated");
|
|
|
|
foreach(vis in self.useObject.visuals)
|
|
{
|
|
vis Delete();
|
|
}
|
|
|
|
self.useObject.visuals = [];
|
|
|
|
trap_set_can_use(false);
|
|
}
|
|
|
|
trap_use_watch()
|
|
{
|
|
wait .05;
|
|
|
|
self.useObject = maps\mp\gametypes\_gameobjects::createUseObject( "neutral", self.use_trigger, [self.use_model], (0,0,0) );
|
|
self.useObject.parent = self;
|
|
|
|
self trap_set_can_use(true);
|
|
self.useObject maps\mp\gametypes\_gameobjects::setUseTime( 2.5 );
|
|
self.useObject maps\mp\gametypes\_gameobjects::setUseText( &"MP_SETTING_TRAP" );
|
|
self.useObject maps\mp\gametypes\_gameobjects::setUseHintText( &"MP_SET_TRAP" );
|
|
self.useObject maps\mp\gametypes\_gameobjects::setVisibleTeam( "any" );
|
|
self.useObject.onUse = ::trap_onUse;
|
|
}
|
|
|
|
trap_set_can_use(canUse)
|
|
{
|
|
if(canUse)
|
|
{
|
|
if( IsDefined( self.use_icon_angles ) && IsDefined( self.use_icon_origin ) )
|
|
{
|
|
self thread hand_icon( "use", self.use_icon_origin, self.use_icon_angles, "trap_triggered" );
|
|
}
|
|
|
|
if( IsDefined( self.useObject ) && IsDefined( self.useObject.visuals ) )
|
|
{
|
|
foreach(vis in self.useObject.visuals)
|
|
{
|
|
vis Hide(); // SetModel("mil_semtex_belt_obj");
|
|
}
|
|
|
|
self.useObject maps\mp\gametypes\_gameobjects::allowUse( "any" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( IsDefined( self.useObject ) && IsDefined( self.useObject.visuals ) )
|
|
{
|
|
foreach(vis in self.useObject.visuals)
|
|
{
|
|
vis Show();
|
|
vis SetModel("mil_semtex_belt");
|
|
}
|
|
self.useObject maps\mp\gametypes\_gameobjects::allowUse( "none" );
|
|
}
|
|
}
|
|
}
|
|
|
|
trap_onUse(player)
|
|
{
|
|
self.parent trap_set_can_use(false);
|
|
self.parent notify( "trap_triggered" );
|
|
|
|
self.parent.owner = player;
|
|
self.parent thread trap_owner_watch();
|
|
self.parent thread trap_active_watch();
|
|
}
|
|
|
|
trap_owner_watch()
|
|
{
|
|
self endon("trap_activated");
|
|
|
|
self.owner waittill("death");
|
|
|
|
self trap_set_can_use(true);
|
|
}
|
|
|
|
trap_active_watch()
|
|
{
|
|
self endon("trap_activated");
|
|
self.owner endon("death");
|
|
|
|
while(1)
|
|
{
|
|
self.activate_trigger waittill("trigger", player);
|
|
|
|
if ( trap_can_player_trigger(player) )
|
|
break;
|
|
}
|
|
|
|
self notify("trap_activated");
|
|
}
|
|
|
|
trap_can_player_trigger(player)
|
|
{
|
|
if(!IsDefined(self.owner))
|
|
return false;
|
|
|
|
if(IsAgent(player) && IsDefined(player.owner) && IsDefined(self.owner) && player.owner==self.owner)
|
|
return false;
|
|
|
|
if(!level.teamBased)
|
|
{
|
|
return player != self.owner;
|
|
}
|
|
|
|
if(player.team != self.owner.team)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Tree Bridges
|
|
////////////////////////////////
|
|
tree_bridges()
|
|
{
|
|
PrecacheMpAnim("mp_prisonbreak_tree_fall");
|
|
|
|
bridges = getstructarray("tree_bridge","targetname");
|
|
array_thread(bridges, ::tree_bridge_init);
|
|
}
|
|
|
|
tree_bridge_init() // self == tree_bridge
|
|
{
|
|
self.tree = undefined;
|
|
self.clip_up = undefined;
|
|
self.clip_down = undefined;
|
|
self.clip_up_delete = undefined;
|
|
|
|
self.linked_ents = [];
|
|
targets = GetEntArray(self.target, "targetname");
|
|
structs = getstructarray(self.target, "targetname");
|
|
|
|
targets = array_combine(targets, structs);
|
|
|
|
foreach(target_ent in targets)
|
|
{
|
|
if(!IsDefined(target_ent.script_noteworthy))
|
|
continue;
|
|
|
|
switch(target_ent.script_noteworthy)
|
|
{
|
|
case "the_tree":
|
|
self.tree = target_ent;
|
|
self thread tree_bridge_damage_watch( target_ent, false );
|
|
break;
|
|
case "clip_up_delete":
|
|
self.clip_up_delete = target_ent;
|
|
break;
|
|
case "clip_up":
|
|
self.clip_up = target_ent;
|
|
self.linked_ents[self.linked_ents.size] = target_ent;
|
|
break;
|
|
case "clip_down":
|
|
self.clip_down = target_ent;
|
|
self.clip_down trigger_off();
|
|
break;
|
|
// case "support":
|
|
// self thread tree_bridge_damage_watch(target, true);
|
|
// break;
|
|
case "link":
|
|
self.linked_ents[self.linked_ents.size] = target_ent;
|
|
break;
|
|
case "delete":
|
|
self.decal = target_ent;
|
|
break;
|
|
case "killcam":
|
|
self.killCamEnt = Spawn( "script_model", target_ent.origin);
|
|
self.killCamEnt SetModel( "tag_origin" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
self.animated_prop = spawn("script_model", self.tree.origin);
|
|
self.animated_prop SetModel("generic_prop_raven");
|
|
self.animated_prop.angles = self.tree.angles;
|
|
|
|
self.tree LinkTo(self.animated_prop, "j_prop_2");
|
|
|
|
foreach ( ent in self.linked_ents )
|
|
{
|
|
ent LinkTo(self.tree);
|
|
}
|
|
|
|
//self thread tree_bridge_damage_watch();
|
|
self thread tree_bridge_run();
|
|
}
|
|
|
|
tree_bridge_damage_watch(watch_ent, delete_on_trigger)
|
|
{
|
|
self endon("tree_down");
|
|
|
|
if(!IsDefined(delete_on_trigger))
|
|
delete_on_trigger = false;
|
|
|
|
large_health_value = 1000000;
|
|
damage_needed_to_fall = 100;
|
|
|
|
watch_ent.health = large_health_value;
|
|
watch_ent SetCanDamage(true);
|
|
|
|
while(1)
|
|
{
|
|
watch_ent waittill( "damage", amount, attacker, direction_vec, point, type );
|
|
attacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "tree" );
|
|
|
|
if(watch_ent.health < (large_health_value - damage_needed_to_fall))
|
|
break;
|
|
}
|
|
|
|
watch_ent SetCanDamage(false);
|
|
|
|
if( IsDefined( self.tree ) )
|
|
{
|
|
self.tree PlaySound( "scn_prison_tree_fall" );
|
|
}
|
|
|
|
if(delete_on_trigger)
|
|
watch_ent Delete();
|
|
|
|
|
|
self.attacker = attacker;
|
|
self notify("tree_down");
|
|
}
|
|
|
|
#using_animtree("animated_props");
|
|
tree_bridge_run()
|
|
{
|
|
self waittill("tree_down");
|
|
|
|
if( IsDefined( self.decal ) )
|
|
{
|
|
self.decal Delete();
|
|
}
|
|
|
|
if(IsDefined(self.clip_up_delete))
|
|
self.clip_up_delete Delete();
|
|
|
|
self.clip_up ConnectPaths();
|
|
|
|
self.tree maps\mp\_movers::notify_moving_platform_invalid();
|
|
self.animated_prop ScriptModelPlayAnimDeltaMotion("mp_prisonbreak_tree_fall");
|
|
|
|
anim_length = GetAnimLength( %mp_prisonbreak_tree_fall );
|
|
fall_time = anim_length - 0.3;
|
|
|
|
sound_origin = GetEnt( "tree_impact_sound_origin", "targetname" );
|
|
sound_origin delayThread( fall_time, ::PlaySound_wrapper, "scn_prison_tree_impact" );
|
|
|
|
wait( fall_time );
|
|
|
|
self.clip_down trigger_on();
|
|
self.clip_down DontInterpolate();
|
|
self.clip_up maps\mp\_movers::notify_moving_platform_invalid();
|
|
self.clip_up Delete();
|
|
|
|
foreach ( character in level.characters )
|
|
{
|
|
if ( character IsTouching( self.clip_down ) && IsAlive( character ) )
|
|
{
|
|
if ( IsDefined( self.attacker ) && IsDefined( self.attacker.team ) && ( self.attacker.team == character.team ) )
|
|
{
|
|
character maps\mp\_movers::mover_suicide();
|
|
}
|
|
else
|
|
{
|
|
self.clip_down.killCamEnt = self.killCamEnt;
|
|
character DoDamage( character.health + 500, character.origin, self.attacker, self.clip_down, "MOD_CRUSH" );
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ( vanguard in level.remote_uav )
|
|
{
|
|
if ( vanguard IsTouching( self.clip_down ) )
|
|
{
|
|
vanguard notify( "death" );
|
|
}
|
|
}
|
|
|
|
// Delete the clip at the base that prevents players from getting on it before it falls
|
|
clip_base = getent( "tree_base_clip", "targetname" );
|
|
if ( IsDefined( clip_base ) )
|
|
{
|
|
clip_base Delete();
|
|
}
|
|
}
|
|
|
|
PlaySound_wrapper( alias )
|
|
{
|
|
self PlaySound( alias );
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Log Piles
|
|
////////////////////////////////
|
|
log_piles()
|
|
{
|
|
if( getDvar( "r_reflectionProbeGenerate" ) == "1" )
|
|
return;
|
|
|
|
log_piles_precache();
|
|
|
|
wait .05;
|
|
|
|
piles = getstructArray("logpile","targetname");
|
|
array_thread(piles, ::log_pile_init);
|
|
}
|
|
|
|
log_piles_precache()
|
|
{
|
|
level.log_visual_link_joints = [];
|
|
level.log_visual_link_joints["ten_log_roll"] = "j_log_5";
|
|
|
|
level.log_anim_lengths = [];
|
|
level.log_anim_lengths["ten_log_roll"] = GetAnimLength( %mp_prisonbreak_log_roll );
|
|
|
|
level.log_anims = [];
|
|
level.log_anims["ten_log_roll"] = "mp_prisonbreak_log_roll";
|
|
foreach(key,value in level.log_anims)
|
|
{
|
|
PrecacheMpAnim(value);
|
|
}
|
|
}
|
|
|
|
log_pile_init()
|
|
{
|
|
self.logs = [];
|
|
self.animated_logs = [];
|
|
self.log_supports = [];
|
|
self.log_supports_broken = [];
|
|
self.clip_delete = [];
|
|
self.clip_show = [];
|
|
self.clip_move = [];
|
|
self.kill_trigger = undefined;
|
|
self.kill_trigger_linked = [];
|
|
|
|
link_visuals_to = undefined;
|
|
link_visuals_to_tag = undefined;
|
|
|
|
if(!IsDefined(self.angles))
|
|
self.angles = (0,0,0);
|
|
|
|
targets = GetEntArray(self.target, "targetname");
|
|
targets = array_combine( targets, getstructarray( self.target, "targetname" ) );
|
|
|
|
foreach( target_ent in targets )
|
|
{
|
|
if(!IsDefined(target_ent.script_noteworthy))
|
|
continue;
|
|
|
|
switch( target_ent.script_noteworthy )
|
|
{
|
|
case "log_with_use_visuals":
|
|
link_visuals_to = target_ent;
|
|
//fallthrough
|
|
case "log":
|
|
self.logs[ self.logs.size ] = target_ent;
|
|
if ( IsDefined( target_ent.target ) )
|
|
target_ent.endpos = getstruct( target_ent.target, "targetname" );
|
|
break;
|
|
case "animated_log_use_visuals":
|
|
link_visuals_to = target_ent;
|
|
if ( IsDefined( target_ent.script_animation ) )
|
|
link_visuals_to_tag = level.log_visual_link_joints[ target_ent.script_animation ];
|
|
self thread log_pile_support_damage_watch( target_ent );
|
|
//fallthrough
|
|
case "animated_log":
|
|
if ( IsDefined( target_ent.script_animation ) && IsDefined( level.log_anims[ target_ent.script_animation ] ) )
|
|
{
|
|
self.animated_logs[ self.animated_logs.size ] = target_ent;
|
|
}
|
|
break;
|
|
case "log_support":
|
|
self.log_supports[ self.log_supports.size ] = target_ent;
|
|
self thread log_pile_support_damage_watch( target_ent );
|
|
break;
|
|
case "log_support_broken":
|
|
self.log_supports_broken[ self.log_supports_broken.size ] = target_ent;
|
|
target_ent Hide();
|
|
break;
|
|
case "clip_delete":
|
|
self.clip_delete[ self.clip_delete.size ] = target_ent;
|
|
break;
|
|
case "clip_move":
|
|
//This is set up so the end position is viewed in the editor
|
|
if ( IsDefined( target_ent.target ) )
|
|
{
|
|
target_ent.end_pos = getstruct( target_ent.target, "targetname" );
|
|
if ( IsDefined( target_ent.end_pos ) && IsDefined( target_ent.end_pos.target ) )
|
|
{
|
|
target_ent.start_pos = getstruct( target_ent.end_pos.target, "targetname" );
|
|
if ( IsDefined( target_ent.start_pos ) )
|
|
{
|
|
target_ent.move_delta = target_ent.end_pos.origin - target_ent.start_pos.origin;
|
|
if ( target_ent is_dynamic_path() )
|
|
target_ent ConnectPaths();
|
|
target_ent.origin = target_ent.origin - target_ent.move_delta;
|
|
self.clip_move[ self.clip_move.size ] = target_ent;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case "clip_show":
|
|
self.clip_show[ self.clip_show.size ] = target_ent;
|
|
target_ent Hide();
|
|
target_ent NotSolid();
|
|
break;
|
|
case "kill_trigger":
|
|
self.kill_trigger = target_ent;
|
|
if ( IsDefined( self.kill_trigger.target ) )
|
|
{
|
|
self.kill_trigger.start_pos = getstruct(self.kill_trigger.target, "targetname");
|
|
if ( IsDefined( self.kill_trigger.start_pos ) && IsDefined( self.kill_trigger.start_pos.target ) )
|
|
{
|
|
self.kill_trigger.end_pos = getstruct(self.kill_trigger.start_pos.target, "targetname");
|
|
if(IsDefined(self.kill_trigger.end_pos))
|
|
{
|
|
self.kill_trigger.script_mover = Spawn( "script_model", self.kill_trigger.start_pos.origin );
|
|
self.kill_trigger.script_mover SetModel("tag_origin");
|
|
// self.kill_trigger.script_mover.killCamEnt = self.kill_trigger.script_mover;
|
|
self.kill_trigger EnableLinkTo();
|
|
self.kill_trigger LinkTo(self.kill_trigger.script_mover, "tag_origin");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case "kill_trigger_link":
|
|
self.kill_trigger_linked[self.kill_trigger_linked.size] = target_ent;
|
|
break;
|
|
case "use_icon":
|
|
self.use_icon_origin = target_ent.origin;
|
|
self.use_icon_angles = target_ent.angles;
|
|
break;
|
|
case "killcam":
|
|
self.killCamEnt = Spawn( "script_model", target_ent.origin );
|
|
self.killCamEnt SetModel( "tag_origin" );
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// have to to this after killcamEnt has had a chance to be defined
|
|
if( IsDefined( self.kill_trigger ) && IsDefined( self.kill_trigger.script_mover ) )
|
|
{
|
|
if( IsDefined( self.killCamEnt ) )
|
|
{
|
|
self.kill_trigger.script_mover.killCamEnt = self.killCamEnt;
|
|
}
|
|
else
|
|
{
|
|
self.kill_trigger.script_mover.killCamEnt = self.kill_trigger.script_mover;
|
|
}
|
|
}
|
|
|
|
if(IsDefined(link_visuals_to))
|
|
{
|
|
foreach(linked_kill_trigger in self.kill_trigger_linked)
|
|
{
|
|
linked_kill_trigger.killCamEnt = self.killCamEnt;
|
|
|
|
linked_kill_trigger EnableLinkTo();
|
|
linked_kill_trigger.no_moving_platfrom_unlink = true;
|
|
linked_kill_trigger linkTo(link_visuals_to, linked_kill_trigger.script_parameters);
|
|
}
|
|
}
|
|
|
|
self.nodes = GetNodeArray(self.target, "targetname");
|
|
foreach(node in self.nodes)
|
|
{
|
|
node DisconnectNode();
|
|
}
|
|
|
|
if((self.logs.size || self.animated_logs.size) && self.log_supports.size>0)
|
|
{
|
|
self thread log_pile_run();
|
|
self thread trap_init();
|
|
}
|
|
|
|
if(IsDefined(link_visuals_to) && IsDefined(self.use_model))
|
|
{
|
|
if(IsDefined(link_visuals_to_tag))
|
|
{
|
|
self.use_model LinkTo(link_visuals_to, link_visuals_to_tag);
|
|
}
|
|
else
|
|
{
|
|
self.use_model LinkTo(link_visuals_to);
|
|
}
|
|
}
|
|
}
|
|
|
|
log_pile_support_damage_watch(log_support)
|
|
{
|
|
self endon("trap_activated");
|
|
|
|
large_health_value = 1000000;
|
|
|
|
log_support.health = large_health_value;
|
|
log_support SetCanDamage(true);
|
|
|
|
while(1)
|
|
{
|
|
log_support waittill("damage", amount, attacker, direction_vec, point, type );
|
|
|
|
log_support.health = large_health_value;
|
|
if(is_explosive(type) && amount>=10)
|
|
{
|
|
self.owner = attacker;
|
|
break;
|
|
}
|
|
}
|
|
|
|
log_support SetCanDamage(false);
|
|
|
|
self notify("trap_activated");
|
|
}
|
|
|
|
log_pile_run()
|
|
{
|
|
self waittill("trap_activated");
|
|
|
|
self trap_set_can_use( false );
|
|
|
|
log_roll_time = 2.3;
|
|
self thread log_pile_kill_trigger( self.kill_trigger );
|
|
foreach(kill_trig in self.kill_trigger_linked)
|
|
{
|
|
self thread log_pile_kill_trigger( kill_trig );
|
|
}
|
|
self thread log_pile_kill_trigger_end( log_roll_time );
|
|
|
|
array_thread( self.log_supports, maps\mp\_movers::notify_moving_platform_invalid );
|
|
array_call( self.log_supports , ::Delete );
|
|
array_call( self.log_supports_broken, ::Show );
|
|
array_thread( self.clip_delete, maps\mp\_movers::notify_moving_platform_invalid );
|
|
array_call( self.clip_delete, ::Delete );
|
|
array_call( self.clip_show , ::Show );
|
|
array_call( self.clip_show , ::Solid );
|
|
|
|
foreach(clip_move in self.clip_move)
|
|
{
|
|
if(clip_move is_dynamic_path())
|
|
clip_move delayCall(log_roll_time, ::DisconnectPaths);
|
|
|
|
clip_move thread log_pile_clip_move( 1.5, 0.5 );
|
|
}
|
|
|
|
if(IsDefined(self.kill_trigger) && IsDefined(self.kill_trigger.script_mover))
|
|
{
|
|
//TODO: Support angle change?
|
|
self.kill_trigger.script_mover MoveTo(self.kill_trigger.end_pos.origin, log_roll_time, log_roll_time*.5, 0);
|
|
}
|
|
|
|
|
|
foreach(log in self.logs)
|
|
{
|
|
if(IsDefined(log.endpos))
|
|
{
|
|
log MoveTo(log.endpos.origin, log_roll_time, log_roll_time*.5, 0);
|
|
|
|
delta_angles = log.endpos.angles - log.angles;
|
|
delta_angles = normalize_angles_180(delta_angles);
|
|
delta_angles += (4 * 360,0,0); //Roll 4 times
|
|
vel = delta_angles/log_roll_time;
|
|
log RotateVelocity(vel, log_roll_time, log_roll_time*.5, 0);
|
|
}
|
|
}
|
|
|
|
foreach(animated_log in self.animated_logs)
|
|
{
|
|
animated_log maps\mp\_movers::notify_moving_platform_invalid();
|
|
animated_log ScriptModelPlayAnimDeltaMotion( level.log_anims[animated_log.script_animation] );
|
|
|
|
throw_vec = ( -20000, 0, 9000 );
|
|
offset = ( 0, 0, 50 );
|
|
delete_volume = GetEnt( "care_package_delete_volume", "targetname" );
|
|
|
|
maps\mp\killstreaks\_airdrop::throw_linked_care_packages( animated_log, offset, throw_vec, delete_volume );
|
|
|
|
anim_length = level.log_anim_lengths[animated_log.script_animation];
|
|
if(isDefined(anim_length) && anim_length>log_roll_time)
|
|
{
|
|
log_roll_time = anim_length;
|
|
}
|
|
}
|
|
|
|
if( IsDefined( self.animated_logs ) && ( self.animated_logs.size > 0 ) )
|
|
{
|
|
self.animated_logs[0] PlaySoundOnMovingEnt( "scn_prison_logtrap_logs_roll" );
|
|
}
|
|
|
|
wait log_roll_time;
|
|
|
|
self notify("log_roll_done");
|
|
|
|
wait .05;
|
|
foreach(node in self.nodes)
|
|
{
|
|
node ConnectNode();
|
|
}
|
|
|
|
}
|
|
|
|
log_pile_clip_move( delay_time, move_time )
|
|
{
|
|
wait( delay_time );
|
|
self MoveTo(self.origin + self.move_delta, move_time );
|
|
}
|
|
|
|
log_pile_kill_trigger(trigger)
|
|
{
|
|
if(!IsDefined(trigger))
|
|
return;
|
|
|
|
self endon("log_roll_end_kill_trigger");
|
|
while(1)
|
|
{
|
|
trigger waittill("trigger", player);
|
|
|
|
if ( !log_pile_can_damage_player(player) )
|
|
continue;
|
|
|
|
inflictor = trigger;
|
|
if(IsDefined(trigger.script_mover))
|
|
inflictor = trigger.script_mover;
|
|
|
|
attacker = self.owner;
|
|
if ( IsAgent( player ) && IsDefined( player.owner ) && IsDefined( attacker ) && ( player.owner == attacker ) )
|
|
{
|
|
player maps\mp\_movers::mover_suicide();
|
|
}
|
|
else
|
|
{
|
|
inflictor.killCamEnt = self.killCamEnt;
|
|
inflictor RadiusDamage( player.origin, 8, 1000, 1000, attacker, "MOD_CRUSH", "none" );
|
|
}
|
|
}
|
|
}
|
|
|
|
log_pile_kill_trigger_end(waitTime)
|
|
{
|
|
wait waitTime;
|
|
self notify("log_roll_end_kill_trigger");
|
|
}
|
|
|
|
log_pile_can_damage_player(player)
|
|
{
|
|
// if(!IsDefined(self.owner))
|
|
// return false;
|
|
//
|
|
// if(!level.teamBased)
|
|
// return true;
|
|
//
|
|
// if(player.team != self.owner.team)
|
|
// return true;
|
|
//
|
|
// return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Falling Rocks
|
|
////////////////////////////////
|
|
falling_rocks()
|
|
{
|
|
rocks = getEntArray("falling_rock","targetname");
|
|
array_thread(rocks, ::falling_rock_init);
|
|
}
|
|
|
|
falling_rock_init()
|
|
{
|
|
|
|
self.fall_to =[];
|
|
self.clip_move = [];
|
|
|
|
targets = GetEntArray(self.target, "targetname");
|
|
structs = getstructarray(self.target, "targetname");
|
|
|
|
targets = array_combine(targets, structs);
|
|
foreach(target in targets)
|
|
{
|
|
if(!IsDefined(target.script_noteworthy))
|
|
continue;
|
|
|
|
switch(target.script_noteworthy)
|
|
{
|
|
case "kill_trigger":
|
|
target EnableLinkTo();
|
|
target LinkTo(self);
|
|
self.kill_trigger = target;
|
|
break;
|
|
case "rock_clip":
|
|
target LinkTo(self);
|
|
self.clip = target;
|
|
break;
|
|
case "fall_to":
|
|
self.fall_to[self.fall_to.size] = target;
|
|
target.fall_dist = Distance(self.origin, target.origin);
|
|
self.fall_dist = target.fall_dist;
|
|
|
|
while(IsDefined(target.target))
|
|
{
|
|
prev_target = target;
|
|
target = getstruct(target.target, "targetname");
|
|
if(!IsDefined(target))
|
|
break;
|
|
|
|
self.fall_to[self.fall_to.size] = target;
|
|
target.fall_dist = Distance(prev_target.origin, target.origin);
|
|
self.fall_dist += target.fall_dist;
|
|
}
|
|
break;
|
|
|
|
case "clip_move":
|
|
//This is set up so the end position is viewed in the editor
|
|
if(IsDefined(target.target))
|
|
{
|
|
target.end_pos = getstruct(target.target, "targetname");
|
|
if(IsDefined(target.end_pos) && IsDefined(target.end_pos.target))
|
|
{
|
|
target.start_pos = getstruct(target.end_pos.target, "targetname");
|
|
if(IsDefined(target.start_pos))
|
|
{
|
|
target.move_delta = target.end_pos.origin - target.start_pos.origin;
|
|
target.origin = target.origin - target.move_delta;
|
|
if(target is_dynamic_path())
|
|
target ConnectPaths();
|
|
self.clip_move[self.clip_move.size] = target;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
self thread falling_rock_damage_watch();
|
|
self thread falling_rock_run();
|
|
}
|
|
|
|
is_dynamic_path()
|
|
{
|
|
return IsDefined(self.spawnflags) && self.spawnflags&1;
|
|
}
|
|
|
|
falling_rock_damage_watch()
|
|
{
|
|
large_health_value = 1000000;
|
|
|
|
self.health = large_health_value;
|
|
self SetCanDamage(true);
|
|
|
|
while(1)
|
|
{
|
|
self waittill("damage", amount, attacker, direction_vec, point, type );
|
|
|
|
self.health = large_health_value;
|
|
if(is_explosive(type))
|
|
{
|
|
self.attacker = attacker;
|
|
break;
|
|
}
|
|
}
|
|
|
|
self SetCanDamage(false);
|
|
|
|
self notify("rock_fall");
|
|
}
|
|
|
|
falling_rock_run()
|
|
{
|
|
self waittill("rock_fall");
|
|
|
|
fall_time = 1.0;
|
|
|
|
self thread falling_rock_kill_trigger();
|
|
|
|
accel = 1;
|
|
for(i=0; i<self.fall_to.size; i++)
|
|
{
|
|
next = self.fall_to[i];
|
|
|
|
time = (next.fall_dist/self.fall_dist) * fall_time;
|
|
|
|
self MoveTo(next.origin, time, time*accel, 0);
|
|
self RotateTo(next.angles, time, time*accel, 0);
|
|
|
|
//the last move, raise the clip
|
|
if(i==self.fall_to.size-1)
|
|
{
|
|
foreach(clip_move in self.clip_move)
|
|
{
|
|
if(clip_move is_dynamic_path())
|
|
clip_move delayCall(time, ::DisconnectPaths);
|
|
clip_move MoveTo(clip_move.origin + clip_move.move_delta, time);
|
|
}
|
|
}
|
|
|
|
self waittill("movedone");
|
|
accel = 0; //only first move accels
|
|
}
|
|
|
|
self notify("rock_move_done");
|
|
self.clip Delete();
|
|
self.kill_trigger Delete();
|
|
}
|
|
|
|
falling_rock_kill_trigger()
|
|
{
|
|
self endon("death");
|
|
self endon("rock_move_done");
|
|
|
|
while(1)
|
|
{
|
|
self.kill_trigger waittill("trigger", player);
|
|
|
|
RadiusDamage(player.origin, 8, 1000, 1000, self.attacker, "MOD_CRUSH");
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Rock Slide
|
|
////////////////////////////////
|
|
rock_slides()
|
|
{
|
|
rock_slides_precache();
|
|
|
|
wait .05;
|
|
rocks = getStructArray("rock_slide","targetname");
|
|
array_thread(rocks, ::rock_slides_init);
|
|
}
|
|
|
|
rock_slides_precache()
|
|
{
|
|
|
|
}
|
|
|
|
rock_slides_init()
|
|
{
|
|
self.ground_ents = [];
|
|
self.rocks = [];
|
|
|
|
targets = GetEntArray(self.target, "targetname");
|
|
|
|
remove = true;
|
|
|
|
foreach(target in targets)
|
|
{
|
|
if(!IsDefined(target.script_noteworthy))
|
|
continue;
|
|
|
|
switch(target.script_noteworthy)
|
|
{
|
|
case "ground":
|
|
if(IsDefined(target.target) && !remove)
|
|
{
|
|
target.start_pos = getstruct(target.target, "targetname");
|
|
if(IsDefined(target.start_pos) && IsDefined(target.start_pos.target))
|
|
{
|
|
target.end_pos = getstruct(target.start_pos.target, "targetname");
|
|
if(IsDefined(target.end_pos))
|
|
{
|
|
target.move_ent = spawn("script_model", target.start_pos.origin);
|
|
target.move_ent SetModel("tag_origin");
|
|
target.move_ent.angles = target.start_pos.angles;
|
|
target LinkTo(target.move_ent);
|
|
self.ground_ents[self.ground_ents.size] = target;
|
|
target.move_delete = IsDefined(target.end_pos.script_noteworthy) && target.end_pos.script_noteworthy=="delete";
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case "rock":
|
|
if(remove)
|
|
{
|
|
target Delete();
|
|
}
|
|
else
|
|
{
|
|
target.end_pos = getstruct(target.target, "targetname");
|
|
if(IsDefined(target.end_pos))
|
|
{
|
|
self.rocks[self.rocks.size] = target;
|
|
target.move_delete = IsDefined(target.end_pos.script_noteworthy) && target.end_pos.script_noteworthy=="delete";
|
|
}
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!remove)
|
|
{
|
|
array_thread(self.ground_ents, ::rock_slide_damage_watch, self);
|
|
self thread rock_slide_run();
|
|
}
|
|
self thread trap_init(remove);
|
|
}
|
|
|
|
rock_slide_damage_watch(parent)
|
|
{
|
|
parent endon("trap_activated");
|
|
|
|
large_health_value = 1000000;
|
|
|
|
self.health = large_health_value;
|
|
self SetCanDamage(true);
|
|
|
|
while(1)
|
|
{
|
|
self waittill("damage", amount, attacker, direction_vec, point, type );
|
|
|
|
self.health = large_health_value;
|
|
if(is_explosive(type))
|
|
{
|
|
self.attacker = attacker;
|
|
break;
|
|
}
|
|
}
|
|
|
|
self SetCanDamage(false);
|
|
|
|
parent notify("trap_activated");
|
|
}
|
|
|
|
rock_slide_run()
|
|
{
|
|
self waittill("trap_activated");
|
|
|
|
Earthquake(.4, 3, self.origin, 800);
|
|
|
|
rock_time = 1.5;
|
|
foreach(rock in self.rocks)
|
|
{
|
|
rock MoveTo(rock.end_pos.origin, rock_time, rock_time, 0);
|
|
rock RotateTo(rock.end_pos.angles, rock_time, rock_time, 0);
|
|
if(rock.move_delete)
|
|
rock delayCall(rock_time, ::delete);
|
|
}
|
|
|
|
wait .5;
|
|
|
|
slide_time = 1;
|
|
foreach ( ent in self.ground_ents )
|
|
{
|
|
ent.move_ent MoveTo(ent.end_pos.origin, slide_time, slide_time, 0);
|
|
ent.move_ent RotateTo(ent.end_pos.angles, slide_time, slide_time, 0);
|
|
if(ent.move_delete)
|
|
ent delayCall(rock_time, ::delete);
|
|
}
|
|
}
|
|
|
|
hand_icon(type, origin, angles, end_ons)
|
|
{
|
|
if(level.createFX_enabled)
|
|
return;
|
|
if(!IsDefined(level.hand_icon_count))
|
|
level.hand_icon_count = 0;
|
|
|
|
level.hand_icon_count++;
|
|
|
|
icon_id = "hand_icon_" + level.hand_icon_count;
|
|
|
|
hand_icon_update(type, origin, angles, icon_id, end_ons);
|
|
|
|
foreach(player in level.players)
|
|
{
|
|
if(IsDefined(player.hand_icons) && IsDefined(player.hand_icons[icon_id]))
|
|
{
|
|
player.hand_icons[icon_id] thread hand_icon_fade_out();
|
|
}
|
|
}
|
|
}
|
|
|
|
hand_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);
|
|
}
|
|
|
|
while(!IsDefined(level.players))
|
|
wait .05;
|
|
|
|
show_dist = 200;
|
|
icon = "hint_usable";
|
|
pin = false;
|
|
switch(type)
|
|
{
|
|
default:
|
|
break;
|
|
}
|
|
|
|
dir = undefined;
|
|
if(IsDefined(angles))
|
|
{
|
|
dir = AnglesToForward(angles);
|
|
}
|
|
|
|
show_dist_sqr = show_dist*show_dist;
|
|
|
|
while(1)
|
|
{
|
|
foreach(player in level.players)
|
|
{
|
|
if(!IsDefined(player.hand_icons))
|
|
player.hand_icons = [];
|
|
|
|
test_origin = player.origin+(0,0,50); //Switches are about 50 units off the ground
|
|
dist_sqr = DistanceSquared(test_origin, origin);
|
|
|
|
dir_check = true;
|
|
if(IsDefined(dir))
|
|
{
|
|
dir_to_player = VectorNormalize(test_origin - origin);
|
|
dir_check = VectorDot(dir, dir_to_player)>.2;
|
|
}
|
|
|
|
if(dist_sqr<=show_dist_sqr && dir_check && (!isDefined(self.in_use) || !self.in_use) && !( player isUsingRemote() ) )
|
|
{
|
|
if(!IsDefined(player.hand_icons[icon_id]))
|
|
{
|
|
player.hand_icons[icon_id] = hand_icon_create(player, icon, origin, pin);
|
|
player.hand_icons[icon_id].alpha = 0;
|
|
}
|
|
|
|
player.hand_icons[icon_id] notify("stop_fade");
|
|
player.hand_icons[icon_id] thread hand_icon_fade_in();
|
|
}
|
|
else
|
|
{
|
|
if(IsDefined(player.hand_icons[icon_id]))
|
|
{
|
|
player.hand_icons[icon_id] thread hand_icon_fade_out();
|
|
}
|
|
}
|
|
}
|
|
wait .05;
|
|
}
|
|
}
|
|
|
|
hand_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;
|
|
}
|
|
|
|
hand_icon_fade_in()
|
|
{
|
|
self endon("death");
|
|
|
|
if(self.alpha == 1)
|
|
return;
|
|
|
|
self FadeOverTime(.5);
|
|
self.alpha = 1;
|
|
}
|
|
|
|
hand_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();
|
|
}
|
|
|
|
tower_radio()
|
|
{
|
|
tower_radio = GetEnt( "tower_radio", "targetname" );
|
|
|
|
tower_radio.tracklist = [];
|
|
tower_radio.tracklist[0] = "mus_emt_portable_radio_01";
|
|
tower_radio.tracklist[1] = "mus_emt_portable_radio_02";
|
|
tower_radio.tracklist[2] = "mus_emt_portable_radio_03";
|
|
|
|
gameFlagWait( "prematch_done" );
|
|
|
|
tower_radio thread tower_radio_damage_watch();
|
|
|
|
tower_radio endon( "death" );
|
|
|
|
while( 1 )
|
|
{
|
|
level waittill( "connected", player );
|
|
tower_radio thread tower_radio_sounds( player );
|
|
}
|
|
}
|
|
|
|
tower_radio_damage_watch()
|
|
{
|
|
self.health = 10000;
|
|
self SetCanDamage( true );
|
|
self waittill( "damage", damage, attacker, direction_vec, point, type );
|
|
self PlaySound( "radio_destroyed_static" );
|
|
self PhysicsLaunchClient( point, direction_vec );
|
|
}
|
|
|
|
tower_radio_sounds( player )
|
|
{
|
|
self endon( "damage" );
|
|
player endon("death");
|
|
player endon("disconnect");
|
|
|
|
player waittill( "spawned_player" );
|
|
waitframe();
|
|
|
|
last_song = "";
|
|
|
|
while( 1 )
|
|
{
|
|
song = last_song;
|
|
while( song == last_song )
|
|
{
|
|
song = random( self.tracklist );
|
|
}
|
|
song_length = LookupSoundLength( song ) / 1000;
|
|
if( song_length < 0.1 )
|
|
{
|
|
// breakpoint; // something went horribly wrong, bad soundalias or sound length
|
|
wait( 5.0 ); // fail quietly, since at this point, it's probably more important that the map run than we force audio to get their .wav files out of devraw
|
|
}
|
|
else
|
|
{
|
|
self PlaySoundToPlayer( song, player );
|
|
}
|
|
|
|
wait( song_length );
|
|
last_song = song;
|
|
}
|
|
}
|