2023-04-13 17:30:38 +02:00

378 lines
17 KiB
Plaintext

#using scripts\shared\callbacks_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\hostmigration_shared;
#namespace oob;
//Change the value in the _oob.csc file to match this one
//Change the value in the _oob.csc file to match this one
//Change the value in the _oob.csc file to match this one
function autoexec __init__sytem__() { system::register("out_of_bounds",&__init__,undefined,undefined); }
function __init__()
{
level.oob_triggers = [];
if(SessionModeIsMultiplayerGame())
{
level.oob_timekeep_ms = GetDvarInt( "oob_timekeep_ms", 3000 );
level.oob_timelimit_ms = GetDvarInt( "oob_timelimit_ms", 3000 );
level.oob_damage_interval_ms = GetDvarInt( "oob_damage_interval_ms", 3000 );
level.oob_damage_per_interval = GetDvarInt( "oob_damage_per_interval", 999 );
level.oob_max_distance_before_black = GetDvarInt( "oob_max_distance_before_black", 100000 );
level.oob_time_remaining_before_black = GetDvarInt( "oob_time_remaining_before_black", -1 );
}
else
{
level.oob_timelimit_ms = GetDvarInt( "oob_timelimit_ms", 6000 );
level.oob_damage_interval_ms = GetDvarInt( "oob_damage_interval_ms", 1000 );
level.oob_damage_per_interval = GetDvarInt( "oob_damage_per_interval", 5 );
level.oob_max_distance_before_black = GetDvarInt( "oob_max_distance_before_black", 400 );
level.oob_time_remaining_before_black = GetDvarInt( "oob_time_remaining_before_black", 1000 );
}
level.oob_damage_interval_sec = level.oob_damage_interval_ms / 1000;
hurt_triggers = GetEntArray( "trigger_out_of_bounds","classname" );
foreach( trigger in hurt_triggers )
{
trigger thread run_oob_trigger();
}
clientfield::register( "toplayer", "out_of_bounds", 1, 5, "int" );
}
function run_oob_trigger()
{
self.oob_players = [];
if ( !isdefined( level.oob_triggers ) ) level.oob_triggers = []; else if ( !IsArray( level.oob_triggers ) ) level.oob_triggers = array( level.oob_triggers ); level.oob_triggers[level.oob_triggers.size]=self;;
self thread waitForPlayerTouch();
self thread waitForCloneTouch();
}
function IsOutOfBounds()
{
if( !IsDefined( self.oob_start_time ) )
{
return false;
}
return self.oob_start_time != -1;
}
function IsTouchingAnyOOBTrigger()
{
triggers_to_remove = [];
result = false;
foreach( trigger in level.oob_triggers )
{
if( !isdefined( trigger ) )
{
if ( !isdefined( triggers_to_remove ) ) triggers_to_remove = []; else if ( !IsArray( triggers_to_remove ) ) triggers_to_remove = array( triggers_to_remove ); triggers_to_remove[triggers_to_remove.size]=trigger;;
continue;
}
if( !trigger IsTriggerEnabled() )
{
continue;
}
if( self IsTouching( trigger ) )
{
result = true;
break;
}
}
foreach( trigger in triggers_to_remove )
{
ArrayRemoveValue( level.oob_triggers, trigger );
}
triggers_to_remove = [];
triggers_to_remove = undefined;
return result;
}
function ResetOOBTimer( is_host_migrating, b_disable_timekeep)
{
self.oob_lastValidPlayerLoc = undefined;
self.oob_LastValidPlayerDir = undefined;
self clientfield::set_to_player( "out_of_bounds", 0 );
self util::show_hud( 1 );
self.oob_start_time = -1;
if( isdefined(level.oob_timekeep_ms))
{
if(( isdefined( b_disable_timekeep ) && b_disable_timekeep ))
{
self.last_oob_timekeep_ms = undefined;
}
else
{
self.last_oob_timekeep_ms = GetTime();
}
}
if(!( isdefined( is_host_migrating ) && is_host_migrating ))
{
self notify( "oob_host_migration_exit" );
}
self notify( "oob_exit" );
}
function waitForCloneTouch()//self = trigger
{
self endon( "death" );
while( true )
{
self waittill( "trigger", clone );
if( IsActor( clone ) && IsDefined( clone.isAiClone ) && clone.isAiClone && (!clone IsPlayingAnimScripted()) )
{
clone notify( "clone_shutdown" );
}
}
}
function GetAdjusedPlayer( Player )
{
if( isdefined(player.hijacked_vehicle_entity) && IsAlive(player.hijacked_vehicle_entity) )
{
return player.hijacked_vehicle_entity;
}
return Player;
}
function waitForPlayerTouch()//self = trigger
{
self endon( "death" );
while( true )
{
if(SessionModeIsMultiplayerGame())
{
hostmigration::waitTillHostMigrationDone();
}
self waittill( "trigger", entity );
if( !IsPlayer(entity) && !(IsVehicle(entity) && ( isdefined( entity.hijacked ) && entity.hijacked ) && isdefined(entity.owner) && IsAlive(entity)) )
continue;
if(IsPlayer(entity))
{
player = entity;
}
else
{
vehicle = entity;
player = vehicle.owner;
}
if( !(player IsOutOfBounds()) && !(player IsPlayingAnimScripted()) && !( isdefined( player.OOBDisabled ) && player.OOBDisabled ) )
{
player notify( "oob_enter" );
//Logic to pause/continue the OOB time for a certain duration if the player come out/in from it.
if( isdefined(level.oob_timekeep_ms) && isdefined(player.last_oob_timekeep_ms) && isdefined(player.last_oob_duration_ms) &&
((GetTime() - player.last_oob_timekeep_ms) < level.oob_timekeep_ms) )
{
player.oob_start_time = GetTime() - (level.oob_timelimit_ms - player.last_oob_duration_ms);
}
else
{
player.oob_start_time = GetTime();
}
player.oob_LastValidPlayerLoc = entity.origin;
player.oob_LastValidPlayerDir = VectorNormalize( entity GetVelocity() ) ;
player util::show_hud( 0 );
player thread watchForLeave( self, entity );
player thread watchForDeath( self, entity );
if(SessionModeIsMultiplayerGame())
{
player thread watchForHostMigration( self, entity );
}
}
}
}
function GetDistanceFromLastValidPlayerLoc(trigger, entity)
{
if(isdefined(self.oob_LastValidPlayerDir) && self.oob_LastValidPlayerDir != (0, 0, 0))
{
vecToPlayerLocFromOrigin = entity.origin - self.oob_lastValidPlayerLoc;
distance = VectorDot(vecToPlayerLocFromOrigin, self.oob_LastValidPlayerDir);
}
else
{
distance = Distance(entity.origin, self.oob_lastValidPlayerLoc);
}
if(distance < 0)
distance = 0;
if(distance > level.oob_max_distance_before_black)
distance = level.oob_max_distance_before_black;
return distance / level.oob_max_distance_before_black;
}
function UpdateVisualEffects( trigger, entity )
{
timeRemaining = (level.oob_timelimit_ms - (GetTime() - self.oob_start_time));
if( isdefined(level.oob_timekeep_ms) )
{
self.last_oob_duration_ms = timeRemaining;
}
oob_effectValue = 0;
if(timeRemaining <= level.oob_time_remaining_before_black)
{
if(!isdefined(self.oob_lastEffectValue))
{
self.oob_lastEffectValue = GetDistanceFromLastValidPlayerLoc(trigger, entity);
}
time_val = 1 - (timeRemaining / level.oob_time_remaining_before_black);
if(time_val > 1)
time_val = 1;
oob_effectValue = self.oob_lastEffectValue + (1 - self.oob_lastEffectValue) * time_val;
}
else
{
oob_effectValue = GetDistanceFromLastValidPlayerLoc(trigger, entity);
if(oob_effectValue > 0.9)
{
oob_effectValue = 0.9;
}
else if(oob_effectValue < 0.05)
{
oob_effectValue = 0.05;
}
self.oob_lastEffectValue = oob_effectValue;
}
oob_effectValue = ceil(oob_effectValue * 31); //5 bits 2^5 = 32 (so 31 values)
self clientfield::set_to_player( "out_of_bounds", int(oob_effectValue) );
}
function killEntity(entity)
{
entity_to_kill = entity;
if ( IsPlayer( entity ) && entity IsInVehicle() )
{
vehicle = entity GetVehicleOccupied();
if ( isdefined( vehicle ) && ( vehicle.is_oob_kill_target === true ) )
entity_to_kill = vehicle;
}
self ResetOOBTimer();
entity_to_kill DoDamage( entity_to_kill.health + 10000, entity_to_kill.origin, undefined, undefined, "none", "MOD_TRIGGER_HURT" );
}
function watchForLeave( trigger, entity )
{
self endon( "oob_exit" );
entity endon( "death" );
while( true )
{
if( entity IsTouchingAnyOOBTrigger() )
{
UpdateVisualEffects( trigger, entity );
if( (level.oob_timelimit_ms - (GetTime() - self.oob_start_time)) <= 0 )
{
if( IsPlayer(entity) )
{
entity DisableInvulnerability();
entity.ignoreme = false;
entity.laststand = undefined;
if( isdefined( entity.revivetrigger ) )
{
entity.reviveTrigger delete();
}
}
self thread killEntity( entity );
}
}
else
{
self ResetOOBTimer();
}
wait( 0.1 );
}
}
function watchForDeath( trigger, entity )
{
self endon( "disconnect" );
self endon( "oob_exit" );
util::waittill_any_ents_two( self, "death", entity, "death" );
self ResetOOBTimer();
}
function watchForHostMigration( trigger, entity )
{
self endon( "oob_host_migration_exit" );
level waittill("host_migration_begin");
self ResetOOBTimer( true, true );
}
function disablePlayerOOB( disabled )
{
if ( disabled )
{
self ResetOOBTimer();
self.OOBDisabled = true;
}
else
{
self.OOBDisabled = false;
}
}