4530 lines
98 KiB
Plaintext
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;
|
|
}
|
|
//=====================================================================================
|
|
|