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

496 lines
17 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\array_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\flag_shared;
#using scripts\shared\fx_shared;
#using scripts\shared\math_shared;
#using scripts\shared\statemachine_shared;
#using scripts\shared\system_shared;
#using scripts\shared\turret_shared;
#using scripts\shared\util_shared;
#using scripts\shared\vehicle_death_shared;
#using scripts\shared\vehicle_shared;
#using scripts\shared\vehicle_ai_shared;
#namespace auto_turret;
function autoexec __init__sytem__() { system::register("auto_turret",&__init__,undefined,undefined); }
function __init__()
{
vehicle::add_main_callback( "auto_turret", &turret_initialze );
}
function turret_initialze()
{
self.health = self.healthdefault;
if ( isdefined( self.scriptbundlesettings ) )
{
self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
}
else
{
self.settings = struct::get_script_bundle( "vehiclecustomsettings", "artillerysettings" );
}
sightfov = self.settings.sightfov;
if ( !isdefined( sightfov ) )
{
sightfov = 0;
}
self.fovcosine = Cos( sightfov - 0.1 );
self.fovcosinebusy = Cos( sightfov - 0.1 );
if ( self.settings.disconnectpaths === true )
{
self DisconnectPaths();
}
if ( self.settings.ignoreme === true )
{
self.ignoreme = true;
}
if ( self.settings.laseron === true )
{
self laserOn();
}
// only auto aim if it can fire. if more specific situation comes we can separate aim assist into a separate GDT field
if ( self.settings.disablefiring !== true )
{
self EnableAimAssist();
}
else
{
self.noCybercom = true;
}
self thread turret::track_lens_flare();
self.overrideVehicleDamage =&turretCallback_VehicleDamage;
self.allowFriendlyFireDamageOverride = &turretAllowFriendlyFireDamage;
//disable some cybercom abilities
if( IsDefined( level.vehicle_initializer_cb ) )
{
[[level.vehicle_initializer_cb]]( self );
}
self.ignoreFireFly = true;
self.ignoreDecoy = true;
self vehicle_ai::InitThreatBias();
defaultRole();
}
function defaultRole()
{
self vehicle_ai::init_state_machine_for_role( "default" );
self vehicle_ai::get_state_callbacks( "death" ).update_func = &state_death_update;
self vehicle_ai::get_state_callbacks( "combat" ).update_func = &state_combat_update;
self vehicle_ai::get_state_callbacks( "combat" ).exit_func = &state_combat_exit;
self vehicle_ai::get_state_callbacks( "off" ).enter_func = &state_off_enter;
self vehicle_ai::get_state_callbacks( "off" ).exit_func = &state_off_exit;
self vehicle_ai::get_state_callbacks( "emped" ).enter_func = &state_emped_enter;
self vehicle_ai::get_state_callbacks( "emped" ).update_func = &state_emped_update;
self vehicle_ai::get_state_callbacks( "emped" ).exit_func = &state_emped_exit;
self vehicle_ai::add_state( "unaware",
undefined,
&state_unaware_update,
undefined );
vehicle_ai::add_interrupt_connection( "unaware", "scripted", "enter_scripted" );
vehicle_ai::add_interrupt_connection( "unaware", "emped", "emped" );
vehicle_ai::add_interrupt_connection( "unaware", "off", "shut_off" );
vehicle_ai::add_interrupt_connection( "unaware", "driving", "enter_vehicle" );
vehicle_ai::add_interrupt_connection( "unaware", "pain", "pain" );
vehicle_ai::add_utility_connection( "unaware", "combat", &should_switch_to_combat );
vehicle_ai::add_utility_connection( "combat", "unaware", &should_switch_to_unaware );
vehicle_ai::StartInitialState( "unaware" );
}
// ----------------------------------------------
// State: death
// ----------------------------------------------
function state_death_update( params )
{
self endon( "death" );
owner = self GetVehicleOwner();
if ( isdefined( owner ) )
{
self waittill( "exit_vehicle" );
}
self SetTurretSpinning( false );
self turret::toggle_lensflare( false );
params.death_type = "default"; // only do default death for now
self thread turret_idle_sound_stop();
self playsound("veh_sentry_turret_dmg_hit");
self.turretRotScale = 2;
self rest_turret( params.resting_pitch );
self vehicle_ai::defaultstate_death_update( params );
}
// death-----------------------------------------
// ----------------------------------------------
// State: unaware
// ----------------------------------------------
function should_switch_to_unaware( current_state, to_state, connection )
{
if ( !isdefined( self.enemy ) || !self VehSeenRecently( self.enemy, 1.5 ) )
{
return 100;
}
return 0;
}
function state_unaware_update( params )
{
self endon( "death" );
self endon( "change_state" );
turret_left = true;
relativeAngle = 0;
self thread turret_idle_sound();
self playsound ("mpl_turret_startup");
self ClearTargetEntity();
while( true )
{
rotScale = self.settings.scanning_speedscale;
if ( !isdefined( rotScale ) )
{
rotScale = 0.01;
}
self.turretRotScale = rotScale;
scanning_arc = self.settings.scanning_arc;
if ( !isdefined( scanning_arc ) )
{
scanning_arc = 0;
}
limits = self GetTurretLimitsYaw();
scanning_arc = min( scanning_arc, limits[0] - 0.1 );
scanning_arc = min( scanning_arc, limits[1] - 0.1 );
if ( scanning_arc > 179 )
{
if ( self.turretontarget )
{
relativeAngle += 90;
if ( relativeAngle > 180 )
{
relativeAngle -= 360;
}
}
scanning_arc = relativeAngle;
}
else
{
if ( self.turretontarget )
{
turret_left = !turret_left;
}
if ( !turret_left )
{
scanning_arc *= -1;
}
}
scanning_pitch = self.settings.scanning_pitch;
if ( !isdefined( scanning_pitch ) )
{
scanning_pitch = 0;
}
self SetTurretTargetRelativeAngles( ( scanning_pitch, scanning_arc, 0 ) );
self vehicle_ai::evaluate_connections();
wait 0.5;
}
}
// unaware---------------------------------------
// ----------------------------------------------
// State: combat
// ----------------------------------------------
function should_switch_to_combat( current_state, to_state, connection )
{
if ( isdefined( self.enemy ) && isAlive( self.enemy ) && self VehCanSee( self.enemy ) )
{
return 100;
}
return 0;
}
function state_combat_update( params )
{
self endon( "death" );
self endon( "change_state" );
if( isdefined( self.enemy ) )
{
sentry_turret_alert_sound();
wait 0.5;
}
while( 1 )
{
if( isdefined( self.enemy ) && self VehCanSee( self.enemy ) )
{
self.turretRotScale = 1;
if ( isdefined( self.enemy ) && self HasPart( "tag_minigun_spin" ) )
{
self SetTurretTargetEnt( self.enemy );
self SetTurretSpinning( true );
wait 0.5;
}
for( i = 0; i < 3; i++ )
{
if( isdefined( self.enemy ) && IsAlive( self.enemy ) && self VehCanSee( self.enemy ) )
{
self SetTurretTargetEnt( self.enemy );
wait 0.1;
waitTime = RandomFloatRange( 0.4, 1.5 );
if ( self.settings.disablefiring !== true )
{
self sentry_turret_fire_for_time( waitTime, self.enemy );
}
else
{
wait waitTime;
}
}
if( isdefined( self.enemy ) && IsPlayer( self.enemy ) )
wait RandomFloatRange( 0.3, 0.6 );
else
wait RandomFloatRange( 0.3, 0.6 ) * 2;
}
self SetTurretSpinning( false );
if( isdefined( self.enemy ) && IsAlive( self.enemy ) && self VehCanSee( self.enemy ) )
{
if( IsPlayer( self.enemy ) )
wait RandomFloatRange( 0.5, 1.3 );
else
wait RandomFloatRange( 0.5, 1.3 ) * 2;
}
}
self vehicle_ai::evaluate_connections();
wait 0.5;
}
}
function state_combat_exit( params )
{
self SetTurretSpinning( false );
}
function sentry_turret_fire_for_time( totalFireTime, enemy )
{
self endon( "death" );
self endon( "change_state" );
sentry_turret_alert_sound();
wait .1;//giving time for the alert to play
weapon = self SeatGetWeapon( 0 );
fireTime = weapon.fireTime;
time = 0;
is_minigun = false;
if ( IsSubStr( weapon.name, "minigun" ) )
{
is_minigun = true;
self SetTurretSpinning( true );
wait 0.5;
}
while( time < totalFireTime )
{
self FireWeapon(0, enemy);
wait fireTime;
time += fireTime;
}
if( is_minigun )
{
self SetTurretSpinning( false );
}
}
// combat----------------------------------------
// ----------------------------------------------
// State: off
// ----------------------------------------------
function state_off_enter( params )
{
self vehicle_ai::defaultstate_off_enter( params );
self.turretRotScale = 0.5;
self rest_turret( params.resting_pitch );
}
function state_off_exit( params )
{
self vehicle_ai::defaultstate_off_exit( params );
self.turretRotScale = 1.0;
self playsound ("mpl_turret_startup");
}
function rest_turret( resting_pitch )
{
if ( !isdefined( resting_pitch ) )
{
resting_pitch = self.settings.resting_pitch;
}
if ( !isdefined( resting_pitch ) )
{
resting_pitch = 0;
}
angles = self GetTagAngles( "tag_turret" ) - self.angles;
self SetTurretTargetRelativeAngles( ( resting_pitch, angles[1], 0 ) );
}
// off-------------------------------------------
// ----------------------------------------------
// State: emped
// ----------------------------------------------
function state_emped_enter( params )
{
self vehicle_ai::defaultstate_emped_enter( params );
PlaySoundAtPosition( "veh_sentry_turret_emp_down", self.origin );
self.turretRotScale = 0.5;
self rest_turret( params.resting_pitch );
params.laserOn = IsLaserOn( self );
self LaserOff();
self vehicle::lights_off();
if ( !isdefined( self.abnormal_status ) )
{
self.abnormal_status = spawnStruct();
}
self.abnormal_status.emped = true;
self.abnormal_status.attacker = params.notify_param[1];
self.abnormal_status.inflictor = params.notify_param[2];
self vehicle::toggle_emp_fx( true );
}
function state_emped_update( params )
{
self endon ("death");
self endon ("change_state");
time = params.notify_param[0];
assert( isdefined( time ) );
vehicle_ai::Cooldown( "emped_timer", time );
while( !vehicle_ai::IsCooldownReady( "emped_timer" ) )
{
timeLeft = max( vehicle_ai::GetCooldownLeft( "emped_timer" ), 0.5 );
wait timeLeft;
}
self.abnormal_status.emped = false;
self vehicle::toggle_emp_fx( false );
self vehicle_ai::emp_startup_fx();
self rest_turret( 0 );
wait 1;
self vehicle_ai::evaluate_connections();
}
function state_emped_exit( params )
{
self vehicle_ai::defaultstate_emped_exit( params );
self.turretRotScale = 1.0;
self playsound ("mpl_turret_startup");
}
// emped-----------------------------------------
// ----------------------------------------------
// State: scripted
// ----------------------------------------------
function state_scripted_update( params )
{
self.turretRotScale = 1;
}
// scripted--------------------------------------
function turretAllowFriendlyFireDamage( eInflictor, eAttacker, sMeansOfDeath, weapon )
{
if ( isdefined( eAttacker ) && isdefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_EXPLOSIVE" )
{
return true;
}
return false;
}
function turretCallback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
{
iDamage = vehicle_ai::shared_callback_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
//self HidePart( "tag_shield" );
return iDamage;
}
function sentry_turret_alert_sound()
{
self playsound ("veh_turret_alert");
}
function turret_idle_sound()
{
if ( !isdefined( self.sndloop_ent ) )
{
self.sndloop_ent = Spawn("script_origin", self.origin);
self.sndloop_ent linkto (self);
self.sndloop_ent PlayLoopSound ("veh_turret_idle");
}
}
function turret_idle_sound_stop()
{
self endon( "death" );
if ( isdefined( self.sndloop_ent ) )
{
self.sndloop_ent stoploopsound( .5 );
wait( 2 );
self.sndloop_ent delete();
}
}