boiii-scripts/shared/gameobjects_shared.gsc
2023-04-13 17:30:38 +02:00

4530 lines
98 KiB
Plaintext

#using scripts\shared\callbacks_shared;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\hud_util_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\math_shared;
#using scripts\shared\objpoints_shared;
#using scripts\shared\system_shared;
#using scripts\shared\trigger_shared;
#using scripts\shared\tweakables_shared;
#using scripts\shared\util_shared;
#using scripts\shared\weapons_shared;
#namespace gameobjects;
function autoexec __init__sytem__() { system::register("gameobjects",&__init__,undefined,undefined); }
function __init__()
{
level.numGametypeReservedObjectives = 0;
level.releasedObjectives = [];
callback::on_spawned( &on_player_spawned );
callback::on_disconnect( &on_disconnect );
callback::on_laststand( &on_player_last_stand );
}
function main()
{
level.vehiclesEnabled = GetGametypeSetting( "vehiclesEnabled" );
level.vehiclesTimed = GetGametypeSetting( "vehiclesTimed" );
level.objectivePingDelay = GetGametypeSetting( "objectivePingTime" );
level.nonTeamBasedTeam = "allies";
if ( !IsDefined( level.allowedGameObjects ) )
{
level.allowedGameObjects = [];
}
/#
//###stefan $NOTE don't remove vehicles when running the vehicle test maps
if ( level.script == "mp_vehicle_test" )
{
level.vehiclesEnabled = true;
}
#/
if (level.vehiclesEnabled)
{
level.allowedGameObjects[level.allowedGameObjects.size]= "vehicle";
filter_script_vehicles_from_vehicle_descriptors(level.allowedGameObjects);
}
entities= GetEntArray();
for (entity_index= entities.size-1; entity_index>=0; entity_index--)
{
entity= entities[entity_index];
if (!entity_is_allowed(entity, level.allowedGameObjects))
{
entity delete();
}
}
return;
}
function register_allowed_gameobject( gameobject )
{
if ( !IsDefined( level.allowedGameObjects ) )
{
level.allowedGameObjects = [];
}
level.allowedGameObjects[level.allowedGameObjects.size] = gameobject;
}
function clear_allowed_gameobjects()
{
level.allowedGameObjects = [];
}
//bool
function entity_is_allowed( entity, allowed_game_modes )
{
allowed= true;
// is entity allowed for any of the give game modes?
if (isdefined(entity.script_gameobjectname) &&
entity.script_gameobjectname!="[all_modes]" )
{
allowed= false;
// allow a space-separated list of gameobjectnames
gameobjectnames= strtok(entity.script_gameobjectname, " ");
for (i= 0; i<allowed_game_modes.size && !allowed; i++)
{
for (j= 0; j<gameobjectnames.size && !allowed; j++)
{
allowed= (gameobjectnames[j]==allowed_game_modes[i]);
}
}
}
return allowed;
}
//bool
function location_is_allowed( entity, location )
{
allowed = true;
location_list = undefined;
// Check if Location stored on Script_Noteworthy
//----------------------------------------------
if ( IsDefined( entity.script_noteworthy ) )
{
location_list = entity.script_noteworthy;
}
// Check if Location stored on Script_Location, Takes Prescedence over Script_Noteworthy
//--------------------------------------------------------------------------------------
if ( IsDefined( entity.script_location ) )
{
location_list = entity.script_location;
}
if ( IsDefined( location_list ) )
{
if ( location_list == "[all_modes]" )
{
allowed = true;
}
else
{
allowed = false;
gameobjectlocations = StrTok( location_list, " " );
for ( j = 0; j < gameobjectlocations.size; j++ )
{
if ( gameobjectlocations[ j ] == location )
{
allowed = true;
break;
}
}
}
}
return allowed;
}
// this function filters out script_vehicles (which are usually placed as prefabs)
// based on associated vehicle_descriptor objects
function filter_script_vehicles_from_vehicle_descriptors(
allowed_game_modes)
{
vehicle_descriptors= GetEntArray("vehicle_descriptor", "targetname");
script_vehicles= GetEntArray("script_vehicle", "classname");
vehicles_to_remove= [];
for (descriptor_index= 0; descriptor_index<vehicle_descriptors.size; descriptor_index++)
{
descriptor= vehicle_descriptors[descriptor_index];
closest_distance_sq= 1000000000000.0;
closest_vehicle= undefined;
for (vehicle_index= 0; vehicle_index<script_vehicles.size; vehicle_index++)
{
vehicle= script_vehicles[vehicle_index];
dsquared= DistanceSquared(vehicle GetOrigin(), descriptor GetOrigin());
if (dsquared < closest_distance_sq)
{
closest_distance_sq= dsquared;
closest_vehicle= vehicle;
}
}
if (isdefined(closest_vehicle))
{
if (!entity_is_allowed(descriptor, allowed_game_modes))
{
vehicles_to_remove[vehicles_to_remove.size]= closest_vehicle;
}
}
}
for (vehicle_index= 0; vehicle_index<vehicles_to_remove.size; vehicle_index++)
{
vehicles_to_remove[vehicle_index] delete();
}
return;
}
//=====================================================================================
// Callback functions
//=====================================================================================
function on_player_spawned()
{
self endon( "disconnect" );
level endon ( "game_ended" );
self thread on_death();
self.touchTriggers = [];
self.packObject = [];
self.packIcon = [];
self.carryObject = undefined;
self.claimTrigger = undefined;
self.canPickupObject = true;
self.disabledWeapon = 0;
self.killedInUse = undefined;
}
//Drops any carried object when the player dies
function on_death()
{
level endon ( "game_ended" );
self endon("killOnDeathMonitor");
self waittill ( "death" );
self thread gameObjects_dropped();
}
//Drops any carried object when the player disconnects
function on_disconnect()
{
level endon ( "game_ended" );
self thread gameObjects_dropped();
}
//Drops any carried object when the player enters laststand
function on_player_last_stand()
{
self thread gameObjects_dropped();
}
function gameObjects_dropped()
{
if ( isdefined( self.carryObject ) )
{
self.carryObject thread set_dropped();
}
if ( isdefined( self.packObject ) && self.packObject.size > 0 )
{
foreach(item in self.packObject)
{
item thread set_dropped();
}
}
}
//=====================================================================================
/*
=============
create_carry_object
Creates and returns a carry object
=============
*/
function create_carry_object( ownerTeam, trigger, visuals, offset, objectiveName, hitSound )
{
carryObject = spawnStruct();
carryObject.type = "carryObject";
carryObject.curOrigin = trigger.origin;
carryObject.entNum = trigger getEntityNumber();
carryObject.hitSound = hitSound;
if ( isSubStr( trigger.classname, "use" ) )
{
carryObject.triggerType = "use";
}
else
{
carryObject.triggerType = "proximity";
}
// associated trigger
trigger.baseOrigin = trigger.origin;
carryObject.trigger = trigger;
carryObject.useWeapon = undefined;
if ( !isdefined( offset ) )
{
offset = (0,0,0);
}
carryObject.offset3d = offset;
carryObject.newStyle = false;
if ( isdefined( objectiveName ) )
{
if( !SessionModeIsCampaignGame() )
{
carryObject.newStyle = true;
}
}
else
{
objectiveName = &"";
}
// associated visual objects
for ( index = 0; index < visuals.size; index++ )
{
visuals[index].baseOrigin = visuals[index].origin;
visuals[index].baseAngles = visuals[index].angles;
}
carryObject.visuals = visuals;
carryObject _set_team( ownerTeam );
// compass objectives
carryObject.compassIcons = [];
carryObject.objID =[];
// this block will completely go away when we have fully switched to the new style
if ( !carryObject.newStyle )
{
foreach( team in level.teams )
{
carryObject.objID[team] = get_next_obj_id();
}
}
carryObject.objIDPingFriendly = false;
carryObject.objIDPingEnemy = false;
level.objIDStart += 2;
// this block will completely go away when we have fully switched to the new style
if ( !carryObject.newStyle )
{
if ( level.teamBased )
{
foreach ( team in level.teams )
{
if( SessionModeIsCampaignGame() )
{
if( team == "allies" )
{
objective_add( carryObject.objID[team], "active", carryObject.curOrigin, objectiveName );
}
else
{
objective_add( carryObject.objID[team], "invisible", carryObject.curOrigin, objectiveName );
}
}
else
{
objective_add( carryObject.objID[team], "invisible", carryObject.curOrigin, objectiveName );
}
objective_team( carryObject.objID[team], team );
carryObject.objPoints[team] = objpoints::create( "objpoint_" + team + "_" + carryObject.entNum, carryObject.curOrigin + offset, team, undefined );
carryObject.objPoints[team].alpha = 0;
}
}
else
{
// TODO MTEAM - not sure why the we only use allies in dm
objective_add( carryObject.objID[level.nonTeamBasedTeam], "invisible", carryObject.curOrigin, objectiveName );
carryObject.objPoints[level.nonTeamBasedTeam] = objpoints::create( "objpoint_"+ level.nonTeamBasedTeam + "_" + carryObject.entNum, carryObject.curOrigin + offset, "all", undefined );
carryObject.objPoints[level.nonTeamBasedTeam].alpha = 0;
}
}
carryObject.objectiveID = get_next_obj_id();
// new style objective
if ( carryObject.newStyle )
{
objective_add( carryObject.objectiveID, "invisible", carryObject.curOrigin, objectiveName );
}
// carrying player
carryObject.carrier = undefined;
// misc
carryObject.isResetting = false;
carryObject.interactTeam = "none"; // "none", "any", "friendly", "enemy";
carryObject.allowWeapons = false;
carryObject.visibleCarrierModel = undefined;
carryObject.dropOffset = 0;
carryObject.disallowRemoteControl = false;
// 3d world icons
carryObject.worldIcons = [];
carryObject.carrierVisible = false; // carryObject only
carryObject.visibleTeam = "none"; // "none", "any", "friendly", "enemy";
carryObject.worldIsWaypoint = [];
carryObject.worldIcons_disabled = [];
carryObject.carryIcon = undefined;
// callbacks
carryObject.setDropped = undefined;
carryObject.onDrop = undefined;
carryObject.onPickup = undefined;
carryObject.onReset = undefined;
if ( carryObject.triggerType == "use" )
{
carryObject thread carry_object_use_think();
}
else
{
carryObject.numTouching["neutral"] = 0;
carryObject.numTouching["none"] = 0;
carryObject.touchList["neutral"] = [];
carryObject.touchList["none"] = [];
foreach( team in level.teams )
{
carryObject.numTouching[team] = 0;
carryObject.touchList[team] = [];
}
carryObject.curProgress = 0;
carryObject.useTime = 0;
carryObject.useRate = 0;
carryObject.claimTeam = "none";
carryObject.claimPlayer = undefined;
carryObject.lastClaimTeam = "none";
carryObject.lastClaimTime = 0;
carryObject.claimGracePeriod = 0;
carryObject.mustMaintainClaim = false;
carryObject.canContestClaim = false;
carryObject.decayProgress = false;
carryObject.teamUseTimes = [];
carryObject.teamUseTexts = [];
carryObject.onUse =&set_picked_up;
carryObject thread use_object_prox_think();
//carryObject thread carry_object_prox_think();
}
carryObject thread update_carry_object_origin();
carryObject thread update_carry_object_objective_origin();
return carryObject;
}
/*
=============
carry_object_use_think
Think function for "use" type carry objects
=============
*/
function carry_object_use_think()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
while ( true )
{
self.trigger waittill ( "trigger", player );
if ( self.isResetting )
{
continue;
}
if ( !isAlive( player ) )
{
continue;
}
if ( isdefined(player.laststand) && player.laststand )
{
continue;
}
if ( !self can_interact_with( player ) )
{
continue;
}
if ( !player.canPickupObject )
{
continue;
}
if ( player.throwingGrenade )
{
continue;
}
if ( isdefined( self.carrier ) )
{
continue;
}
if ( player isInVehicle() )
{
continue;
}
if ( player isRemoteControlling() || player util::isUsingRemote() )
{
continue;
}
if ( ( isdefined( player.selectingLocation ) && player.selectingLocation ) )
{
continue;
}
if ( player IsWeaponViewOnlyLinked() )
{
continue;
}
if( !player isTouching( self.trigger ) )
{
continue;
}
self set_picked_up( player );
}
}
/*
=============
carry_object_prox_think
Think function for "proximity" type carry objects
=============
*/
function carry_object_prox_think()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
while ( true )
{
self.trigger waittill ( "trigger", player );
if ( self.isResetting )
{
continue;
}
if ( !isAlive( player ) )
{
continue;
}
if ( isdefined(player.laststand) && player.laststand )
{
continue;
}
if ( !self can_interact_with( player ) )
{
continue;
}
if ( !player.canPickupObject )
{
continue;
}
if ( player.throwingGrenade )
{
continue;
}
if ( isdefined( self.carrier ) )
{
continue;
}
if ( player isInVehicle() )
{
continue;
}
if ( player isRemoteControlling() || player util::isUsingRemote() )
{
continue;
}
if ( ( isdefined( player.selectingLocation ) && player.selectingLocation ) )
{
continue;
}
if ( player IsWeaponViewOnlyLinked() )
{
continue;
}
//Fix for player being able to respawn with the flag. This occured due to
//trigger collisions being stored and used a frame later than the collision occured.
if( !player isTouching( self.trigger ) )
{
continue;
}
self set_picked_up( player );
}
}
/*
=============
pickup_object_delay
Temporarily disallows picking up of "proximity" type objects
=============
*/
function pickup_object_delay( origin )
{
level endon ( "game_ended" );
self endon("death");
self endon("disconnect");
self.canPickupObject = false;
for( ;; )
{
if ( distanceSquared( self.origin, origin ) > 64*64 )
{
break;
}
wait 0.2;
}
self.canPickupObject = true;
}
/*
=============
set_picked_up
Sets this object as picked up by passed player
=============
*/
function set_picked_up( player )
{
if ( !IsAlive( player ) )
{
return;
}
if ( self.type == "carryObject" )
{
if(isdefined( player.carryObject ))
{
if ( ( isdefined( player.carryObject.swappable ) && player.carryObject.swappable ) )
{
player.carryObject thread set_dropped();
}
else
{
if ( isdefined( self.onPickupFailed ) )
{
self [[self.onPickupFailed]]( player );
}
return;
}
}
player give_object( self );
}
else if( self.type == "packObject")
{
if(IsDefined(level.max_packObjects) && (level.max_packObjects <= player.packObject.size))
{
if ( isdefined( self.onPickupFailed ) )
{
self [[self.onPickupFailed]]( player );
}
return;
}
player give_pack_object( self );
}
self set_carrier( player );
self ghost_visuals();
// this should get replaced triggerenable functionality
self.trigger.origin += (0,0,10000);
self notify ( "pickup_object" );
if ( isdefined( self.onPickup ) )
{
self [[self.onPickup]]( player );
}
self update_compass_icons();
self update_world_icons();
self update_objective();
}
function unlink_grenades()
{
radius = 32;
origin = self.origin;
grenades = getentarray( "grenade", "classname" );
radiusSq = radius * radius;
linkedGrenades = [];
foreach( grenade in grenades )
{
if( DistanceSquared( origin, grenade.origin ) < radiusSq )
{
if ( grenade islinkedto( self ) )
{
grenade unlink();
linkedGrenades[linkedGrenades.size] = grenade;
}
}
}
waittillframeend;
foreach( grenade in linkedGrenades )
{
grenade launch( (RandomFloatRange( -5, 5 ),RandomFloatRange( -5, 5 ),5) );
}
}
function ghost_visuals()
{
foreach ( visual in self.visuals )
{
visual Ghost();
visual thread unlink_grenades();
}
}
function update_carry_object_origin()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
if ( self.newStyle )
{
return;
}
objPingDelay = level.objectivePingDelay;
for ( ;; )
{
if ( isdefined( self.carrier ) && level.teamBased )
{
self.curOrigin = self.carrier.origin + (0,0,75);
foreach ( team in level.teams )
{
self.objPoints[team] objpoints::update_origin( self.curOrigin );
}
if ( (self.visibleTeam == "friendly" || self.visibleTeam == "any") && self.objIDPingFriendly )
{
foreach ( team in level.teams )
{
if ( self is_friendly_team( team ) )
{
if ( self.objPoints[team].isShown )
{
self.objPoints[team].alpha = self.objPoints[team].baseAlpha;
self.objPoints[team] fadeOverTime( objPingDelay + 1.0 );
self.objPoints[team].alpha = 0;
}
objective_position( self.objID[team], self.curOrigin );
}
}
}
if ( (self.visibleTeam == "enemy" || self.visibleTeam == "any") && self.objIDPingEnemy )
{
if ( !self is_friendly_team( team ) )
{
if ( self.objPoints[team].isShown )
{
self.objPoints[team].alpha = self.objPoints[team].baseAlpha;
self.objPoints[team] fadeOverTime( objPingDelay + 1.0 );
self.objPoints[team].alpha = 0;
}
objective_position( self.objID[team], self.curOrigin );
}
}
self util::wait_endon( objPingDelay, "dropped", "reset" );
}
else if( isdefined( self.carrier ) )
{
self.curOrigin = self.carrier.origin + (0,0,75);
self.objPoints[level.nonTeamBasedTeam] objpoints::update_origin( self.curOrigin );
objective_position( self.objID[level.nonTeamBasedTeam], self.curOrigin );
{wait(.05);};
}
else
{
if ( level.teamBased )
{
foreach( team in level.teams )
{
self.objPoints[team] objpoints::update_origin( self.curOrigin + self.offset3d );
}
}
else
{
self.objPoints[level.nonTeamBasedTeam] objpoints::update_origin( self.curOrigin + self.offset3d );
}
{wait(.05);};
}
}
}
function update_carry_object_objective_origin()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
if ( !self.newStyle )
{
return;
}
objPingDelay = level.objectivePingDelay;
for ( ;; )
{
if ( isdefined( self.carrier ) )
{
self.curOrigin = self.carrier.origin;
objective_position( self.objectiveID, self.curOrigin );
self util::wait_endon( objPingDelay, "dropped", "reset" );
}
else
{
objective_position( self.objectiveID, self.curOrigin );
{wait(.05);};
}
}
}
/*
=============
give_object
Set player as holding this object
Should only be called from set_picked_up
=============
*/
function give_object( object )
{
assert( !isdefined( self.carryObject ) );
self.carryObject = object;
self thread track_carrier(object);
if ( IsDefined(object.carryWeapon) )
{
//object.carrierWeaponCurrent = self GetCurrentWeapon();
//So we don't take the weapon if the player has it in their loadout.
//object.carrierHasCarryWeaponInLoadout = self HasWeapon(object.carryWeapon);
if ( isDefined(object.carryWeaponThink) )
{
self thread [[object.carryWeaponThink]]();
}
count = 0;
while( self IsMeleeing() && count < 10 )
{
count++;
wait 0.2;
}
self GiveWeapon( object.carryWeapon );
if( self IsSwitchingWeapons() )
self util::waittill_any_timeout( 2, "weapon_change" );
self SwitchToWeaponImmediate( object.carryWeapon );
self setblockweaponpickup( object.carryWeapon, true );
self DisableWeaponCycling();
}
else if ( !object.allowWeapons )
{
self util::_disableWeapon();
self thread manual_drop_think();
}
self.disallowVehicleUsage = true;
if ( isdefined( object.visibleCarrierModel ) )
{
self weapons::force_stowed_weapon_update();
}
if ( !object.newStyle )
{
if ( isdefined( object.carryIcon ) )
{
if ( self IsSplitscreen() )
{
self.carryIcon = hud::createIcon( object.carryIcon, 35, 35 );
self.carryIcon.x = -130;
self.carryIcon.y = -90;
self.carryIcon.horzAlign = "right";
self.carryIcon.vertAlign = "bottom";
}
else
{
self.carryIcon = hud::createIcon( object.carryIcon, 50, 50 );
if ( !object.allowWeapons )
{
self.carryIcon hud::setPoint( "CENTER", "CENTER", 0, 60 );
}
else
{
self.carryIcon.x = 130;
self.carryIcon.y = -60;
self.carryIcon.horzAlign = "user_left";
self.carryIcon.vertAlign = "user_bottom";
}
}
self.carryIcon.alpha = 0.75;
self.carryIcon.hidewhileremotecontrolling = true;
self.carryIcon.hidewheninkillcam = true;
}
}
}
function move_visuals_to_base( )
{
foreach( visual in self.visuals )
{
visual.origin = visual.baseOrigin;
visual.angles = visual.baseAngles;
visual DontInterpolate();
visual show();
}
}
/*
=============
return_home
Resets a carryObject to it's default home position
=============
*/
function return_home()
{
self.isResetting = true;
// trigger is more up to date then self.curOrigin
prev_origin = self.trigger.origin;
self notify ( "reset" );
self move_visuals_to_base();
self.trigger.origin = self.trigger.baseOrigin;
self.curOrigin = self.trigger.origin;
if ( isdefined( self.onReset ) )
{
self [[self.onReset]](prev_origin);
}
self clear_carrier();
update_world_icons();
update_compass_icons();
update_objective();
self.isResetting = false;
}
/*
=============
is_object_away_from_home
=============
*/
function is_object_away_from_home()
{
if ( isdefined( self.carrier ) )
{
return true;
}
if ( distancesquared(self.trigger.origin,self.trigger.baseOrigin) > 4 )
{
return true;
}
return false;
}
/*
=============
set_position
set a carryObject to a new position
=============
*/
function set_position( origin, angles )
{
self.isResetting = true;
foreach( visual in self.visuals )
{
visual.origin = origin;
visual.angles = angles;
visual DontInterpolate();
visual show();
}
self.trigger.origin = origin;
self.curOrigin = self.trigger.origin;
self clear_carrier();
update_world_icons();
update_compass_icons();
update_objective();
self.isResetting = false;
}
function set_drop_offset( height )
{
self.dropOffset = height;
}
/*
=============
set_dropped
Sets this carry object as dropped and calculates dropped position
=============
*/
function set_dropped()
{
if ( isdefined(self.setDropped) )
{
if ( [[self.setDropped]]() )
return;
}
self.isResetting = true;
self notify ( "dropped" );
startOrigin = (0,0,0);
endOrigin = (0,0,0);
body = undefined;
if ( isdefined( self.carrier ) && self.carrier.team != "spectator" )
{
startOrigin = self.carrier.origin + (0,0,20);
endOrigin = self.carrier.origin - (0,0,2000);
body = self.carrier.body;
}
else
{
if( isdefined( self.safeOrigin ) )
{
startOrigin = self.safeOrigin + (0,0,20);
endOrigin = self.safeOrigin - (0,0,20);
}
else
{
startOrigin = self.curorigin + (0,0,20);
endOrigin = self.curorigin - (0,0,20);
}
}
trace_size = 10;
trace = PhysicsTrace( startOrigin, endOrigin, ( -trace_size, -trace_size, -trace_size ), ( trace_size, trace_size, trace_size ), self, (1 << 5) );
droppingPlayer = self.carrier;
self clear_carrier();
if ( isdefined( trace ) )
{
tempAngle = randomfloat( 360 );
dropOrigin = trace["position"] + ( 0, 0, self.dropOffset );
if ( trace["fraction"] < 1 /*&& distance( trace["position"], trace ) < 10.0*/ )
{
forward = (cos( tempAngle ), sin( tempAngle ), 0);
forward = vectornormalize( forward - VectorScale( trace["normal"], vectordot( forward, trace["normal"] ) ) );
// TU HACK: this block should not be multiplayer only. Post ship caution.
if(SessionModeIsMultiplayerGame())
{
if ( isdefined( trace["walkable"] ) )
{
if ( trace["walkable"] == false )
{
if ( self should_be_reset( trace["position"][2], startOrigin[2], true ) )
{
self thread return_home();
self.isResetting = false;
return;
}
end_reflect = (forward * 1000) + trace["position"];
reflect_trace = PhysicsTrace( trace["position"], end_reflect, ( -trace_size, -trace_size, -trace_size ), ( trace_size, trace_size, trace_size ), self, (1 << 5) );
if ( isdefined( reflect_trace ) && (reflect_trace["normal"][2] < 0.0) )
{
dropOrigin_reflect = reflect_trace["position"] + ( 0, 0, self.dropOffset );
// if ( reflect_trace["fraction"] < 1 /*&& distance( trace["position"], trace ) < 10.0*/ )
// {
// forward = (cos( tempAngle ), sin( tempAngle ), 0);
// forward = vectornormalize( forward - VectorScale( reflect_trace["normal"], vectordot( forward, reflect_trace["normal"] ) ) );
// }
if ( self should_be_reset( dropOrigin_reflect[2], trace["position"][2], true ) )
{
self thread return_home();
self.isResetting = false;
return;
}
}
}
}
}
dropAngles = vectortoangles( forward );
}
else
{
dropAngles = (0,tempAngle,0);
}
foreach( visual in self.visuals )
{
visual.origin = dropOrigin;
visual.angles = dropAngles;
visual DontInterpolate();
visual show();
}
self.trigger.origin = dropOrigin;
self.curOrigin = self.trigger.origin;
self thread pickup_timeout( trace["position"][2], startOrigin[2] );
}
else
{
self move_visuals_to_base();
self.trigger.origin = self.trigger.baseOrigin;
self.curOrigin = self.trigger.baseOrigin;
}
if ( IsDefined( self.onDrop ) )
{
self [[self.onDrop]]( droppingPlayer );
}
self update_icons_and_objective();
self.isResetting = false;
}
function update_icons_and_objective()
{
self update_compass_icons();
self update_world_icons();
self update_objective();
}
function set_carrier( carrier )
{
self.carrier = carrier;
Objective_SetPlayerUsing( self.objectiveID, carrier );
self thread update_visibility_according_to_radar();
}
/*
=============
get_carrier
Returns the carrier entity for this gameobject
=============
*/
// CP TODO - Added
function get_carrier()
{
return( self.carrier );
}
function clear_carrier()
{
if ( !isdefined( self.carrier ) )
{
return;
}
self.carrier take_object( self );
Objective_ClearPlayerUsing( self.objectiveID, self.carrier );
self.carrier = undefined;
self notify("carrier_cleared");
}
function is_touching_any_trigger( triggers, minZ, maxZ )
{
foreach( trigger in triggers )
{
if( self isTouchingSwept( trigger, minZ, maxZ ) )
return true;
}
return false;
}
function is_touching_any_trigger_key_value( value, key, minZ, maxZ )
{
return self is_touching_any_trigger( getEntArray( value, key ), minZ, maxZ );
}
function should_be_reset( minZ, maxZ, testHurtTriggers )
{
if ( self.visuals[0] is_touching_any_trigger_key_value( "minefield", "targetname", minZ, maxZ ) )
return true;
if ( ( isdefined( testHurtTriggers ) && testHurtTriggers ) && self.visuals[0] is_touching_any_trigger_key_value( "trigger_hurt", "classname", minZ, maxZ ) )
return true;
if ( self.visuals[0] is_touching_any_trigger( level.oob_triggers, minZ, maxZ ) )
return true;
elevators = GetEntArray( "script_elevator", "targetname" );
foreach( elevator in elevators )
{
assert( isdefined( elevator.occupy_volume ) );
if ( self.visuals[0] isTouchingSwept( elevator.occupy_volume, minZ, maxZ ) )
return true;
}
return false;
}
function pickup_timeout( minZ, maxZ )
{
self endon ( "pickup_object" );
self endon ( "reset" );
{wait(.05);};
if ( self should_be_reset( minZ, maxZ, true ) )
{
self thread return_home();
return;
}
if ( isdefined( self.pickupTimeoutOverride ) )
{
self thread [[self.pickupTimeoutOverride]]();
}
else if ( isdefined( self.autoResetTime ) )
{
wait ( self.autoResetTime );
if ( !isdefined( self.carrier ) )
{
self thread return_home();
}
}
}
/*
=============
take_object
Set player as dropping this object
=============
*/
function take_object( object )
{
if ( isdefined( object.visibleCarrierModel ) )
{
self weapons::detach_all_weapons();
}
shouldEnableWeapon = true;
if( isDefined(object.carryWeapon) && !IsDefined( self.player_disconnected ) )
{
shouldEnableWeapon = false;
self thread wait_take_carry_weapon( object.carryWeapon );
}
if(object.type == "carryObject")
{
if ( isdefined( self.carryIcon ) )
{
self.carryIcon hud::destroyElem();
}
self.carryObject = undefined;
}
else if(object.type == "packObject")
{
if ( isdefined( self.packIcon ) && self.packIcon.size > 0 )
{
for( i = 0; i < self.packIcon.size; i++ )
{
if(IsDefined(self.packIcon[i].script_string))
{
if(self.packIcon[i].script_string == object.packIcon)
{
elem = self.packIcon[i];
ArrayRemoveValue(self.packIcon, elem);
elem hud::destroyElem();
//adjust remaining icons
self thread adjust_remaining_packIcons();
}
}
}
}
ArrayRemoveValue(self.packObject, object);
}
if ( !isAlive( self ) || IsDefined( self.player_disconnected ) )
{
return;
}
self notify ( "drop_object" );
self.disallowVehicleUsage = false;
if ( object.triggerType == "proximity" )
{
self thread pickup_object_delay( object.trigger.origin );
}
if ( isdefined( object.visibleCarrierModel ) )
{
self weapons::force_stowed_weapon_update();
}
if ( !object.allowWeapons && shouldEnableWeapon )
{
self util::_enableWeapon();
}
}
function wait_take_carry_weapon( weapon )
{
self thread take_carry_weapon_on_death( weapon );
// Take some time away otherwise it tends to 'flash' before disappearing
wait( Max( 0, weapon.fireTime - ( 2 * .05 ) ) );
self take_carry_weapon( weapon );
}
function take_carry_weapon_on_death( weapon )
{
self endon( "take_carry_weapon" );
self waittill( "death" );
self take_carry_weapon( weapon );
}
function take_carry_weapon( weapon )
{
self notify( "take_carry_weapon" );
if ( self HasWeapon( weapon, true ) )
{
ballWeapon = GetWeapon( "ball" );
currWeapon = self GetCurrentWeapon();
if( ( weapon == ballWeapon ) && ( currWeapon === ballWeapon ) )
self killstreaks::switch_to_last_non_killstreak_weapon( undefined, true );
self setblockweaponpickup( weapon, false );
self TakeWeapon( weapon );
self EnableWeaponCycling();
if( level.gameType == "ball" )
self EnableOffhandWeapons();
}
}
/*
=============
track_carrier
Calculates and updates a safe drop origin for a carry object based on the current carriers position
=============
*/
function track_carrier(object)
{
level endon ( "game_ended" );
self endon ( "disconnect" );
self endon ( "death" );
self endon ( "drop_object" );
{wait(.05);}; // wait a frame so the carrier gets set
while ( (isdefined( object.carrier ) && object.carrier == self) && isAlive( self ) )
{
if ( self isOnGround() )
{
trace = bulletTrace( self.origin + (0,0,20), self.origin - (0,0,20), false, undefined );
if ( trace["fraction"] < 1 ) // if there is ground at the player's origin (not necessarily true just because of isOnGround)
{
object.safeOrigin = trace["position"];
}
}
{wait(.05);};
}
}
/*
=============
manual_drop_think
Allows the player to manually drop this object by pressing the fire button
Does not allow drop if the use button is pressed
=============
*/
function manual_drop_think()
{
level endon ( "game_ended" );
self endon ( "disconnect" );
self endon ( "death" );
self endon ( "drop_object" );
for( ;; )
{
while ( self attackButtonPressed() || self fragButtonPressed() || self secondaryOffhandButtonPressed() || self meleeButtonPressed() )
{
wait .05;
}
while ( !self attackButtonPressed() && !self fragButtonPressed() && !self secondaryOffhandButtonPressed() && !self meleeButtonPressed() )
{
wait .05;
}
if ( isdefined( self.carryObject ) && !self useButtonPressed() )
{
self.carryObject thread set_dropped();
}
}
}
/*
=============
create_use_object
Creates and returns a use object
In FFA gametypes, ownerTeam should be the player who owns the object
=============
*/
function create_use_object( ownerTeam, trigger, visuals, offset, objectiveName, allowInitialHoldDelay = false, allowWeaponCyclingDuringHold = false )
{
useObject = Spawn( "script_model", trigger.origin );
useObject.type = "useObject";
useObject.curOrigin = trigger.origin;
useObject.entNum = trigger getEntityNumber();
useObject.keyObject = undefined;
if ( isSubStr( trigger.classname, "use" ) )
{
useObject.triggerType = "use";
}
else
{
useObject.triggerType = "proximity";
}
// associated trigger
useObject.trigger = trigger;
useObject LinkTo( trigger );
// associated visual object
for ( index = 0; index < visuals.size; index++ )
{
visuals[index].baseOrigin = visuals[index].origin;
visuals[index].baseAngles = visuals[index].angles;
}
useObject.visuals = visuals;
useObject _set_team( ownerTeam );
if ( !isdefined( offset ) )
{
offset = (0,0,0);
}
useObject.offset3d = offset;
useObject.newStyle = false;
if ( isdefined( objectiveName ) )
{
useObject.newStyle = true;
}
else
{
objectiveName = &"";
}
// this block will completely go away when we have fully switched to the new style
{
// compass objectives
useObject.compassIcons = [];
useObject.objID = [];
if ( !useObject.newStyle )
{
foreach( team in level.teams )
{
useObject.objID[team] = get_next_obj_id();
}
if ( level.teamBased )
{
foreach( team in level.teams )
{
if( SessionModeIsCampaignGame() )
{
objective_add( useObject.objID[ "allies" ], "active", useObject.curOrigin, objectiveName );
break;
}
else
{
objective_add( useObject.objID[team], "invisible", useObject.curOrigin, objectiveName );
}
objective_team( useObject.objID[team], team );
}
}
else
{
objective_add( useObject.objID[level.nonTeamBasedTeam], "invisible", useObject.curOrigin, objectiveName );
}
}
}
useObject.objectiveID = get_next_obj_id();
// new style objective
if ( useObject.newStyle )
{
if( SessionModeIsCampaignGame() )
{
objective_add( useObject.objectiveID, "invisible", useObject, objectiveName );
useObject.keepWeapon = true;
}
else
{
objective_add( useObject.objectiveID, "invisible", useObject.curOrigin + offset, objectiveName );
}
}
if ( !useObject.newStyle )
{
if ( level.teamBased )
{
foreach( team in level.teams )
{
useObject.objPoints[team] = objpoints::create( "objpoint_" + team + "_" + useObject.entNum, useObject.curOrigin + offset, team, undefined );
useObject.objPoints[team].alpha = 0;
}
}
else
{
useObject.objPoints[level.nonTeamBasedTeam] = objpoints::create( "objpoint_allies_" + useObject.entNum, useObject.curOrigin + offset, "all", undefined );
useObject.objPoints[level.nonTeamBasedTeam].alpha = 0;
}
}
// misc
useObject.interactTeam = "none"; // "none", "any", "friendly", "enemy";
// 3d world icons
useObject.worldIcons = [];
useObject.visibleTeam = "none"; // "none", "any", "friendly", "enemy";
useObject.worldIsWaypoint = [];
useObject.worldIcons_disabled = [];
// calbacks
useObject.onUse = undefined;
useObject.onCantUse = undefined;
useObject.useText = "default";
useObject.useTime = 10000;
useObject clear_progress();
// if this is true, decay the flag back down instead of just resetting it to 0
useObject.decayProgress = false;
if ( useObject.triggerType == "proximity" )
{
useObject.numTouching["neutral"] = 0;
useObject.numTouching["none"] = 0;
useObject.touchList["neutral"] = [];
useObject.touchList["none"] = [];
foreach( team in level.teams )
{
useObject.numTouching[team] = 0;
useObject.touchList[team] = [];
}
useObject.teamUseTimes = [];
useObject.teamUseTexts = [];
useObject.useRate = 0;
useObject.claimTeam = "none";
useObject.claimPlayer = undefined;
useObject.lastClaimTeam = "none";
useObject.lastClaimTime = 0;
useObject.claimGracePeriod = 1.0;
useObject.mustMaintainClaim = false;
useObject.canContestClaim = false;
useObject thread use_object_prox_think();
}
else
{
useObject.useRate = 1;
useObject thread use_object_use_think( !allowInitialHoldDelay, !allowWeaponCyclingDuringHold );
}
return useObject;
}
/*
=============
set_key_object
function Sets this use object to require carry object(s)
=============
*/
function set_key_object( object )
{
if ( !isdefined( object ) )
{
self.keyObject = undefined;
return;
}
if ( !isdefined( self.keyObject ) )
{
self.keyObject = [];
}
self.keyObject[ self.keyObject.size ] = object;
}
/*
=============
has_key_object
function Checks if player is carrying key object(s)
=============
*/
function has_key_object( use )
{
if(!isdefined( use.keyObject ) )
{
return false;
}
for ( x = 0; x < use.keyObject.size; x++ )
{
if ( isdefined( self.carryObject ) && ( self.carryObject == use.keyObject[ x ] ) )
{
return true;
}
else if( isdefined(self.packObject) )
{
for ( i = 0; i < self.packObject.size; i++ )
{
if(self.packObject[i] == use.keyObject[x] )
{
return true;
}
}
}
}
return false;
}
/*
=============
use_object_use_think
Think function for "use" type carry objects
=============
*/
function use_object_use_think( disableInitialHoldDelay, disableWeaponCyclingDuringHold )
{
self.trigger endon( "destroyed" );
if( self.useTime > 0 && disableInitialHoldDelay )
{
// If script is going to do its own use time then ignore the code g_holdUseTime before getting the "trigger" notify
self.trigger UseTriggerIgnoreUseHoldTime();
}
while ( true )
{
self.trigger waittill ( "trigger", player );
if( level.gameEnded )
{
continue;
}
if ( !isAlive( player ) )
{
continue;
}
if ( !self can_interact_with( player ) )
{
continue;
}
if ( IsDefined( self.canInteractWithPlayer ) && ![[self.canInteractWithPlayer]]( player ) )
{
continue;
}
if ( !player isOnGround() || player IsWallRunning() )
{
continue;
}
if ( player isInVehicle() )
{
continue;
}
if ( isdefined( self.keyObject ) && !player has_key_object( self ) )
{
if ( isdefined( self.onCantUse ) )
{
self [[self.onCantUse]]( player );
}
continue;
}
result = true;
if ( self.useTime > 0 )
{
if ( isdefined( self.onBeginUse ) )
{
if( isdefined( self.classObj ) )
{
[[self.classObj]]->onBeginUse( player );
}
else
{
self [[self.onBeginUse]]( player );
}
}
team = player.pers["team"];
result = self use_hold_think( player, disableWeaponCyclingDuringHold );
if ( isdefined( self.onEndUse ) )
{
self [[self.onEndUse]]( team, player, result );
}
}
if ( !( isdefined( result ) && result ) )
{
continue;
}
if ( isdefined( self.onUse ) )
{
if( ( isdefined( self.onUse_thread ) && self.onUse_thread ) )
{
//used in co-op situations when we need simultaneous interaction
//with the use object. Example: mobile armory
self thread use_object_OnUse( player );
}
else
{
self use_object_OnUse( player );
}
}
}
}
function use_object_onUse( player )
{
level endon( "game_ended" );
self.trigger endon( "destroyed" );
if( isdefined( self.classObj ) )
{
[[self.classObj]]->onUse( player );
}
else
{
self [[self.onUse]]( player );
}
}
function get_earliest_claim_player()
{
assert( self.claimTeam != "none" );
team = self.claimTeam;
earliestPlayer = self.claimPlayer;
if ( self.touchList[team].size > 0 )
{
// find earliest touching player
earliestTime = undefined;
players = getArrayKeys( self.touchList[team] );
for ( index = 0; index < players.size; index++ )
{
touchdata = self.touchList[team][players[index]];
if ( !isdefined( earliestTime ) || touchdata.starttime < earliestTime )
{
earliestPlayer = touchdata.player;
earliestTime = touchdata.starttime;
}
}
}
return earliestPlayer;
}
/*
=============
use_object_prox_think
Think function for "proximity" type carry objects
=============
*/
function use_object_prox_think()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
self thread prox_trigger_think();
while ( true )
{
if ( self.useTime && self.curProgress >= self.useTime )
{
self clear_progress();
creditPlayer = get_earliest_claim_player();
if ( isdefined( self.onEndUse ) )
{
self [[self.onEndUse]]( self get_claim_team(), creditPlayer, isdefined( creditPlayer ) );
}
if ( isdefined( creditPlayer ) && isdefined( self.onUse ) )
{
self [[self.onUse]]( creditPlayer );
}
if ( !self.mustMaintainClaim )
{
self set_claim_team( "none" );
self.claimPlayer = undefined;
}
}
if ( self.claimTeam != "none" )
{
if ( self use_object_locked_for_team( self.claimTeam ) )
{
if ( isdefined( self.onEndUse ) )
{
self [[self.onEndUse]]( self get_claim_team(), self.claimPlayer, false );
}
self set_claim_team( "none" );
self.claimPlayer = undefined;
self clear_progress();
}
else
{
if ( self.useTime &&
( !self.mustMaintainClaim || ( self get_owner_team() != self get_claim_team() ) ) )
{
if ( self.decayProgress && !self.numTouching[self.claimTeam] )
{
if ( isdefined( self.claimPlayer ) )
{
if ( isdefined( self.onEndUse ) )
{
self [[self.onEndUse]]( self get_claim_team(), self.claimPlayer, false );
}
self.claimPlayer = undefined;
}
decayScale = 0;
if ( self.decayTime )
{
decayScale = self.useTime / self.decayTime;
}
self.curProgress -= (50 * self.useRate * decayScale);
if ( self.curProgress <= 0 )
{
self clear_progress();
}
self update_current_progress();
if ( isdefined( self.onUseUpdate ) )
{
self [[self.onUseUpdate]]( self get_claim_team(), self.curProgress / self.useTime, (50*self.useRate*decayScale) / self.useTime );
}
if ( self.curProgress == 0 )
{
self set_claim_team( "none" );
}
}
else if ( !self.numTouching[self.claimTeam] )
{
if ( isdefined( self.onEndUse ) )
{
self [[self.onEndUse]]( self get_claim_team(), self.claimPlayer, false );
}
self set_claim_team( "none" );
self.claimPlayer = undefined;
}
else
{
self.curProgress += (50 * self.useRate);
self update_current_progress();
if ( isdefined( self.onUseUpdate ) )
{
self [[self.onUseUpdate]]( self get_claim_team(), self.curProgress / self.useTime, (50*self.useRate) / self.useTime );
}
}
}
else if ( !self.mustMaintainClaim )
{
if ( isdefined( self.onUse ) )
{
self [[self.onUse]]( self.claimPlayer );
}
// onUse may toggle on mustMaintainClaim
if ( !self.mustMaintainClaim )
{
self set_claim_team( "none" );
self.claimPlayer = undefined;
}
}
else if ( !self.numTouching[self.claimTeam] )
{
if ( isdefined( self.onUnoccupied ) )
{
self [[self.onUnoccupied]]();
}
self set_claim_team( "none" );
self.claimPlayer = undefined;
}
else if ( self.canContestClaim )
{
numOther = get_num_touching_except_team( self.claimTeam );
if ( numOther > 0 )
{
if ( isdefined( self.onContested ) )
{
self [[self.onContested]]();
}
self set_claim_team( "none" );
self.claimPlayer = undefined;
}
}
}
}
else
{
if ( self.curProgress > 0 && getTime() - self.lastClaimTime > ( self.claimGracePeriod * 1000 ) )
{
self clear_progress();
}
if ( self.mustMaintainClaim && ( self get_owner_team() != "none" ) )
{
if ( !self.numTouching[self get_owner_team()] )
{
if ( isdefined( self.onUnoccupied ) )
{
self [[self.onUnoccupied]]();
}
}
else if ( self.canContestClaim && self.lastClaimTeam != "none" && self.numTouching[self.lastClaimTeam] )
{
numOther = get_num_touching_except_team( self.lastClaimTeam );
if ( numOther == 0 )
{
if ( isdefined( self.onUncontested ) )
{
self [[self.onUncontested]](self.lastClaimTeam);
}
}
}
}
}
{wait(.05);};
hostmigration::waitTillHostMigrationDone();
}
}
/*
=============
use_object_locked_for_team
Verify that a team is not locked from using an object
=============
*/
function use_object_locked_for_team( team )
{
if ( isdefined( self.teamLock ) && isdefined( level.teams[team] ) )
{
return self.teamLock[team];
}
return false;
}
/*
=============
can_claim
Determine if the player can claim
=============
*/
function can_claim( player )
{
if ( isdefined( self.carrier ) )
{
return false;
}
if ( self.canContestClaim )
{
numOther = get_num_touching_except_team( player.pers["team"] );
if ( numOther != 0 )
{
return false;
}
}
if ( !isdefined( self.keyObject ) || player has_key_object( self ) )
{
return true;
}
return false;
}
/*
=============
function prox_trigger_think ("proximity" only)
Handles setting the current claiming team and player, as well as starting threads to track players touching the trigger
=============
*/
function prox_trigger_think()
{
level endon ( "game_ended" );
self.trigger endon( "destroyed" );
entityNumber = self.entNum;
if(!isdefined(self.trigger.remote_control_player_can_trigger))self.trigger.remote_control_player_can_trigger=false;
while ( true )
{
self.trigger waittill ( "trigger", player );
if( !IsPlayer( player ) )
{
continue; //might be an AI in zombies
}
if ( player.using_map_vehicle === true )
{
if ( !isdefined( self.allow_map_vehicles ) || self.allow_map_vehicles == false )
continue;
}
// TODO: Notify the player if they are attempting to capture a locked flag
if ( !isAlive( player ) || self use_object_locked_for_team( player.pers["team"] ) )
{
continue;
}
if ( ( isdefined( player.laststand ) && player.laststand ))
{
continue;
}
if ( player.spawntime == GetTime() ) // It's possible to get the "trigger" notify from the origin of the beginning of this frame when the player was dead
{
continue; // and then have the player spawn in, changing origins later this frame and this will no longer be valid.
}
// if ( player isInVehicle() )
// {
// continue;
// }
if ( self.trigger.remote_control_player_can_trigger == false )
{
if ( player isRemoteControlling() || player util::isUsingRemote() )
{
continue;
}
}
if ( ( isdefined( player.selectingLocation ) && player.selectingLocation ) )
{
continue;
}
if ( player IsWeaponViewOnlyLinked() )
{
continue;
}
if ( self is_excluded( player ) )
{
continue;
}
if( IsDefined(self.canUseObject) && ![[self.canUseObject]](player) )
{
continue;
}
if ( self can_interact_with( player ) && self.claimTeam == "none" )
{
if ( self can_claim( player ) )
{
set_claim_team( player.pers["team"] );
self.claimPlayer = player;
relativeTeam = self get_relative_team( player.pers["team"] );
if ( isdefined( self.teamUseTimes[relativeTeam] ) )
{
self.useTime = self.teamUseTimes[relativeTeam];
// TODO we don't store the base self.useTime setting... we should.
}
if ( self.useTime && isdefined( self.onBeginUse ) )
{
self [[self.onBeginUse]]( self.claimPlayer );
}
}
else
{
if ( isdefined( self.onCantUse ) )
{
self [[self.onCantUse]]( player );
}
}
}
if ( isAlive( player ) && !isdefined( player.touchTriggers[entityNumber] ) )
{
player thread trigger_touch_think( self );
}
}
}
function is_excluded( player )
{
if ( !isdefined( self.exclusions ) )
{
return false;
}
foreach( exclusion in self.exclusions )
{
if ( exclusion istouching( player ) )
{
return true;
}
}
return false;
}
function clear_progress()
{
self.curProgress = 0;
self update_current_progress();
if ( isdefined( self.onUseClear ) )
{
self [[self.onUseClear]]( );
}
}
/*
=============
function set_claim_team ("proximity" only)
Sets this object as claimed by specified team including grace period to prevent
object reset when claiming team leave trigger for short periods of time
=============
*/
function set_claim_team( newTeam )
{
assert( newTeam != self.claimTeam );
if ( self.claimTeam == "none" && getTime() - self.lastClaimTime > ( self.claimGracePeriod * 1000 ) )
{
self clear_progress();
}
else if ( newTeam != "none" && newTeam != self.lastClaimTeam )
{
self clear_progress();
}
self.lastClaimTeam = self.claimTeam;
self.lastClaimTime = getTime();
self.claimTeam = newTeam;
self update_use_rate();
}
function get_claim_team()
{
return self.claimTeam;
}
function continue_trigger_touch_think(team,object) // self == player
{
if ( !isAlive( self ) )
{
return false;
}
if ( self.using_map_vehicle === true )
{
if ( !isdefined( object.allow_map_vehicles ) || object.allow_map_vehicles == false )
return false;
}
else
{
if ( !isdefined( object ) || !isdefined( object.trigger ) || !isdefined( object.trigger.remote_control_player_can_trigger ) || object.trigger.remote_control_player_can_trigger == false )
{
if ( self isinvehicle() )
{
return false;
}
else if ( self isRemoteControlling() || self util::isUsingRemote() )
{
return false;
}
}
else if ( self isinvehicle() && !(self isRemoteControlling() || self util::isUsingRemote()))
{
return false;
}
}
if ( self use_object_locked_for_team( team ) )
{
return false;
}
if ( ( isdefined( self.laststand ) && self.laststand ))
{
return false;
}
if ( !isdefined( object ) || !isdefined( object.trigger ) )
return false;
if( !object.trigger IsTriggerEnabled() )
return false;
if ( !self isTouching( object.trigger ) )
{
return false;
}
return true;
}
/*
=============
function trigger_touch_think ("proximity" only)
Updates use object while player is touching the trigger and updates the players visual use bar
=============
*/
function trigger_touch_think( object )
{
team = self.pers["team"];
score = 1;
object.numTouching[team] = object.numTouching[team] + score;
if ( object.useTime )
{
object update_use_rate();
}
touchName = "player" + self.clientid;
struct = spawnstruct();
struct.player = self;
struct.starttime = gettime();
object.touchList[team][touchName] = struct;
Objective_SetPlayerUsing( object.objectiveID, self );
self.touchTriggers[object.entNum] = object.trigger;
if ( isdefined( object.onTouchUse ) )
{
object [[object.onTouchUse]]( self );
}
while ( self continue_trigger_touch_think(team,object) )
{
if ( object.useTime )
{
self update_prox_bar( object, false );
}
{wait(.05);};
}
// disconnected player will skip this code
if ( isdefined( self ) )
{
if ( object.useTime )
{
self update_prox_bar( object, true );
}
self.touchTriggers[object.entNum] = undefined;
Objective_ClearPlayerUsing( object.objectiveID, self );
}
if ( level.gameEnded )
{
return;
}
object.touchList[team][touchName] = undefined;
object.numTouching[team] = object.numTouching[team] - score;
// there's a bug here because of the specialty_fastinteract, so we need to see if we're less than 1
// reason being is because the team can never have less than 1 person on the flag, so if it's less than 1 then we can say no one is on it
if( object.numTouching[team] < 1 )
{
object.numTouching[team] = 0;
}
if ( object.useTime )
{
// There was a timing bug here where a player could leave the trigger but have just completed its progress so:
// If no one is touching make sure progress is not completed in the same frame
if ( object.numTouching[team] <= 0 && ( object.curProgress >= object.useTime ) )
{
object.curProgress = object.useTime - 1;
object update_current_progress();
}
}
if ( isdefined( self ) && isdefined( object.onEndTouchUse ) )
{
object [[object.onEndTouchUse]]( self );
}
object update_use_rate();
}
/*
=============
function update_prox_bar ("proximity" only)
Updates drawing of the players use bar when using a use object
=============
*/
function update_prox_bar( object, forceRemove )
{
if ( object.newStyle )
{
return;
}
if ( !forceRemove && object.decayProgress )
{
if ( !object can_interact_with( self ) )
{
if ( isdefined( self.proxBar ) )
{
self.proxBar hud::hideElem();
}
if ( isdefined( self.proxBarText ) )
{
self.proxBarText hud::hideElem();
}
return;
}
else
{
if ( !isdefined( self.proxBar ) )
{
self.proxBar = hud::createPrimaryProgressBar();
self.proxBar.lastUseRate = -1;
}
if ( self.pers["team"] == object.claimTeam )
{
if ( self.proxBar.bar.color != ( 1, 1, 1 ) )
{
self.proxBar.bar.color = ( 1, 1, 1 );
self.proxBar.lastUseRate = -1;
}
}
else
{
if ( self.proxBar.bar.color != ( 1, 0, 0 ) )
{
self.proxBar.bar.color = ( 1, 0, 0 );
self.proxBar.lastUseRate = -1;
}
}
}
}
else if ( forceRemove || !object can_interact_with( self ) || self.pers["team"] != object.claimTeam )
{
if ( isdefined( self.proxBar ) )
{
self.proxBar hud::hideElem();
}
if ( isdefined( self.proxBarText ) )
{
self.proxBarText hud::hideElem();
}
return;
}
if ( !isdefined( self.proxBar ) )
{
self.proxBar = hud::createPrimaryProgressBar();
self.proxBar.lastUseRate = -1;
self.proxBar.lastHostMigrationState = false;
}
if ( self.proxBar.hidden )
{
self.proxBar hud::showElem();
self.proxBar.lastUseRate = -1;
self.proxBar.lastHostMigrationState = false;
}
if ( !isdefined( self.proxBarText ) )
{
self.proxBarText = hud::createPrimaryProgressBarText();
self.proxBarText setText( object.useText );
}
if ( self.proxBarText.hidden )
{
self.proxBarText hud::showElem();
self.proxBarText setText( object.useText );
}
if ( self.proxBar.lastUseRate != object.useRate || self.proxBar.lastHostMigrationState != isdefined( level.hostMigrationTimer ) )
{
if( object.curProgress > object.useTime)
{
object.curProgress = object.useTime;
}
if ( object.decayProgress && self.pers["team"] != object.claimTeam )
{
if ( object.curProgress > 0 )
{
progress = object.curProgress / object.useTime;
rate = (1000 / object.useTime) * ( object.useRate * -1 );
if ( isdefined( level.hostMigrationTimer ) )
{
rate = 0;
}
self.proxBar hud::updateBar( progress, rate );
}
}
else
{
progress = object.curProgress / object.useTime;
rate = (1000 / object.useTime) * object.useRate;
if ( isdefined( level.hostMigrationTimer ) )
{
rate = 0;
}
self.proxBar hud::updateBar( progress, rate );
}
self.proxBar.lastHostMigrationState = isdefined( level.hostMigrationTimer );
self.proxBar.lastUseRate = object.useRate;
}
}
function get_num_touching_except_team( ignoreTeam )
{
numTouching = 0;
foreach( team in level.teams )
{
if ( ignoreTeam == team )
{
continue;
}
numTouching += self.numTouching[team];
}
return numTouching;
}
/*
=============
function update_use_rate ("proximity" only)
Handles the rate a which a use objects progress bar is filled based on the number of players touching the trigger
Stops updating if an enemy is touching the trigger
=============
*/
function update_use_rate()
{
numClaimants = self.numTouching[self.claimTeam];
numOther = 0;
numOther = get_num_touching_except_team( self.claimTeam );
self.useRate = 0;
if ( self.decayProgress )
{
if ( numClaimants && !numOther )
{
self.useRate = numClaimants;
}
else if ( !numClaimants && numOther )
{
self.useRate = numOther;
}
else if ( !numClaimants && !numOther )
{
self.useRate = 0;
}
}
else
{
if ( numClaimants && !numOther )
{
self.useRate = numClaimants;
}
}
if ( isdefined( self.onUpdateUseRate ) )
{
self [[self.onUpdateUseRate]]( );
}
}
//attachUseModel()
//{
// self endon("death");
// self endon("disconnect");
// self endon("done_using");
//
// wait 1.3;
//
// self attach( "weapon_explosives", "tag_inhand", true );
// self.attachedUseModel = "weapon_explosives";
//}
/*
=============
use_hold_think
Claims the use trigger for player and displays a use bar
Returns true if the player sucessfully fills the use bar
=============
*/
function use_hold_think( player, disableWeaponCyclingDuringHold )
{
player notify ( "use_hold" );
if ( !( isdefined( self.dontLinkPlayerToTrigger ) && self.dontLinkPlayerToTrigger ) )
{
if(!SessionModeIsMultiplayerGame()) //allow 3d person rotation for linked player since the trigger doesn't get sent to client, ToDo: make this an option
{
gameobject_link = util::spawn_model( "tag_origin", player.origin, player.angles );
player PlayerLinkTo( gameobject_link);
}
else
{
player playerLinkTo( self.trigger );
player PlayerLinkedOffsetEnable();
}
}
player clientClaimTrigger( self.trigger );
player.claimTrigger = self.trigger;
useWeapon = self.useWeapon;
if ( isdefined( useWeapon ) )
{
player giveWeapon( useWeapon );
player setWeaponAmmoStock( useWeapon, 0 );
player setWeaponAmmoClip( useWeapon, 0 );
player switchToWeapon( useWeapon );
}
else if ( self.keepWeapon !== true )
{
player util::_disableWeapon();
}
self clear_progress();
self.inUse = true;
self.useRate = 0;
Objective_SetPlayerUsing( self.objectiveID, player );
player thread personal_use_bar( self );
if ( disableWeaponCyclingDuringHold )
{
player DisableWeaponCycling();
enableWeaponCyclingAfterHold = true;
}
result = use_hold_think_loop( player );
self.inUse = false;
if ( isdefined( player ) )
{
if ( enableWeaponCyclingAfterHold === true )
{
player EnableWeaponCycling();
}
Objective_ClearPlayerUsing( self.objectiveID, player );
self clear_progress();
if ( isdefined( player.attachedUseModel ) )
{
player detach( player.attachedUseModel, "tag_inhand" );
player.attachedUseModel = undefined;
}
player notify( "done_using" );
if ( isdefined( useWeapon ) )
{
player thread take_use_weapon( useWeapon );
}
player.claimTrigger = undefined;
player clientReleaseTrigger( self.trigger );
if ( isdefined( useWeapon ) )
{
player killstreaks::switch_to_last_non_killstreak_weapon();
}
else if ( self.keepWeapon !== true )
{
player util::_enableWeapon();
}
if ( !( isdefined( self.dontLinkPlayerToTrigger ) && self.dontLinkPlayerToTrigger ) )
{
player unlink();
}
if ( !isAlive( player ) )
{
player.killedInUse = true;
}
if ( level.gameEnded )
{
player WaitThenFreezePlayerControlsIfGameEndedStill();
}
}
if(isdefined(gameobject_link))
{
gameobject_link Delete();
}
return result;
}
function WaitThenFreezePlayerControlsIfGameEndedStill( wait_time = 1.0 )
{
player = self;
wait wait_time;
if ( isdefined( player ) && level.gameEnded )
{
player FreezeControls( true );
}
}
function take_use_weapon( useWeapon )
{
self endon( "use_hold" );
self endon( "death" );
self endon( "disconnect" );
level endon( "game_ended" );
while ( self getCurrentWeapon() == useWeapon && !self.throwingGrenade )
{wait(.05);};
self takeWeapon( useWeapon );
}
function continue_hold_think_loop(player, waitForWeapon, timedOut, useTime)
{
maxWaitTime = 1.5; // must be greater than the putaway timer for all weapons
if (!IsAlive(player))
{
return false;
}
if ( isdefined( player.laststand ) && player.laststand )
{
return false;
}
if ( self.curProgress >= useTime )
{
return false;
}
if ( !(player useButtonPressed()) )
{
return false;
}
if (player.throwingGrenade)
{
return false;
}
//if ( player meleeButtonPressed() )
//{
// return false;
//}
if ( player isinvehicle() )
{
return false;
}
if ( player isRemoteControlling() || player util::isUsingRemote() )
{
return false;
}
if ( ( isdefined( player.selectingLocation ) && player.selectingLocation ) )
{
return false;
}
if ( player IsWeaponViewOnlyLinked() )
{
return false;
}
if ( !(player isTouching( self.trigger ) ) )
{
// Make sure the code doesn't think we are too far
if( !isdefined( player.cursorHintEnt ) || player.cursorHintEnt != self )
{
return false;
}
}
if ( !self.useRate && !waitForWeapon )
{
return false;
}
if (waitForWeapon && timedOut > maxWaitTime)
{
return false;
}
if ( ( isdefined( self.interrupted ) && self.interrupted ) )
{
return false;
}
if( level.gameEnded )
{
return false;
}
return true;
}
function update_current_progress()
{
if ( self.useTime )
{
if ( isdefined( self.curProgress ) )
{
progress = float(self.curProgress) / self.useTime;
}
else
{
progress = 0;
}
Objective_SetProgress( self.objectiveID, math::clamp(progress,0,1) );
}
}
function use_hold_think_loop( player )
{
self endon("disabled");
useWeapon = self.useWeapon;
waitForWeapon = true;
timedOut = 0;
useTime = self.useTime;
while( self continue_hold_think_loop( player, waitForWeapon, timedOut, useTime ) )
{
timedOut += 0.05;
if ( !isdefined( useWeapon ) || player getCurrentWeapon() == useWeapon )
{
self.curProgress += (50 * self.useRate);
self update_current_progress();
self.useRate = 1;
waitForWeapon = false;
}
else
{
self.useRate = 0;
}
if ( SessionModeIsMultiplayerGame() )
{
// MP wants minimal delay always
if ( self.curProgress >= useTime )
{
return true;
}
{wait(.05);};
}
else
{
{wait(.05);};
if ( self.curProgress >= useTime )
{
util::wait_network_frame(); // Let the client see the 100% progress before clearing it after returning
return true;
}
}
hostmigration::waitTillHostMigrationDone();
}
return false;
}
/*
=============
personal_use_bar
Displays and updates a players use bar
=============
*/
function personal_use_bar( object )
{
self endon("disconnect");
if ( object.newStyle )
{
return;
}
if( isdefined( self.useBar ) )
{
return;
}
self.useBar = hud::createPrimaryProgressBar();
self.useBarText = hud::createPrimaryProgressBarText();
self.useBarText setText( object.useText );
useTime = object.useTime;
lastRate = -1;
lastHostMigrationState = isdefined( level.hostMigrationTimer );
while ( isAlive( self ) && object.inUse && !level.gameEnded )
{
if ( lastRate != object.useRate || lastHostMigrationState != isdefined( level.hostMigrationTimer ) )
{
if( object.curProgress > useTime)
{
object.curProgress = useTime;
}
if ( object.decayProgress && self.pers["team"] != object.claimTeam )
{
if ( object.curProgress > 0 )
{
progress = object.curProgress / useTime;
rate = (1000 / useTime) * ( object.useRate * -1 );
if ( isdefined( level.hostMigrationTimer ) )
{
rate = 0;
}
self.proxBar hud::updateBar( progress, rate );
}
}
else
{
progress = object.curProgress / useTime;
rate = (1000 / useTime) * object.useRate;
if ( isdefined( level.hostMigrationTimer ) )
{
rate = 0;
}
self.useBar hud::updateBar( progress, rate );
}
if ( !object.useRate )
{
self.useBar hud::hideElem();
self.useBarText hud::hideElem();
}
else
{
self.useBar hud::showElem();
self.useBarText hud::showElem();
}
}
lastRate = object.useRate;
lastHostMigrationState = isdefined( level.hostMigrationTimer );
{wait(.05);};
}
self.useBar hud::destroyElem();
self.useBarText hud::destroyElem();
}
/*
=============
update_trigger
Displays and updates a players use bar
=============
*/
function update_trigger()
{
if ( self.triggerType != "use" )
{
return;
}
if ( self.interactTeam == "none" )
{
self.trigger TriggerEnable( false );
}
else if ( ( self.interactTeam == "any" ) || !level.teamBased )
{
self.trigger TriggerEnable( true );
self.trigger setTeamForTrigger( "none" );
}
else if ( self.interactTeam == "friendly" )
{
self.trigger TriggerEnable( true );
if ( isdefined( level.teams[self.ownerTeam] ) )
{
self.trigger setTeamForTrigger( self.ownerTeam );
}
else
{
self.trigger TriggerEnable( false );
}
}
else if ( self.interactTeam == "enemy" )
{
self.trigger TriggerEnable( true );
self.trigger SetExcludeTeamForTrigger( self.ownerTeam );
}
}
function update_objective()
{
if ( !self.newStyle )
{
return;
}
objective_team( self.objectiveID, self.ownerTeam );
if ( self.visibleTeam == "any" )
{
objective_state( self.objectiveID, "active");
objective_visibleteams( self.objectiveID, level.spawnsystem.iSPAWN_TEAMMASK["all"] );
}
else if ( self.visibleTeam == "friendly" )
{
objective_state( self.objectiveID, "active");
// TODO convert level.spawnsystem.iSPAWN_TEAMMASK to be more global
objective_visibleteams( self.objectiveID, level.spawnsystem.iSPAWN_TEAMMASK[self.ownerTeam] );
}
else if ( self.visibleTeam == "enemy" )
{
objective_state( self.objectiveID, "active");
// TODO convert level.spawnsystem.iSPAWN_TEAMMASK to be more global
objective_visibleteams( self.objectiveID, level.spawnsystem.iSPAWN_TEAMMASK["all"] & ~(level.spawnsystem.iSPAWN_TEAMMASK[self.ownerTeam]) );
}
else
{
objective_state( self.objectiveID, "invisible");
objective_visibleteams( self.objectiveID, 0 );
}
if ( (self.type == "carryObject") || (self.type == "packObject"))
{
if ( isAlive( self.carrier ) )
{
objective_onentity( self.objectiveID, self.carrier );
}
else if ( IsDefined(self.objectiveOnVisuals) && self.objectiveOnVisuals )
{
objective_onentity( self.objectiveID, self.visuals[0] );
}
else
{
objective_clearentity( self.objectiveID );
}
}
}
function update_world_icons()
{
if ( self.visibleTeam == "any" )
{
update_world_icon( "friendly", true );
update_world_icon( "enemy", true );
}
else if ( self.visibleTeam == "friendly" )
{
update_world_icon( "friendly", true );
update_world_icon( "enemy", false );
}
else if ( self.visibleTeam == "enemy" )
{
update_world_icon( "friendly", false );
update_world_icon( "enemy", true );
}
else
{
update_world_icon( "friendly", false );
update_world_icon( "enemy", false );
}
}
function update_world_icon( relativeTeam, showIcon )
{
if ( self.newStyle )
{
return;
}
if ( !isdefined( self.worldIcons[relativeTeam] ) )
{
showIcon = false;
}
updateTeams = get_update_teams( relativeTeam );
for ( index = 0; index < updateTeams.size; index++ )
{
if ( !level.teamBased && updateTeams[index] != level.nonTeamBasedTeam )
{
continue;
}
opName = "objpoint_" + updateTeams[index] + "_" + self.entNum;
objPoint = objpoints::get_by_name( opName );
objPoint notify( "stop_flashing_thread" );
objPoint thread objpoints::stop_flashing();
if ( showIcon )
{
objPoint setShader( self.worldIcons[relativeTeam], level.objPointSize, level.objPointSize );
objPoint fadeOverTime( 0.05 ); // overrides old fadeOverTime setting from flashing thread
objPoint.alpha = objPoint.baseAlpha;
objPoint.isShown = true;
isWaypoint = true;
if ( isdefined(self.worldIsWaypoint[relativeTeam]) )
{
isWaypoint = self.worldIsWaypoint[relativeTeam];
}
if ( isdefined( self.compassIcons[relativeTeam] ) )
{
objPoint setWayPoint( isWaypoint, self.worldIcons[relativeTeam] );
}
else
{
objPoint setWayPoint( isWaypoint );
}
if ( (self.type == "carryObject") || (self.type == "packObject"))
{
if ( isdefined( self.carrier ) && !should_ping_object( relativeTeam ) )
{
objPoint SetTargetEnt( self.carrier );
}
else
{
objPoint ClearTargetEnt();
}
}
}
else
{
objPoint fadeOverTime( 0.05 );
objPoint.alpha = 0;
objPoint.isShown = false;
objPoint ClearTargetEnt();
}
}
}
function update_compass_icons()
{
if ( self.visibleTeam == "any" )
{
update_compass_icon( "friendly", true );
update_compass_icon( "enemy", true );
}
else if ( self.visibleTeam == "friendly" )
{
update_compass_icon( "friendly", true );
update_compass_icon( "enemy", false );
}
else if ( self.visibleTeam == "enemy" )
{
update_compass_icon( "friendly", false );
update_compass_icon( "enemy", true );
}
else
{
update_compass_icon( "friendly", false );
update_compass_icon( "enemy", false );
}
}
function update_compass_icon( relativeTeam, showIcon )
{
if ( self.newStyle )
{
return;
}
updateTeams = get_update_teams( relativeTeam );
for ( index = 0; index < updateTeams.size; index++ )
{
showIconThisTeam = showIcon;
if ( !showIconThisTeam && should_show_compass_due_to_radar( updateTeams[ index ] ) )
{
showIconThisTeam = true;
}
if ( level.teamBased )
{
objId = self.objID[updateTeams[ index ]];
}
else
{
objId = self.objID[level.nonTeamBasedTeam];
}
if ( !isdefined( self.compassIcons[relativeTeam] ) || !showIconThisTeam )
{
if( !SessionModeIsCampaignGame() )
{
objective_state( objId, "invisible" );
}
continue;
}
objective_icon( objId, self.compassIcons[relativeTeam] );
if( !SessionModeIsCampaignGame() )
{
objective_state( objId, "active" );
}
if ( (self.type == "carryObject") || (self.type == "packObject"))
{
if ( isAlive( self.carrier ) && !should_ping_object( relativeTeam ) )
{
objective_onentity( objId, self.carrier );
}
else
{
if( !SessionModeIsCampaignGame() )
{
objective_clearentity( objId );
}
objective_position( objId, self.curOrigin );
}
}
}
}
function hide_waypoint( e_player )
{
if ( isdefined( e_player ) )
{
Assert( IsPlayer( e_player ), "Passed a non-player entity into gameobjects::hide_waypoint()" );
Objective_SetInvisibleToPlayer( self.objectiveid, e_player );
}
else
{
Objective_SetInvisibleToAll( self.objectiveid );
}
}
function show_waypoint( e_player )
{
if ( isdefined( e_player ) )
{
Assert( IsPlayer( e_player ), "Passed a non-player entity into gameobjects::hide_waypoint()" );
Objective_SetVisibleToPlayer( self.objectiveid, e_player );
}
else
{
Objective_SetVisibleToAll( self.objectiveid );
}
}
function should_ping_object( relativeTeam )
{
if ( relativeTeam == "friendly" && self.objIDPingFriendly )
{
return true;
}
else if ( relativeTeam == "enemy" && self.objIDPingEnemy )
{
return true;
}
return false;
}
function get_update_teams( relativeTeam )
{
updateTeams = [];
if ( level.teamBased )
{
if ( relativeTeam == "friendly" )
{
foreach( team in level.teams )
{
if ( self is_friendly_team( team ) )
{
updateTeams[updateTeams.size] = team;
}
}
}
else if ( relativeTeam == "enemy" )
{
foreach( team in level.teams )
{
if ( !self is_friendly_team( team ) )
{
updateTeams[updateTeams.size] = team;
}
}
}
}
else
{
if ( relativeTeam == "friendly" )
{
updateTeams[updateTeams.size] = level.nonTeamBasedTeam;
}
else
{
updateTeams[updateTeams.size] = "axis";
}
}
return updateTeams;
}
function should_show_compass_due_to_radar( team )
{
showCompass = false;
if ( !isdefined( self.carrier ) )
{
return false;
}
if ( self.carrier hasPerk( "specialty_gpsjammer" ) == false )
{
if( killstreaks::HasUAV( team ) )
{
showCompass = true;
}
}
if( killstreaks::HasSatellite( team ) )
{
showCompass = true;
}
return showCompass;
}
function update_visibility_according_to_radar()
{
self endon("death");
self endon("carrier_cleared");
while(1)
{
level waittill("radar_status_change");
self update_compass_icons();
}
}
function private _set_team( team )
{
self.ownerTeam = team;
if ( team != "any" )
{
self.team = team;
foreach( visual in self.visuals )
{
visual.team = team;
}
}
}
function set_owner_team( team )
{
self _set_team( team );
self update_trigger();
self update_icons_and_objective();
}
function get_owner_team()
{
return self.ownerTeam;
}
function set_decay_time( time )
{
self.decayTime = int( time * 1000 );
}
function set_use_time( time )
{
self.useTime = int( time * 1000 );
}
function set_use_text( text )
{
self.useText = text;
}
function set_team_use_time( relativeTeam, time )
{
self.teamUseTimes[relativeTeam] = int( time * 1000 );
}
function set_team_use_text( relativeTeam, text )
{
self.teamUseTexts[relativeTeam] = text;
}
function set_use_hint_text( text )
{
self.trigger setHintString( text );
}
function allow_carry( relativeTeam )
{
allow_use( relativeTeam );
}
function allow_use( relativeTeam )
{
self.interactTeam = relativeTeam;
update_trigger();
}
function set_visible_team( relativeTeam )
{
self.visibleTeam = relativeTeam;
if ( !tweakables::getTweakableValue( "hud", "showobjicons" ) )
{
self.visibleTeam = "none";
}
update_icons_and_objective();
}
function set_model_visibility( visibility )
{
if ( visibility )
{
for ( index = 0; index < self.visuals.size; index++ )
{
self.visuals[index] show();
if ( self.visuals[index].classname == "script_brushmodel" || self.visuals[index].classname == "script_model" )
{
self.visuals[index] thread make_solid();
}
}
}
else
{
for ( index = 0; index < self.visuals.size; index++ )
{
self.visuals[index] Ghost();
if ( self.visuals[index].classname == "script_brushmodel" || self.visuals[index].classname == "script_model" )
{
self.visuals[index] notify("changing_solidness");
self.visuals[index] notsolid();
}
}
}
}
function make_solid()
{
self endon("death");
self notify("changing_solidness");
self endon("changing_solidness");
while(1)
{
for ( i = 0; i < level.players.size; i++ )
{
if ( level.players[i] isTouching( self ) )
{
break;
}
}
if ( i == level.players.size )
{
self solid();
break;
}
wait .05;
}
}
function set_carrier_visible( relativeTeam )
{
self.carrierVisible = relativeTeam;
}
function set_can_use( relativeTeam )
{
self.useTeam = relativeTeam;
}
function set_2d_icon( relativeTeam, shader )
{
self.compassIcons[relativeTeam] = shader;
update_compass_icons();
}
function set_3d_icon( relativeTeam, shader )
{
if( !IsDefined(shader) )
{
self.worldIcons_disabled[relativeTeam] = true;
}
else
{
self.worldIcons_disabled[relativeTeam] = false;
}
self.worldIcons[relativeTeam] = shader;
update_world_icons();
}
// Added
function set_3d_icon_color( relativeTeam, v_color, alpha )
{
updateTeams = get_update_teams( relativeTeam );
for ( index = 0; index < updateTeams.size; index++ )
{
if ( !level.teamBased && updateTeams[index] != level.nonTeamBasedTeam )
{
continue;
}
opName = "objpoint_" + updateTeams[index] + "_" + self.entNum;
objPoint = objpoints::get_by_name( opName );
if ( isdefined( objPoint ) )
{
if ( isdefined( v_color ) )
{
objPoint.color = v_color;
}
if ( isdefined( alpha ) )
{
objPoint.alpha = alpha;
}
}
}
}
function set_objective_color( relativeTeam, v_color, alpha = 1 ) // self = gameobject
{
if ( self.newstyle )
{
Objective_SetColor( self.objectiveID, v_color[ 0 ], v_color[ 1 ], v_color[ 2 ], alpha );
}
else
{
a_teams = get_update_teams( relativeTeam );
for ( index = 0; index < a_teams.size; index++ )
{
if ( !level.teamBased && a_teams[ index ] != level.nonTeamBasedTeam )
{
continue;
}
Objective_SetColor( self.objID[ a_teams[ index ] ], v_color[ 0 ], v_color[ 1 ], v_color[ 2 ], alpha );
}
}
}
function set_objective_entity( entity ) // self = gameobject
{
if ( self.newstyle )
{
if ( IsDefined( self.objectiveID ) )
{
Objective_OnEntity( self.objectiveID, entity );
}
}
else
{
a_teams = gameobjects::get_update_teams( self.interactTeam );
foreach ( str_team in a_teams )
{
Objective_OnEntity( self.objID[ str_team ], entity );
}
}
}
function get_objective_ids( str_team ) // self = gameobject
{
a_objective_ids = [];
if ( ( isdefined( self.newstyle ) && self.newstyle ) )
{
// newStyle objectives only use one objective index
if ( !isdefined( a_objective_ids ) ) a_objective_ids = []; else if ( !IsArray( a_objective_ids ) ) a_objective_ids = array( a_objective_ids ); a_objective_ids[a_objective_ids.size]=self.objectiveID;;
}
else
{
// oldStyle objectives use two objective indicies
a_keys = GetArrayKeys( self.objID );
for ( i = 0; i < a_keys.size; i++ )
{
if ( !IsDefined( str_team ) || ( str_team == a_keys[ i ] ) )
{
if ( !isdefined( a_objective_ids ) ) a_objective_ids = []; else if ( !IsArray( a_objective_ids ) ) a_objective_ids = array( a_objective_ids ); a_objective_ids[a_objective_ids.size]=self.objID[ a_keys[ i ] ];;
}
}
if ( !isdefined( a_objective_ids ) ) a_objective_ids = []; else if ( !IsArray( a_objective_ids ) ) a_objective_ids = array( a_objective_ids ); a_objective_ids[a_objective_ids.size]=self.objectiveID;;
}
return a_objective_ids;
}
// Added
// v_color
// hide_distance - Hide icon if player futher away than this distance
// los_check - Trace check?
// ignore_ent - (optional) ignore ent in los check
function hide_icon_distance_and_los( v_color, hide_distance, los_check, ignore_ent )
{
self endon( "disabled" );
self endon( "destroyed_complete" );
while( 1 )
{
hide = 0;
if( IsDefined(self.worldIcons_disabled["friendly"]) && (self.worldIcons_disabled["friendly"] == true) )
{
hide = 1;
}
if( !hide )
{
hide = 1;
for( i=0; i<level.players.size; i++ )
{
n_dist = ( Distance( level.players[i].origin, self.curorigin ) );
if( n_dist < hide_distance )
{
if( ( isdefined( los_check ) && los_check ) )
{
b_cansee = level.players[i] gameobject_is_player_looking_at( self.curorigin, 0.8, true, ignore_ent, 42 );
if( b_cansee )
{
hide = 0;
break;
}
}
else
{
hide = 0;
break;
}
}
}
}
if( hide )
{
self gameobjects::set_3d_icon_color( "friendly", v_color, 0 );
}
else
{
self gameobjects::set_3d_icon_color( "friendly", v_color, 1 );
}
{wait(.05);};
}
}
function gameobject_is_player_looking_at( origin, dot, do_trace, ignore_ent, ignore_trace_distance )
{
assert(IsPlayer(self), "player_looking_at must be called on a player.");
if (!isdefined(dot))
{
dot = .7;
}
if (!isdefined(do_trace))
{
do_trace = true;
}
eye = self util::get_eye();
delta_vec = AnglesToForward(VectorToAngles(origin - eye));
view_vec = AnglesToForward(self GetPlayerAngles());
new_dot = VectorDot( delta_vec, view_vec );
if ( new_dot >= dot )
{
if (do_trace)
{
trace = BulletTrace( eye, origin, false, ignore_ent );
// If no collision, we pass
if( trace[ "position" ] == origin )
{
return( true );
}
// if collision is close to the origin, the trace can pass
else if( IsDefined(ignore_trace_distance) )
{
n_mag = Distance( origin, eye );
n_dist = Distance( trace[ "position" ], eye );
n_delta = abs( n_dist - n_mag );
if( n_delta <= ignore_trace_distance )
{
return( true );
}
}
}
else
{
return true;
}
}
return false;
}
// Hides both compass and world icons
function hide_icons( team )
{
// Flag which icons should be hidden
if( (self.visibleTeam == "any") || (self.visibleTeam == "friendly") )
{
hide_friendly = true;
}
else
{
hide_friendly = false;
}
if( (self.visibleTeam == "any") || (self.visibleTeam == "enemy") )
{
hide_enemy = true;
}
else
{
hide_enemy = false;
}
// Hide icons
self.hidden_compassIcon = [];
self.hidden_worldIcon = [];
if( hide_friendly == true )
{
self.hidden_compassIcon["friendly"] = self.compassIcons["friendly"];
self.hidden_worldIcon["friendly"] = self.worldIcons["friendly"];
}
if( hide_enemy == true )
{
self.hidden_compassIcon["enemy"] = self.compassIcons["enemyy"];
self.hidden_worldIcon["enemy"] = self.worldIcons["enemy"];
}
self gameobjects::set_2d_icon( team, undefined );
self gameobjects::set_3d_icon( team, undefined );
}
// Shows hidden compass and world icons
function show_icons( team )
{
if( IsDefined(self.hidden_compassIcon[team]) )
{
self gameobjects::set_2d_icon( team, self.hidden_compassIcon[team] );
}
if( IsDefined(self.hidden_worldIcon[team]) )
{
self gameobjects::set_3d_icon( team, self.hidden_worldIcon[team] );
}
}
function set_3d_use_icon( relativeTeam, shader )
{
self.worldUseIcons[relativeTeam] = shader;
}
function set_3d_is_waypoint( relativeTeam, waypoint )
{
self.worldIsWaypoint[relativeTeam] = waypoint;
}
function set_carry_icon( shader )
{
assert(self.type == "carryObject", "for packObjects use: set_pack_icon() instead.");
self.carryIcon = shader;
}
function set_visible_carrier_model( visibleModel )
{
self.visibleCarrierModel = visibleModel;
}
function get_visible_carrier_model( )
{
return self.visibleCarrierModel;
}
function destroy_object( deleteTrigger, forceHide, b_connect_paths = false )
{
if ( !isdefined( forceHide ) )
{
forceHide = true;
}
self disable_object( forceHide );
foreach ( visual in self.visuals )
{
if ( b_connect_paths )
{
visual ConnectPaths();
}
if ( IsDefined( visual ) )
{
visual Ghost();
visual Delete();
}
}
self.trigger notify( "destroyed" );
if ( ( isdefined( deleteTrigger ) && deleteTrigger ) )
{
self.trigger Delete();
}
else
{
self.trigger TriggerEnable( true );
}
self notify( "destroyed_complete" );
}
function disable_object( forceHide )
{
self notify("disabled");
if ( (self.type == "carryObject") || (self.type == "packObject") || ( isdefined( forceHide ) && forceHide ) )
{
if ( isdefined( self.carrier ) )
{
self.carrier take_object( self );
}
for ( index = 0; index < self.visuals.size; index++ )
{
if( IsDefined(self.visuals[index]) )
{
self.visuals[index] Ghost();
}
}
}
self.trigger TriggerEnable( false );
self set_visible_team( "none" );
if( isdefined( self.objectiveid ) )
{
objective_clearentity( self.objectiveID );
}
}
function enable_object( forceShow )
{
if ( (self.type == "carryObject") || (self.type == "packObject") || ( isdefined( forceShow ) && forceShow ) )
{
for ( index = 0; index < self.visuals.size; index++ )
{
self.visuals[index] show();
}
}
self.trigger TriggerEnable( true );
self set_visible_team( "any" );
if( isdefined( self.objectiveid ) )
{
objective_onentity( self.objectiveID, self );
}
}
function get_relative_team( team )
{
if( self.ownerTeam == "any" )
{
return "friendly";
}
if ( team == self.ownerTeam )
{
return "friendly";
}
else if ( team == get_enemy_team( self.ownerTeam ) )
{
return "enemy";
}
else
{
return "neutral";
}
}
function is_friendly_team( team )
{
if ( !level.teamBased )
{
return true;
}
if ( self.ownerTeam == "any" )
{
return true;
}
if ( self.ownerTeam == team )
{
return true;
}
return false;
}
function can_interact_with( player )
{
if ( player.using_map_vehicle === true )
{
if ( !isdefined( self.allow_map_vehicles ) || self.allow_map_vehicles == false )
return false;
}
team = player.pers["team"];
switch( self.interactTeam )
{
case "none":
return false;
case "any":
return true;
case "friendly":
if ( level.teamBased )
{
if ( team == self.ownerTeam )
{
return true;
}
else
{
return false;
}
}
else
{
if ( player == self.ownerTeam )
{
return true;
}
else
{
return false;
}
}
case "enemy":
if ( level.teamBased )
{
if ( team != self.ownerTeam )
{
return true;
}
else if ( isdefined(self.decayProgress) && self.decayProgress && self.curProgress > 0 )
{
return true;
}
else
{
return false;
}
}
else
{
if ( player != self.ownerTeam )
{
return true;
}
else
{
return false;
}
}
default:
assert( 0, "invalid interactTeam" );
return false;
}
}
function is_team( team )
{
switch( team )
{
case "neutral":
case "any":
case "none":
return true;
break;
}
if ( isdefined( level.teams[team] ) )
{
return true;
}
return false;
}
function is_relative_team( relativeTeam )
{
switch( relativeTeam )
{
case "friendly":
case "enemy":
case "any":
case "none":
return true;
break;
default:
return false;
break;
}
}
function get_enemy_team( team )
{
switch( team )
{
case "neutral":
return "none";
break;
// TODO MTEAM - figure out how to determine enemy team
case "allies":
return "axis";
break;
default:
return "allies";
break;
}
}
function get_next_obj_id()
{
nextID = 0;
if ( level.releasedObjectives.size > 0 )
{
nextID = level.releasedObjectives[ level.releasedObjectives.size - 1 ];
level.releasedObjectives[ level.releasedObjectives.size - 1 ] = undefined;
}
else
{
nextID = level.numGametypeReservedObjectives;
level.numGametypeReservedObjectives++;
}
/#
//No longer an assert, but still print a warning so we know when it happens.
if( nextId >= 128 )
{
println("^3SCRIPT WARNING: Ran out of objective IDs");
}
#/
// if for some reason we ever overrun the objective array then just going
// to keep using the last objective id. This should only happen in extreme
// situations (ie. trying to make this happen).
if ( nextId > ( 128 - 1 ) )
{
nextId = ( 128 - 1 );
}
return nextID;
}
function release_obj_id( objID )
{
Assert( objID < level.numGametypeReservedObjectives );
for ( i = 0; i < level.releasedObjectives.size; i++ )
{
if ( objID == level.releasedObjectives[i] && objID == ( 128 - 1 ) )
{
return;
}
/#
Assert( objID != level.releasedObjectives[i] );
#/
}
level.releasedObjectives[ level.releasedObjectives.size ] = objID;
// reset color and alpha
Objective_SetColor( objID, 1, 1, 1, 1 );
// clear objective state
Objective_State( objID, "empty" );
}
function release_all_objective_ids() // self = gameobject
{
if ( IsDefined( self.objID ) )
{
a_keys = GetArrayKeys( self.objID );
{
for ( i = 0; i < a_keys.size; i++ )
{
release_obj_id( self.objID[ a_keys[ i ] ] );
}
}
}
if ( IsDefined( self.objectiveID ) )
{
release_obj_id( self.objectiveID );
}
}
function get_label()
{
label = self.trigger.script_label;
if ( !isdefined( label ) )
{
label = "";
return label;
}
if ( label[0] != "_" )
{
return ("_" + label);
}
return label;
}
function must_maintain_claim( enabled )
{
self.mustMaintainClaim = enabled;
}
function can_contest_claim( enabled )
{
self.canContestClaim = enabled;
}
function set_flags( flags )
{
Objective_SetGamemodeFlags( self.objectiveID, flags );
}
function get_flags( flags )
{
return Objective_GetGamemodeFlags( self.objectiveID );
}
//=====================================================================================
// create_pack_object
// dcs: 042314
// Creates and returns a pack object
// pack objects are line carry objects except you can carry more than one at a time.
//=====================================================================================
function create_pack_object( ownerTeam, trigger, visuals, offset, objectiveName )
{
if(!IsDefined(level.max_packObjects))
{
level.max_packObjects = 4;
}
Assert( level.max_packObjects < 5, "packObject system not currently designed to handle more than 4 objects" );
packObject = spawnStruct();
packObject.type = "packObject";
packObject.curOrigin = trigger.origin;
packObject.entNum = trigger getEntityNumber();
if ( isSubStr( trigger.classname, "use" ) )
{
packObject.triggerType = "use";
}
else
{
packObject.triggerType = "proximity";
}
// associated trigger
trigger.baseOrigin = trigger.origin;
packObject.trigger = trigger;
packObject.useWeapon = undefined;
if ( !isdefined( offset ) )
{
offset = (0,0,0);
}
packObject.offset3d = offset;
packObject.newStyle = false;
if ( isdefined( objectiveName ) )
{
if( !SessionModeIsCampaignGame() )
{
packObject.newStyle = true;
}
}
else
{
objectiveName = &"";
}
// associated visual objects
for ( index = 0; index < visuals.size; index++ )
{
visuals[index].baseOrigin = visuals[index].origin;
visuals[index].baseAngles = visuals[index].angles;
}
packObject.visuals = visuals;
packObject _set_team( ownerTeam );
// compass objectives
packObject.compassIcons = [];
packObject.objID =[];
// this block will completely go away when we have fully switched to the new style
if ( !packObject.newStyle )
{
foreach( team in level.teams )
{
packObject.objID[team] = get_next_obj_id();
}
}
packObject.objIDPingFriendly = false;
packObject.objIDPingEnemy = false;
level.objIDStart += 2;
// this block will completely go away when we have fully switched to the new style
if ( !packObject.newStyle )
{
if ( level.teamBased )
{
foreach ( team in level.teams )
{
objective_add( packObject.objID[team], "invisible", packObject.curOrigin );
objective_team( packObject.objID[team], team );
packObject.objPoints[team] = objpoints::create( "objpoint_" + team + "_" + packObject.entNum, packObject.curOrigin + offset, team, undefined );
packObject.objPoints[team].alpha = 0;
}
}
else
{
// TODO MTEAM - not sure why the we only use allies in dm
objective_add( packObject.objID[level.nonTeamBasedTeam], "invisible", packObject.curOrigin );
packObject.objPoints[level.nonTeamBasedTeam] = objpoints::create( "objpoint_"+ level.nonTeamBasedTeam + "_" + packObject.entNum, packObject.curOrigin + offset, "all", undefined );
packObject.objPoints[level.nonTeamBasedTeam].alpha = 0;
}
}
packObject.objectiveID = get_next_obj_id();
// new style objective
if ( packObject.newStyle )
{
objective_add( packObject.objectiveID, "invisible", packObject.curOrigin, objectiveName );
}
// carrying player
packObject.carrier = undefined;
// misc
packObject.isResetting = false;
packObject.interactTeam = "none"; // "none", "any", "friendly", "enemy";
packObject.allowWeapons = true;
packObject.visibleCarrierModel = undefined;
packObject.dropOffset = 0;
// 3d world icons
packObject.worldIcons = [];
packObject.carrierVisible = false; // packObject only
packObject.visibleTeam = "none"; // "none", "any", "friendly", "enemy";
packObject.worldIsWaypoint = [];
packObject.worldIcons_disabled = [];
packObject.packIcon = undefined;
// callbacks
packObject.setDropped = undefined;
packObject.onDrop = undefined;
packObject.onPickup = undefined;
packObject.onReset = undefined;
if ( packObject.triggerType == "use" )
{
packObject thread carry_object_use_think();
}
else
{
packObject.numTouching["neutral"] = 0;
packObject.numTouching["none"] = 0;
packObject.touchList["neutral"] = [];
packObject.touchList["none"] = [];
foreach( team in level.teams )
{
packObject.numTouching[team] = 0;
packObject.touchList[team] = [];
}
packObject.curProgress = 0;
packObject.useTime = 0;
packObject.useRate = 0;
packObject.claimTeam = "none";
packObject.claimPlayer = undefined;
packObject.lastClaimTeam = "none";
packObject.lastClaimTime = 0;
packObject.claimGracePeriod = 0;
packObject.mustMaintainClaim = false;
packObject.canContestClaim = false;
packObject.decayProgress = false;
packObject.teamUseTimes = [];
packObject.teamUseTexts = [];
packObject.onUse =&set_picked_up;
packObject thread use_object_prox_think();
//packObject thread carry_object_prox_think();
}
packObject thread update_carry_object_origin();
packObject thread update_carry_object_objective_origin();
return packObject;
}
//=====================================================================================
//give_pack_object
//Set player as holding this object
//Should only be called from set_picked_up
//=====================================================================================
function give_pack_object( object )
{
self.packObject[ self.packObject.size ] = object;
self thread track_carrier(object);
if ( !object.newStyle )
{
if ( isdefined( object.packIcon ))
{
if ( self IsSplitscreen() )
{
elem = hud::createIcon( object.packIcon, 25, 25 );
elem.y = -90;
elem.horzAlign = "right";
elem.vertAlign = "bottom";
}
else
{
elem = hud::createIcon( object.packIcon, 35, 35 );
elem.y = -110;
elem.horzAlign = "user_right";
elem.vertAlign = "user_bottom";
}
elem.x = get_packIcon_offset(self.packIcon.size);
elem.alpha = 0.75;
elem.hidewhileremotecontrolling = true;
elem.hidewheninkillcam = true;
elem.script_string = object.packIcon;
self.packIcon[ self.packIcon.size ] = elem;
}
}
}
function get_packIcon_offset(index)
{
if(!IsDefined(index))
{
index = 0;
}
if( self IsSplitscreen() )
{
size = 25;
base = -130;
}
else
{
size = 35;
base = -40;
}
int = base - (size * index);
return int;
}
function adjust_remaining_packIcons()
{
if(!IsDefined(self.packIcon))
{
return;
}
if(self.packIcon.size > 0)
{
for( i = 0; i < self.packIcon.size; i++ )
{
self.packIcon[i].x = get_packIcon_offset(i);
}
}
}
function set_pack_icon( shader )
{
assert(self.type == "packObject", "for carryObjects use: set_carry_icon() instead.");
self.packIcon = shader;
}
//=====================================================================================