772 lines
25 KiB
Plaintext
772 lines
25 KiB
Plaintext
#using scripts\shared\callbacks_shared;
|
|
#using scripts\shared\clientfield_shared;
|
|
#using scripts\shared\math_shared;
|
|
#using scripts\shared\system_shared;
|
|
#using scripts\shared\util_shared;
|
|
|
|
|
|
|
|
|
|
#namespace visionset_mgr;
|
|
|
|
function autoexec __init__sytem__() { system::register("visionset_mgr",&__init__,undefined,undefined); }
|
|
|
|
function __init__()
|
|
{
|
|
level.vsmgr_initializing = true;
|
|
level.vsmgr_default_info_name = "__none"; // underscores force this into the zeroth slot
|
|
|
|
level.vsmgr = [];
|
|
|
|
level thread register_type( "visionset" );
|
|
level thread register_type( "overlay" );
|
|
|
|
callback::on_finalize_initialization(&finalize_clientfields );
|
|
level thread monitor();
|
|
callback::on_connect( &on_player_connect );
|
|
}
|
|
|
|
|
|
function register_info( type, name, version, priority, lerp_step_count, should_activate_per_player, lerp_thread, ref_count_lerp_thread )
|
|
{
|
|
assert( level.vsmgr_initializing, "All info registration in the visionset_mgr system must occur during the first frame while the system is initializing" );
|
|
|
|
lower_name = ToLower( name );
|
|
validate_info( type, lower_name, priority );
|
|
|
|
add_sorted_name_key( type, lower_name );
|
|
add_sorted_priority_key( type, lower_name, priority );
|
|
|
|
level.vsmgr[type].info[lower_name] = spawnstruct();
|
|
level.vsmgr[type].info[lower_name] add_info( type, lower_name, version, priority, lerp_step_count, should_activate_per_player, lerp_thread, ref_count_lerp_thread );
|
|
|
|
if ( level.vsmgr[type].highest_version < version )
|
|
{
|
|
level.vsmgr[type].highest_version = version;
|
|
}
|
|
}
|
|
|
|
|
|
function activate( type, name, player, opt_param_1, opt_param_2, opt_param_3 )
|
|
{
|
|
if ( level.vsmgr[type].info[name].state.should_activate_per_player )
|
|
{
|
|
activate_per_player( type, name, player, opt_param_1, opt_param_2, opt_param_3 );
|
|
return;
|
|
}
|
|
|
|
state = level.vsmgr[type].info[name].state;
|
|
|
|
if ( state.ref_count_lerp_thread )
|
|
{
|
|
state.ref_count++;
|
|
if ( 1 < state.ref_count )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( isdefined( state.lerp_thread ) )
|
|
{
|
|
state thread lerp_thread_wrapper( state.lerp_thread, opt_param_1, opt_param_2, opt_param_3 );
|
|
}
|
|
else
|
|
{
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
state set_state_active( players[player_index], 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function deactivate( type, name, player )
|
|
{
|
|
if ( level.vsmgr[type].info[name].state.should_activate_per_player )
|
|
{
|
|
deactivate_per_player( type, name, player );
|
|
return;
|
|
}
|
|
|
|
state = level.vsmgr[type].info[name].state;
|
|
|
|
if ( state.ref_count_lerp_thread )
|
|
{
|
|
state.ref_count--;
|
|
if ( 0 < state.ref_count )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
state set_state_inactive( players[player_index] );
|
|
}
|
|
|
|
state notify( "visionset_mgr_deactivate_all" );
|
|
}
|
|
|
|
|
|
function set_state_active( player, lerp )
|
|
{
|
|
player_entnum = player GetEntityNumber();
|
|
|
|
if ( !IsDefined( self.players[player_entnum] ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.players[player_entnum].active = true;
|
|
self.players[player_entnum].lerp = lerp;
|
|
}
|
|
|
|
|
|
function set_state_inactive( player )
|
|
{
|
|
player_entnum = player GetEntityNumber();
|
|
|
|
if ( !IsDefined( self.players[player_entnum] ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.players[player_entnum].active = false;
|
|
self.players[player_entnum].lerp = 0;
|
|
}
|
|
|
|
|
|
function timeout_lerp_thread( timeout, opt_param_2, opt_param_3 )
|
|
{
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
self set_state_active( players[player_index], 1 );
|
|
}
|
|
|
|
wait( timeout );
|
|
|
|
deactivate( self.type, self.name );
|
|
}
|
|
|
|
|
|
function timeout_lerp_thread_per_player( player, timeout, opt_param_2, opt_param_3 )
|
|
{
|
|
self set_state_active( player, 1 );
|
|
|
|
wait( timeout );
|
|
|
|
deactivate_per_player( self.type, self.name, player );
|
|
}
|
|
|
|
|
|
function duration_lerp_thread( duration, max_duration )
|
|
{
|
|
start_time = GetTime();
|
|
end_time = start_time + int( duration * 1000 );
|
|
|
|
if ( isdefined( max_duration ) )
|
|
{
|
|
// if a max_duration is supplied, we adjust the start time so that our lerp begins at less than 1,
|
|
// since we won't be running for the full duration that the clientside expects
|
|
start_time = end_time - int( max_duration * 1000 );
|
|
}
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_remaining_duration_lerp( start_time, end_time );
|
|
|
|
if ( 0 >= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
self set_state_active( players[player_index], lerp );
|
|
}
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
deactivate( self.type, self.name );
|
|
}
|
|
|
|
|
|
function duration_lerp_thread_per_player( player, duration, max_duration )
|
|
{
|
|
start_time = GetTime();
|
|
end_time = start_time + int( duration * 1000 );
|
|
|
|
if ( isdefined( max_duration ) )
|
|
{
|
|
// if a max_duration is supplied, we adjust the start time so that our lerp begins at less than 1,
|
|
// since we won't be running for the full duration that the clientside expects
|
|
start_time = end_time - int( max_duration * 1000 );
|
|
}
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_remaining_duration_lerp( start_time, end_time );
|
|
|
|
if ( 0 >= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
self set_state_active( player, lerp );
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
deactivate_per_player( self.type, self.name, player );
|
|
}
|
|
|
|
|
|
function ramp_in_thread_per_player( player, duration )
|
|
{
|
|
start_time = GetTime();
|
|
end_time = start_time + int( duration * 1000 );
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_ramp_in_lerp( start_time, end_time );
|
|
|
|
if ( 1 <= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
self set_state_active( player, lerp );
|
|
|
|
{wait(.05);};
|
|
}
|
|
}
|
|
|
|
|
|
function ramp_in_out_thread_hold_func()
|
|
{
|
|
level endon( "kill_ramp_in_out_thread_hold_func" );
|
|
|
|
while ( true )
|
|
{
|
|
for ( player_index = 0; player_index < level.players.size; player_index++ )
|
|
{
|
|
self visionset_mgr::set_state_active( level.players[player_index], 1 );
|
|
}
|
|
|
|
{wait(.05);};
|
|
}
|
|
}
|
|
|
|
|
|
function ramp_in_out_thread( ramp_in, full_period, ramp_out )
|
|
{
|
|
start_time = GetTime();
|
|
end_time = start_time + int( ramp_in * 1000 );
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_ramp_in_lerp( start_time, end_time );
|
|
|
|
if ( 1 <= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
self set_state_active( players[player_index], lerp );
|
|
}
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
self thread ramp_in_out_thread_hold_func();
|
|
if ( IsFunctionPtr( full_period ) )
|
|
{
|
|
self [[full_period]]();
|
|
}
|
|
else
|
|
{
|
|
wait( full_period );
|
|
}
|
|
level notify( "kill_ramp_in_out_thread_hold_func" );
|
|
|
|
start_time = GetTime();
|
|
end_time = start_time + int( ramp_out * 1000 );
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_remaining_duration_lerp( start_time, end_time );
|
|
|
|
if ( 0 >= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
players = GetPlayers();
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
self set_state_active( players[player_index], lerp );
|
|
}
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
deactivate( self.type, self.name );
|
|
}
|
|
|
|
function ramp_in_out_thread_per_player_internal( player, ramp_in, full_period, ramp_out )
|
|
{
|
|
start_time = GetTime();
|
|
end_time = start_time + int( ramp_in * 1000 );
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_ramp_in_lerp( start_time, end_time );
|
|
|
|
if ( 1 <= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
self set_state_active( player, lerp );
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
self set_state_active( player, lerp );
|
|
|
|
if ( IsFunctionPtr( full_period ) )
|
|
{
|
|
player [[full_period]]();
|
|
}
|
|
else
|
|
{
|
|
wait( full_period );
|
|
}
|
|
|
|
start_time = GetTime();
|
|
end_time = start_time + int( ramp_out * 1000 );
|
|
|
|
while ( true )
|
|
{
|
|
lerp = calc_remaining_duration_lerp( start_time, end_time );
|
|
|
|
if ( 0 >= lerp )
|
|
{
|
|
break;
|
|
}
|
|
|
|
self set_state_active( player, lerp );
|
|
|
|
{wait(.05);};
|
|
}
|
|
|
|
deactivate_per_player( self.type, self.name, player );
|
|
}
|
|
|
|
function ramp_in_out_thread_watch_player_shutdown( player )
|
|
{
|
|
player notify( "ramp_in_out_thread_watch_player_shutdown" );
|
|
player endon( "ramp_in_out_thread_watch_player_shutdown" );
|
|
player endon( "disconnect" );
|
|
player waittill( "death" );
|
|
|
|
if ( player IsRemoteControlling() == false )
|
|
deactivate_per_player( self.type, self.name, player );
|
|
}
|
|
|
|
function ramp_in_out_thread_per_player_death_shutdown( player, ramp_in, full_period, ramp_out )
|
|
{
|
|
player endon ( "death" );
|
|
thread ramp_in_out_thread_watch_player_shutdown( player );
|
|
ramp_in_out_thread_per_player_internal( player, ramp_in, full_period, ramp_out );
|
|
}
|
|
|
|
function ramp_in_out_thread_per_player( player, ramp_in, full_period, ramp_out )
|
|
{
|
|
ramp_in_out_thread_per_player_internal( player, ramp_in, full_period, ramp_out );
|
|
}
|
|
|
|
function register_type( type )
|
|
{
|
|
level.vsmgr[type] = spawnstruct();
|
|
|
|
level.vsmgr[type].type = type;
|
|
level.vsmgr[type].in_use = false; // true if items other than the default value has been registered
|
|
level.vsmgr[type].highest_version = 0;
|
|
level.vsmgr[type].cf_slot_name = type + "_slot";
|
|
level.vsmgr[type].cf_lerp_name = type + "_lerp";
|
|
level.vsmgr[type].info = [];
|
|
level.vsmgr[type].sorted_name_keys = [];
|
|
level.vsmgr[type].sorted_prio_keys = [];
|
|
|
|
register_info( type, level.vsmgr_default_info_name, 1, 0, 1, false, undefined );
|
|
}
|
|
|
|
|
|
function finalize_clientfields()
|
|
{
|
|
typeKeys = GetArrayKeys( level.vsmgr );
|
|
for ( type_index = 0; type_index < typeKeys.size; type_index++ )
|
|
{
|
|
level.vsmgr[typeKeys[type_index]] thread finalize_type_clientfields();
|
|
}
|
|
|
|
level.vsmgr_initializing = false; // registering new infos is not allowed after this point
|
|
}
|
|
|
|
|
|
function finalize_type_clientfields()
|
|
{
|
|
/#println( "visionset_mgr [" + self.type + "] server registrations:" );#/
|
|
|
|
if ( 1 >= self.info.size ) // if only the default info has been registered, don't spend bits on this type
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.in_use = true;
|
|
self.cf_slot_bit_count = GetMinBitCountForNum( self.info.size - 1 );
|
|
self.cf_lerp_bit_count = self.info[self.sorted_name_keys[0]].lerp_bit_count;
|
|
|
|
for ( i = 0; i < self.sorted_name_keys.size; i++ )
|
|
{
|
|
self.info[self.sorted_name_keys[i]].slot_index = i;
|
|
|
|
if ( self.info[self.sorted_name_keys[i]].lerp_bit_count > self.cf_lerp_bit_count )
|
|
{
|
|
self.cf_lerp_bit_count = self.info[self.sorted_name_keys[i]].lerp_bit_count;
|
|
}
|
|
|
|
/#println( " name: " + self.info[self.sorted_name_keys[i]].name + ", version: " + self.info[self.sorted_name_keys[i]].version + ", lerp_step_count: " + self.info[self.sorted_name_keys[i]].lerp_step_count + "" );#/
|
|
}
|
|
|
|
clientfield::register( "toplayer", self.cf_slot_name, self.highest_version, self.cf_slot_bit_count, "int" );
|
|
|
|
// don't spend a clientfield if all slots are just on/off
|
|
if ( 1 < self.cf_lerp_bit_count )
|
|
{
|
|
clientfield::register( "toplayer", self.cf_lerp_name, self.highest_version, self.cf_lerp_bit_count, "float" );
|
|
}
|
|
}
|
|
|
|
|
|
function validate_info( type, name, priority )
|
|
{
|
|
keys = GetArrayKeys( level.vsmgr );
|
|
for ( i = 0; i < keys.size; i++ )
|
|
{
|
|
if ( type == keys[i] )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
assert( i < keys.size, "In visionset_mgr, type '" + type + "'is unknown" );
|
|
|
|
keys = GetArrayKeys( level.vsmgr[type].info );
|
|
for ( i = 0; i < keys.size; i++ )
|
|
{
|
|
assert( level.vsmgr[type].info[keys[i]].name != name, "In visionset_mgr of type '" + type + "': name '" + name + "' has previously been registered" );
|
|
assert( level.vsmgr[type].info[keys[i]].priority != priority, "In visionset_mgr of type '" + type + "': priority '" + priority + "' requested for name '" + name + "' has previously been registered under name '" + level.vsmgr[type].info[keys[i]].name + "'");
|
|
}
|
|
}
|
|
|
|
|
|
function add_sorted_name_key( type, name )
|
|
{
|
|
for ( i = 0; i < level.vsmgr[type].sorted_name_keys.size; i++ )
|
|
{
|
|
if ( name < level.vsmgr[type].sorted_name_keys[i] )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
ArrayInsert( level.vsmgr[type].sorted_name_keys, name, i );
|
|
}
|
|
|
|
|
|
function add_sorted_priority_key( type, name, priority )
|
|
{
|
|
for ( i = 0; i < level.vsmgr[type].sorted_prio_keys.size; i++ )
|
|
{
|
|
if ( priority > level.vsmgr[type].info[level.vsmgr[type].sorted_prio_keys[i]].priority )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
ArrayInsert( level.vsmgr[type].sorted_prio_keys, name, i );
|
|
}
|
|
|
|
|
|
function add_info( type, name, version, priority, lerp_step_count, should_activate_per_player, lerp_thread, ref_count_lerp_thread )
|
|
{
|
|
self.type = type;
|
|
self.name = name;
|
|
self.version = version;
|
|
self.priority = priority;
|
|
self.lerp_step_count = lerp_step_count;
|
|
self.lerp_bit_count = GetMinBitCountForNum( lerp_step_count );
|
|
|
|
if ( !isdefined( ref_count_lerp_thread ) )
|
|
{
|
|
ref_count_lerp_thread = false;
|
|
}
|
|
|
|
self.state = spawnstruct();
|
|
self.state.type = type;
|
|
self.state.name = name;
|
|
self.state.should_activate_per_player = should_activate_per_player;
|
|
self.state.lerp_thread = lerp_thread;
|
|
self.state.ref_count_lerp_thread = ref_count_lerp_thread;
|
|
self.state.players = [];
|
|
|
|
if ( ref_count_lerp_thread && !should_activate_per_player )
|
|
{
|
|
self.state.ref_count = 0;
|
|
}
|
|
}
|
|
|
|
function on_player_connect()
|
|
{
|
|
self player_setup();
|
|
}
|
|
|
|
|
|
function player_setup()
|
|
{
|
|
self.vsmgr_player_entnum = self GetEntityNumber();
|
|
|
|
typeKeys = GetArrayKeys( level.vsmgr );
|
|
for ( type_index = 0; type_index < typeKeys.size; type_index++ )
|
|
{
|
|
type = typeKeys[type_index];
|
|
|
|
if ( !level.vsmgr[type].in_use )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for ( name_index = 0; name_index < level.vsmgr[type].sorted_name_keys.size; name_index++ )
|
|
{
|
|
name_key = level.vsmgr[type].sorted_name_keys[name_index];
|
|
|
|
level.vsmgr[type].info[name_key].state.players[self.vsmgr_player_entnum] = SpawnStruct();
|
|
|
|
level.vsmgr[type].info[name_key].state.players[self.vsmgr_player_entnum].active = false;
|
|
level.vsmgr[type].info[name_key].state.players[self.vsmgr_player_entnum].lerp = 0;
|
|
|
|
if ( level.vsmgr[type].info[name_key].state.ref_count_lerp_thread && level.vsmgr[type].info[name_key].state.should_activate_per_player )
|
|
{
|
|
level.vsmgr[type].info[name_key].state.players[self.vsmgr_player_entnum].ref_count = 0;
|
|
}
|
|
}
|
|
|
|
level.vsmgr[type].info[level.vsmgr_default_info_name].state set_state_active( self, 1 );
|
|
}
|
|
}
|
|
|
|
function player_shutdown()
|
|
{
|
|
self.vsmgr_player_entnum = self GetEntityNumber();
|
|
|
|
typeKeys = GetArrayKeys( level.vsmgr );
|
|
for ( type_index = 0; type_index < typeKeys.size; type_index++ )
|
|
{
|
|
type = typeKeys[type_index];
|
|
|
|
if ( !level.vsmgr[type].in_use )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for ( name_index = 0; name_index < level.vsmgr[type].sorted_name_keys.size; name_index++ )
|
|
{
|
|
name_key = level.vsmgr[type].sorted_name_keys[name_index];
|
|
|
|
deactivate_per_player( type, name_key, self );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function monitor()
|
|
{
|
|
while ( level.vsmgr_initializing )
|
|
{
|
|
{wait(.05);};
|
|
}
|
|
|
|
typeKeys = GetArrayKeys( level.vsmgr );
|
|
|
|
while ( true )
|
|
{
|
|
{wait(.05);};
|
|
waittillframeend;
|
|
|
|
players = GetPlayers();
|
|
|
|
for ( type_index = 0; type_index < typeKeys.size; type_index++ )
|
|
{
|
|
type = typeKeys[type_index];
|
|
|
|
if ( !level.vsmgr[type].in_use )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for ( player_index = 0; player_index < players.size; player_index++ )
|
|
{
|
|
if ( !IsDefined( players[player_index].vsmgr_player_entnum ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
update_clientfields( players[player_index], level.vsmgr[type] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function get_first_active_name( type_struct )
|
|
{
|
|
//player_entnum = player GetEntityNumber();
|
|
|
|
size = type_struct.sorted_prio_keys.size;
|
|
|
|
for ( prio_index = 0; prio_index < size; prio_index++ )
|
|
{
|
|
prio_key = type_struct.sorted_prio_keys[prio_index];
|
|
|
|
if ( type_struct.info[prio_key].state.players[self.vsmgr_player_entnum].active )
|
|
{
|
|
return prio_key;
|
|
}
|
|
}
|
|
|
|
return level.vsmgr_default_info_name;
|
|
}
|
|
|
|
|
|
function update_clientfields( player, type_struct )
|
|
{
|
|
//player_entnum = player GetEntityNumber();
|
|
|
|
name = player get_first_active_name( type_struct );
|
|
|
|
player clientfield::set_to_player( type_struct.cf_slot_name, type_struct.info[name].slot_index );
|
|
|
|
if ( 1 < type_struct.cf_lerp_bit_count )
|
|
{
|
|
player clientfield::set_to_player( type_struct.cf_lerp_name, type_struct.info[name].state.players[player.vsmgr_player_entnum].lerp );
|
|
}
|
|
}
|
|
|
|
|
|
function lerp_thread_wrapper( func, opt_param_1, opt_param_2, opt_param_3 )
|
|
{
|
|
self notify( "visionset_mgr_deactivate_all" );
|
|
self endon( "visionset_mgr_deactivate_all" );
|
|
|
|
self [[func]]( opt_param_1, opt_param_2, opt_param_3 );
|
|
}
|
|
|
|
|
|
function lerp_thread_per_player_wrapper( func, player, opt_param_1, opt_param_2, opt_param_3 )
|
|
{
|
|
player_entnum = player GetEntityNumber();
|
|
self.players[player_entnum] notify( "visionset_mgr_deactivate" );
|
|
self.players[player_entnum] endon( "visionset_mgr_deactivate" );
|
|
player endon( "disconnect" );
|
|
|
|
self [[func]]( player, opt_param_1, opt_param_2, opt_param_3 );
|
|
}
|
|
|
|
|
|
function activate_per_player( type, name, player, opt_param_1, opt_param_2, opt_param_3 )
|
|
{
|
|
player_entnum = player GetEntityNumber();
|
|
state = level.vsmgr[type].info[name].state;
|
|
|
|
if ( state.ref_count_lerp_thread )
|
|
{
|
|
state.players[player_entnum].ref_count++;
|
|
if ( 1 < state.players[player_entnum].ref_count )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( isdefined( state.lerp_thread ) )
|
|
{
|
|
state thread lerp_thread_per_player_wrapper( state.lerp_thread, player, opt_param_1, opt_param_2, opt_param_3 );
|
|
}
|
|
else
|
|
{
|
|
state set_state_active( player, 1 );
|
|
}
|
|
}
|
|
|
|
|
|
function deactivate_per_player( type, name, player )
|
|
{
|
|
player_entnum = player GetEntityNumber();
|
|
|
|
state = level.vsmgr[type].info[name].state;
|
|
|
|
if ( state.ref_count_lerp_thread )
|
|
{
|
|
state.players[player_entnum].ref_count--;
|
|
if ( 0 < state.players[player_entnum].ref_count )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
state set_state_inactive( player );
|
|
|
|
state.players[player_entnum] notify( "visionset_mgr_deactivate" );
|
|
}
|
|
|
|
|
|
function calc_ramp_in_lerp( start_time, end_time )
|
|
{
|
|
if( 0 >= ( end_time - start_time ) )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
now = GetTime();
|
|
|
|
frac = float(now - start_time) / float(end_time - start_time);
|
|
|
|
return math::clamp( frac, 0, 1 );
|
|
}
|
|
|
|
|
|
function calc_remaining_duration_lerp( start_time, end_time )
|
|
{
|
|
if( 0 >= ( end_time - start_time ) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
now = GetTime();
|
|
|
|
frac = float(end_time - now) / float(end_time - start_time);
|
|
|
|
return math::clamp( frac, 0, 1 );
|
|
}
|
|
|
|
|