init
This commit is contained in:
921 files changed
+337975
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,27 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\math_shared;
|
||||
#using scripts\shared\statemachine_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\vehicle_death_shared;
|
||||
#using scripts\shared\vehicle_ai_shared;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#namespace attack_drone;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("attack_drone",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
#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;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\filter_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\archetype_shared\archetype_shared;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
#namespace counteruav;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("counteruav",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\math_shared;
|
||||
#using scripts\shared\statemachine_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\array_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\vehicle_ai_shared;
|
||||
#using scripts\shared\vehicle_death_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#using_animtree( "generic" );
|
||||
|
||||
#namespace counteruav;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("counteruav",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
vehicle::add_main_callback( "counteruav", &counteruav_initialize );
|
||||
}
|
||||
|
||||
function counteruav_initialize()
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
|
||||
Target_Set( self, ( 0, 0, 0 ) );
|
||||
|
||||
self.health = self.healthdefault;
|
||||
|
||||
self vehicle::friendly_fire_shield();
|
||||
|
||||
//self EnableAimAssist();
|
||||
//self SetNearGoalNotifyDist( 40 );
|
||||
|
||||
self SetVehicleAvoidance( true ); // this is ORCA avoidance
|
||||
|
||||
self SetHoverParams( 50.0, 100.0, 100.0 );
|
||||
|
||||
self.vehAirCraftCollisionEnabled = true;
|
||||
|
||||
assert( isdefined( self.scriptbundlesettings ) );
|
||||
|
||||
self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
self.goalRadius = 999999;
|
||||
self.goalHeight = 999999;
|
||||
self SetGoal( self.origin, false, self.goalRadius, self.goalHeight );
|
||||
|
||||
self.overrideVehicleDamage = &drone_callback_damage;
|
||||
|
||||
// self thread vehicle_ai::nudge_collision(); // do we need this?
|
||||
|
||||
//disable some cybercom abilities
|
||||
if( IsDefined( level.vehicle_initializer_cb ) )
|
||||
{
|
||||
[[level.vehicle_initializer_cb]]( self );
|
||||
}
|
||||
}
|
||||
|
||||
function drone_callback_damage( 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 );
|
||||
|
||||
return iDamage;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,669 @@
|
||||
Line truncated
|
||||
|
||||
#using scripts\shared\audio_shared;
|
||||
|
||||
#namespace driving_fx;
|
||||
|
||||
class GroundFx
|
||||
{
|
||||
var id ;
|
||||
var handle;
|
||||
|
||||
constructor()
|
||||
{
|
||||
id = undefined;
|
||||
handle = -1;
|
||||
}
|
||||
|
||||
destructor()
|
||||
{
|
||||
}
|
||||
|
||||
function play( localClientNum, vehicle, fx_id, fx_tag )
|
||||
{
|
||||
if ( !isdefined(fx_id ) )
|
||||
{
|
||||
//stop( localClientNum );
|
||||
|
||||
if ( handle > 0 )
|
||||
{
|
||||
StopFx( localClientNum, handle );
|
||||
}
|
||||
|
||||
id = undefined;
|
||||
handle = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isdefined( id ) )
|
||||
{
|
||||
id = fx_id;
|
||||
handle = PlayFxOnTag( localClientNum, id, vehicle, fx_tag );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !isdefined( id ) || id != fx_id )
|
||||
{
|
||||
if ( handle > 0 )
|
||||
{
|
||||
StopFx( localClientNum, handle );
|
||||
}
|
||||
|
||||
id = fx_id;
|
||||
handle = PlayFxOnTag( localClientNum, id, vehicle, fx_tag );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stop( localClientNum )
|
||||
{
|
||||
if ( handle > 0 )
|
||||
{
|
||||
StopFx( localClientNum, handle );
|
||||
}
|
||||
|
||||
id = undefined;
|
||||
handle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleWheelFx
|
||||
{
|
||||
var name;
|
||||
var tag_name;
|
||||
var ground_fx;
|
||||
|
||||
constructor()
|
||||
{
|
||||
name = "";
|
||||
tag_name = "";
|
||||
}
|
||||
|
||||
destructor()
|
||||
{
|
||||
}
|
||||
|
||||
function init( _name, _tag_name )
|
||||
{
|
||||
name = _name;
|
||||
tag_name = _tag_name;
|
||||
|
||||
ground_fx = [];
|
||||
ground_fx[ "skid" ] = new GroundFx();
|
||||
ground_fx[ "tread" ] = new GroundFx();
|
||||
|
||||
ground_fx[ "tread" ].id = "";
|
||||
ground_fx[ "tread" ].handle = -1;
|
||||
}
|
||||
|
||||
function update( localClientNum, vehicle, speed_fraction )
|
||||
{
|
||||
if ( vehicle.vehicleclass === "boat" )
|
||||
{
|
||||
peelingout = false;
|
||||
sliding = false;
|
||||
trace = bullettrace( vehicle.origin + ( 0, 0, 60 ), vehicle.origin - ( 0, 0, 200 ), false, vehicle );
|
||||
|
||||
if( trace["fraction"] < 1.0 )
|
||||
{
|
||||
surface = trace["surfacetype"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[ ground_fx[ "skid" ] ]]->stop( localClientNum );
|
||||
[[ ground_fx[ "tread" ] ]]->stop( localClientNum );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are not colliding stop all fx
|
||||
if ( !vehicle IsWheelColliding( name ) )
|
||||
{
|
||||
[[ ground_fx[ "skid" ] ]]->stop( localClientNum );
|
||||
[[ ground_fx[ "tread" ] ]]->stop( localClientNum );
|
||||
return;
|
||||
}
|
||||
|
||||
peelingout = vehicle IsWheelPeelingOut( name );
|
||||
sliding = vehicle IsWheelSliding( name );
|
||||
surface = vehicle GetWheelSurface( name );
|
||||
}
|
||||
|
||||
origin = vehicle GetTagOrigin( tag_name ) + ( 0, 0, 1 );
|
||||
angles = vehicle GetTagAngles( tag_name );
|
||||
|
||||
fwd = AnglesToForward( angles );
|
||||
right = AnglesToRight( angles );
|
||||
|
||||
rumble = false;
|
||||
|
||||
if ( peelingout )
|
||||
{
|
||||
peel_fx = vehicle driving_fx::get_wheel_fx( "peel", surface );
|
||||
|
||||
if ( isdefined( peel_fx ) )
|
||||
{
|
||||
PlayFx( localClientNum, peel_fx, origin, fwd * -1 );
|
||||
rumble = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( sliding )
|
||||
{
|
||||
skid_fx = vehicle driving_fx::get_wheel_fx( "skid", surface );
|
||||
|
||||
[[ ground_fx[ "skid" ] ]]->play( localClientNum, vehicle, skid_fx, tag_name );
|
||||
|
||||
vehicle.skidding = true;
|
||||
rumble = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
[[ ground_fx[ "skid" ] ]]->stop( localClientNum );
|
||||
}
|
||||
|
||||
if ( speed_fraction > 0.1 )
|
||||
{
|
||||
tread_fx = vehicle driving_fx::get_wheel_fx( "tread", surface );
|
||||
|
||||
[[ ground_fx[ "tread" ] ]]->play( localClientNum, vehicle, tread_fx, tag_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
[[ ground_fx[ "tread" ] ]]->stop( localClientNum );
|
||||
}
|
||||
|
||||
if ( rumble )
|
||||
{
|
||||
if ( vehicle IsLocalClientDriver( localClientNum ) )
|
||||
{
|
||||
player = GetLocalPlayer( localClientNum );
|
||||
player PlayRumbleOnEntity( localClientNum, "reload_small" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class vehicle_camera_fx
|
||||
{
|
||||
var quake_time_min;
|
||||
var quake_time_max;
|
||||
var quake_strength_min;
|
||||
var quake_strength_max;
|
||||
var rumble_name;
|
||||
|
||||
constructor()
|
||||
{
|
||||
quake_time_min = 0.5;
|
||||
quake_time_max = 1.0;
|
||||
quake_strength_min = 0.1;
|
||||
quake_strength_max = 0.115;
|
||||
rumble_name = "";
|
||||
}
|
||||
|
||||
destructor()
|
||||
{
|
||||
}
|
||||
|
||||
function init( t_min, t_max, s_min, s_max, rumble = "" )
|
||||
{
|
||||
quake_time_min = t_min;
|
||||
quake_time_max = t_max;
|
||||
quake_strength_min = s_min;
|
||||
quake_strength_max = s_max;
|
||||
rumble_name = ( rumble != "" ? rumble : rumble_name );
|
||||
}
|
||||
|
||||
function update( localClientNum, vehicle, speed_fraction )
|
||||
{
|
||||
if ( vehicle IsLocalClientDriver( localClientNum ) )
|
||||
{
|
||||
player = getlocalplayer( localClientNum );
|
||||
|
||||
if ( speed_fraction > 0 )
|
||||
{
|
||||
strength = RandomFloatRange( quake_strength_min, quake_strength_max ) * speed_fraction;
|
||||
time = RandomFloatRange( quake_time_min, quake_time_max );
|
||||
|
||||
player Earthquake( strength, time, player.origin, 500 );
|
||||
|
||||
if ( rumble_name != "" && speed_fraction > 0.5 )
|
||||
{
|
||||
if ( RandomInt( 100 ) < 10 )
|
||||
{
|
||||
player PlayRumbleOnEntity( localClientNum, rumble_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* DEAD CODE REMOVAL
|
||||
function play_driving_fx_thirdperson( localClientNum, speed, speed_fraction )
|
||||
{
|
||||
// SP uses _treadfx.csc
|
||||
}
|
||||
*/
|
||||
|
||||
function vehicle_enter( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "enter_vehicle", user );
|
||||
|
||||
if ( isdefined( user ) && user isplayer() )
|
||||
{
|
||||
self thread driving_fx::collision_thread( localClientNum );
|
||||
self thread driving_fx::jump_landing_thread( localClientNum );
|
||||
// self thread driving_fx::speed_fx( localClientNum );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function speed_fx( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
self endon( "exit_vehicle" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
curspeed = self GetSpeed();
|
||||
curspeed = 0.0005 * curspeed;
|
||||
curspeed = Abs(curspeed);
|
||||
if (curspeed>0.001)
|
||||
{
|
||||
SetSavedDvar("r_speedBlurFX_enable","1");
|
||||
SetSavedDvar("r_speedBlurAmount",curspeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSavedDvar("r_speedBlurFX_enable","0");
|
||||
}
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
function play_driving_fx( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
|
||||
self thread vehicle_enter( localClientNum );
|
||||
|
||||
if ( self.surfacefxdeftype == "" )
|
||||
return;
|
||||
|
||||
if ( !isdefined( self.wheel_fx ) )
|
||||
{
|
||||
wheel_names = array( "front_left", "front_right", "back_left", "back_right" );
|
||||
wheel_tag_names = array( "tag_wheel_front_left", "tag_wheel_front_right", "tag_wheel_back_left", "tag_wheel_back_right" );
|
||||
|
||||
// temp hack for RAPS vehicle
|
||||
if( isdefined( self.scriptvehicletype ) && self.scriptvehicletype == "raps" )
|
||||
{
|
||||
wheel_names = array( "front_left" );
|
||||
wheel_tag_names = array( "tag_origin" );
|
||||
}
|
||||
else if( self.vehicleclass == "boat" )
|
||||
{
|
||||
wheel_names = array( "tag_origin" );
|
||||
wheel_tag_names = array( "tag_origin" );
|
||||
}
|
||||
|
||||
self.wheel_fx = [];
|
||||
for ( i = 0; i < wheel_names.size; i++ )
|
||||
{
|
||||
self.wheel_fx[i] = new VehicleWheelFx();
|
||||
[[ self.wheel_fx[i] ]]->init( wheel_names[i], wheel_tag_names[i] );
|
||||
}
|
||||
|
||||
self.camera_fx = [];
|
||||
self.camera_fx[ "speed" ] = new vehicle_camera_fx();
|
||||
[[ self.camera_fx[ "speed" ] ]]->init( 0.5, 1.0, 0.1, 0.115, "reload_small" );
|
||||
|
||||
self.camera_fx[ "skid" ] = new vehicle_camera_fx();
|
||||
[[ self.camera_fx[ "skid" ] ]]->init( 0.25, 0.35, 0.1, 0.115 );
|
||||
}
|
||||
|
||||
self.last_screen_dirt = 0;
|
||||
self.screen_dirt_delay = 0;
|
||||
|
||||
speed_fraction = 0;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
speed = Length( self GetVelocity() );
|
||||
max_speed = ( speed < 0 ? self GetMaxReverseSpeed() : self GetMaxSpeed() );
|
||||
speed_fraction = ( max_speed > 0 ? Abs(speed) / max_speed : 0 );
|
||||
|
||||
self.skidding = false;
|
||||
|
||||
for ( i = 0; i < self.wheel_fx.size; i++ )
|
||||
{
|
||||
[[ self.wheel_fx[i] ]]->update( localClientNum, self, speed_fraction );
|
||||
}
|
||||
|
||||
// [[ self.camera_fx[ "speed" ] ]]->update( localClientNum, self, speed_fraction );
|
||||
//
|
||||
// if ( self.skidding )
|
||||
// {
|
||||
// [[ self.camera_fx[ "skid" ] ]]->update( localClientNum, self, ( speed_fraction < 0.25 ? 0.25 : 1 ) );
|
||||
// }
|
||||
|
||||
wait( 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function get_wheel_fx( type, surface )
|
||||
{
|
||||
fxarray = undefined;
|
||||
|
||||
if ( type == "tread" )
|
||||
{
|
||||
fxarray = self.treadfxnamearray;
|
||||
}
|
||||
else if ( type == "peel" )
|
||||
{
|
||||
fxarray = self.peelfxnamearray;
|
||||
}
|
||||
else if ( type == "skid" )
|
||||
{
|
||||
fxarray = self.skidfxnamearray;
|
||||
}
|
||||
|
||||
if( isdefined( fxarray ) )
|
||||
{
|
||||
return fxarray[ surface ];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function play_driving_fx_firstperson( localClientNum, speed, speed_fraction )
|
||||
{
|
||||
const normal_speed_fraction = 0.25;
|
||||
|
||||
// in yo face!
|
||||
if ( speed > 0 && speed_fraction >= normal_speed_fraction )
|
||||
{
|
||||
viewangles = getlocalclientangles( localClientNum );
|
||||
pitch = angleclamp180( viewangles[0] );
|
||||
|
||||
const max_additional_time = 1000;
|
||||
const no_effects_pitch = -10.0; // 10 degress up, no dirt
|
||||
const full_effects_pitch = 10.0; // 10 down, full dirt
|
||||
|
||||
if ( pitch > no_effects_pitch )
|
||||
{
|
||||
current_additional_time = 0;
|
||||
if ( pitch < full_effects_pitch )
|
||||
{
|
||||
current_additional_time = max_additional_time * ( ( (pitch - full_effects_pitch) / ( no_effects_pitch - full_effects_pitch ) ) );
|
||||
}
|
||||
|
||||
if ( self.last_screen_dirt + self.screen_dirt_delay + current_additional_time < getrealtime() )
|
||||
{
|
||||
screen_fx_type = self correct_surface_type_for_screen_fx();
|
||||
if ( screen_fx_type == "dirt" )
|
||||
{
|
||||
play_screen_fx_dirt( localClientNum );
|
||||
}
|
||||
else
|
||||
{
|
||||
play_screen_fx_dust( localClientNum );
|
||||
}
|
||||
self.last_screen_dirt = getrealtime();
|
||||
self.screen_dirt_delay = RandomIntRange( 250, 500 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function collision_thread( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
self endon( "exit_vehicle" );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
self waittill( "veh_collision", hip, hitn, hit_intensity );
|
||||
|
||||
if ( self IsLocalClientDriver( localClientNum ) )
|
||||
{
|
||||
//println( "veh_collision " + hit_intensity );
|
||||
|
||||
player = getlocalplayer( localClientNum );
|
||||
|
||||
if ( isdefined( self.driving_fx_collision_override ) )
|
||||
{
|
||||
self [[ self.driving_fx_collision_override ]]( localClientNum, player, hip, hitn, hit_intensity );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isdefined( player ) && isdefined( hit_intensity ) )
|
||||
{
|
||||
if( hit_intensity > self.heavyCollisionSpeed )
|
||||
{
|
||||
volume = get_impact_vol_from_speed();
|
||||
|
||||
if (isdefined (self.sounddef))
|
||||
{
|
||||
alias = self.sounddef + "_suspension_lg_hd";
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = "veh_default_suspension_lg_hd";
|
||||
}
|
||||
|
||||
id = PlaySound( 0, alias, self.origin, volume);
|
||||
|
||||
if( isdefined( self.heavyCollisionRumble ) )
|
||||
{
|
||||
player PlayRumbleOnEntity( localClientNum, self.heavyCollisionRumble );
|
||||
}
|
||||
}
|
||||
else if( hit_intensity > self.lightCollisionSpeed )
|
||||
{
|
||||
volume = get_impact_vol_from_speed();
|
||||
|
||||
if (isdefined (self.sounddef))
|
||||
{
|
||||
alias = self.sounddef + "_suspension_lg_lt";
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = "veh_default_suspension_lg_lt";
|
||||
}
|
||||
|
||||
id = PlaySound( 0, alias, self.origin, volume );
|
||||
|
||||
if( isdefined( self.lightCollisionRumble ) )
|
||||
{
|
||||
player PlayRumbleOnEntity( localClientNum, self.lightCollisionRumble );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function jump_landing_thread( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
self endon( "exit_vehicle" );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
self waittill( "veh_landed" );
|
||||
|
||||
if ( self IsLocalClientDriver( localClientNum ) )
|
||||
{
|
||||
player = getlocalplayer( localClientNum );
|
||||
|
||||
if( isdefined( player ) )
|
||||
{
|
||||
if ( isdefined( self.driving_fx_jump_landing_override ) )
|
||||
{
|
||||
self [[ self.driving_fx_jump_landing_override ]]( localClientNum, player );
|
||||
}
|
||||
else
|
||||
{
|
||||
volume = get_impact_vol_from_speed();
|
||||
|
||||
if (isdefined (self.sounddef))
|
||||
{
|
||||
alias = self.sounddef + "_suspension_lg_hd";
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = "veh_default_suspension_lg_hd";
|
||||
}
|
||||
|
||||
id = PlaySound( 0, alias, self.origin, volume);
|
||||
if( isdefined( self.jumpLandingRumble ) )
|
||||
{
|
||||
player PlayRumbleOnEntity( localClientNum, self.jumpLandingRumble );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function suspension_thread( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
self endon( "exit_vehicle" );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
self waittill( "veh_suspension_limit_activated" );
|
||||
|
||||
if ( self IsLocalClientDriver( localClientNum ) )
|
||||
{
|
||||
player = getlocalplayer( localClientNum );
|
||||
|
||||
if( isdefined( player ) )
|
||||
{
|
||||
volume = get_impact_vol_from_speed();
|
||||
|
||||
if (isdefined (self.sounddef))
|
||||
{
|
||||
alias = self.sounddef + "_suspension_lg_lt";
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = "veh_default_suspension_lg_lt";
|
||||
}
|
||||
|
||||
id = PlaySound( 0, alias, self.origin, volume);
|
||||
player PlayRumbleOnEntity( localClientNum, "damage_light" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function get_impact_vol_from_speed( )
|
||||
{
|
||||
// values to map to a linear scale
|
||||
curspeed = self GetSpeed();
|
||||
maxSpeed = self GetMaxSpeed();
|
||||
|
||||
volume = audio::scale_speed( 0, maxSpeed, 0, 1, curspeed );
|
||||
|
||||
volume = volume * volume * volume;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
function any_wheel_colliding()
|
||||
{
|
||||
return ( self iswheelcolliding( "front_left" ) || self iswheelcolliding( "front_right" ) ||
|
||||
self iswheelcolliding( "back_left" ) || self iswheelcolliding( "back_right" ) );
|
||||
}
|
||||
|
||||
function dirt_surface_type( surface_type )
|
||||
{
|
||||
switch( surface_type )
|
||||
{
|
||||
case "dirt":
|
||||
case "mud":
|
||||
case "gravel":
|
||||
case "grass":
|
||||
case "foliage":
|
||||
case "sand":
|
||||
case "snow":
|
||||
case "water":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function correct_surface_type_for_screen_fx()
|
||||
{
|
||||
right_rear = self GetWheelSurface("back_right");
|
||||
left_rear = self GetWheelSurface("back_left");
|
||||
|
||||
// PrintLn("surfacetypes: " + left_rear + " " + right_rear );
|
||||
if ( dirt_surface_type( right_rear ) )
|
||||
return "dirt";
|
||||
|
||||
if ( dirt_surface_type( left_rear ) )
|
||||
return "dirt";
|
||||
|
||||
return "dust";
|
||||
}
|
||||
|
||||
function play_screen_fx_dirt(localClientNum)
|
||||
{
|
||||
// support for this has been removed with the .menu system
|
||||
/*
|
||||
pick_one = RandomIntRange(0,4);
|
||||
if ( pick_one == 0 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dirt", "dirt", "in", 0 );
|
||||
}
|
||||
else if ( pick_one == 1 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dirt", "dirt_right_splash", "in", 0 );
|
||||
}
|
||||
else if ( pick_one == 2 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dirt", "dirt_left_splash", "in", 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dirt", "blurred_dirt_random", "in", 0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function play_screen_fx_dust(localClientNum)
|
||||
{
|
||||
// support for this has been removed with the .menu system
|
||||
/*
|
||||
pick_one = RandomIntRange(0,4);
|
||||
if ( pick_one == 0 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dust", "dust", "in", 0 );
|
||||
}
|
||||
else if ( pick_one == 1 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dust", "dust_right_splash", "in", 0 );
|
||||
}
|
||||
else if ( pick_one == 2 )
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dust", "dust_left_splash", "in", 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimateUI( localClientNum, "fullscreen_dust", "blurred_dust_random", "in", 0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,82 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\duplicaterender_mgr;
|
||||
#using scripts\shared\filter_shared;
|
||||
#using scripts\shared\postfx_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#namespace parasite;
|
||||
|
||||
function autoexec main()
|
||||
{
|
||||
clientfield::register( "vehicle", "parasite_tell_fx", 1, 1, "int", ¶siteTellFxHandler, !true, !true );
|
||||
clientfield::register( "toplayer", "parasite_damage", 1, 1, "counter", ¶site_damage, !true, !true );
|
||||
clientfield::register( "vehicle", "parasite_secondary_deathfx", 1, 1, "int", ¶siteSecondaryDeathFxHandler, !true, !true );
|
||||
|
||||
vehicle::add_vehicletype_callback( "parasite", &_setup_ );
|
||||
}
|
||||
|
||||
function private parasiteTellFxHandler( localClientNum, oldValue, newValue, bNewEnt, bInitialSnap, fieldName, wasDemoJump )
|
||||
{
|
||||
if ( IsDefined( self.tellFxHandle ) )
|
||||
{
|
||||
StopFX( localClientNum, self.tellFxHandle );
|
||||
self.tellFxHandle = undefined;
|
||||
self MapShaderConstant( localClientNum, 0, "scriptVector2", 0.1 );
|
||||
}
|
||||
|
||||
settings = struct::get_script_bundle( "vehiclecustomsettings", "parasitesettings" );
|
||||
|
||||
if( IsDefined( settings ) )
|
||||
{
|
||||
if( newValue )
|
||||
{
|
||||
self.tellFxHandle = PlayFXOnTag( localClientNum, settings.weakspotfx, self, "tag_flash" );
|
||||
self MapShaderConstant( localClientNum, 0, "scriptVector2", 1.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function private parasite_damage( localClientNum, oldValue, newValue, bNewEnt, bInitialSnap, fieldName, wasDemoJump )
|
||||
{
|
||||
if ( newValue )
|
||||
{
|
||||
self postfx::PlayPostfxBundle( "pstfx_parasite_dmg" );
|
||||
}
|
||||
}
|
||||
|
||||
function private parasiteSecondaryDeathFxHandler( localClientNum, oldValue, newValue, bNewEnt, bInitialSnap, fieldName, wasDemoJump )
|
||||
{
|
||||
settings = struct::get_script_bundle( "vehiclecustomsettings", "parasitesettings" );
|
||||
|
||||
if( IsDefined( settings ) )
|
||||
{
|
||||
if( newValue )
|
||||
{
|
||||
handle = PlayFX( localClientNum, settings.secondary_death_fx_1, self GetTagOrigin( settings.secondary_death_tag_1 ) );
|
||||
SetFXIgnorePause( localClientNum, handle, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function private _setup_( localClientNum )
|
||||
{
|
||||
self MapShaderConstant( localClientNum, 0, "scriptVector2", 0.1 );
|
||||
|
||||
if( ( isdefined( level.debug_keyline_zombies ) && level.debug_keyline_zombies ) )
|
||||
{
|
||||
self duplicate_render::set_dr_flag( "keyline_active", 1 );
|
||||
self duplicate_render::update_dr_filters(localClientNum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,768 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\math_shared;
|
||||
#using scripts\shared\statemachine_shared;
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\array_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\ai_shared;
|
||||
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\vehicle_death_shared;
|
||||
#using scripts\shared\vehicle_ai_shared;
|
||||
#using scripts\shared\ai\systems\blackboard;
|
||||
#using scripts\shared\ai\blackboard_vehicle;
|
||||
#using scripts\shared\ai\systems\ai_interface;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#using scripts\shared\ai\zombie_utility;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//reduce these defines to have the parasite make more movements close together
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#namespace parasite;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("parasite",&__init__,undefined,undefined); }
|
||||
|
||||
#using_animtree( "generic" );
|
||||
|
||||
function __init__()
|
||||
{
|
||||
vehicle::add_main_callback( "parasite", ¶site_initialize );
|
||||
|
||||
clientfield::register( "vehicle", "parasite_tell_fx", 1, 1, "int" );
|
||||
clientfield::register( "vehicle", "parasite_secondary_deathfx", 1, 1, "int" );
|
||||
clientfield::register( "toplayer", "parasite_damage", 1, 1, "counter" );
|
||||
|
||||
callback::on_spawned( ¶site_damage );
|
||||
|
||||
ai::RegisterMatchedInterface(
|
||||
"parasite",
|
||||
"firing_rate",
|
||||
"slow",
|
||||
array( "slow", "medium", "fast" ) );
|
||||
}
|
||||
|
||||
function parasite_damage()
|
||||
{
|
||||
self notify( "parasite_damage_thread" );
|
||||
self endon( "parasite_damage_thread" );
|
||||
|
||||
self endon( "death" );
|
||||
|
||||
while ( true )
|
||||
{
|
||||
self waittill( "damage", n_ammount, e_attacker );
|
||||
|
||||
if ( IsDefined( e_attacker ) && ( isdefined( e_attacker.is_parasite ) && e_attacker.is_parasite ) && !( isdefined( e_attacker.squelch_damage_overlay ) && e_attacker.squelch_damage_overlay ) )
|
||||
{
|
||||
self clientfield::increment_to_player( "parasite_damage" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function private is_target_valid( target )
|
||||
{
|
||||
if( !IsDefined( target ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !IsAlive( target ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( IsPlayer( target ) && target.sessionstate == "spectator" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( IsPlayer( target ) && target.sessionstate == "intermission" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ( isdefined( target.ignoreme ) && target.ignoreme ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( target IsNoTarget() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( IsDefined( self.is_target_valid_cb ) )
|
||||
{
|
||||
return self [[ self.is_target_valid_cb ]]( target );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_parasite_enemy()
|
||||
{
|
||||
parasite_targets = GetPlayers();
|
||||
least_hunted = parasite_targets[0];
|
||||
for( i = 0; i < parasite_targets.size; i++ )
|
||||
{
|
||||
if ( !isdefined( parasite_targets[i].hunted_by ) )
|
||||
{
|
||||
parasite_targets[i].hunted_by = 0;
|
||||
}
|
||||
|
||||
if( !is_target_valid( parasite_targets[i] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !is_target_valid( least_hunted ) )
|
||||
{
|
||||
least_hunted = parasite_targets[i];
|
||||
}
|
||||
|
||||
if( parasite_targets[i].hunted_by < least_hunted.hunted_by )
|
||||
{
|
||||
least_hunted = parasite_targets[i];
|
||||
}
|
||||
|
||||
}
|
||||
// do not return the default first player if he is invalid
|
||||
if( !is_target_valid( least_hunted ) )
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
return least_hunted;
|
||||
}
|
||||
}
|
||||
|
||||
function set_parasite_enemy( enemy )
|
||||
{
|
||||
if( !is_target_valid( enemy ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( IsDefined( self.parasiteEnemy ) )
|
||||
{
|
||||
if( !IsDefined( self.parasiteEnemy.hunted_by ) )
|
||||
{
|
||||
self.parasiteEnemy.hunted_by = 0;
|
||||
}
|
||||
if( self.parasiteEnemy.hunted_by > 0 )
|
||||
{
|
||||
self.parasiteEnemy.hunted_by--;
|
||||
}
|
||||
}
|
||||
|
||||
self.parasiteEnemy = enemy;
|
||||
if( !IsDefined( self.parasiteEnemy.hunted_by ) )
|
||||
{
|
||||
self.parasiteEnemy.hunted_by = 0;
|
||||
}
|
||||
self.parasiteEnemy.hunted_by++;
|
||||
self SetLookAtEnt( self.parasiteEnemy );
|
||||
self SetTurretTargetEnt( self.parasiteEnemy );
|
||||
}
|
||||
|
||||
function private parasite_target_selection()
|
||||
{
|
||||
self endon( "change_state" );
|
||||
self endon( "death" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if ( ( isdefined( self.ignoreall ) && self.ignoreall ) )
|
||||
{
|
||||
wait 0.5;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( is_target_valid( self.parasiteEnemy ) )
|
||||
{
|
||||
wait 0.5;
|
||||
continue;
|
||||
}
|
||||
//decide who the enemy should be
|
||||
target = get_parasite_enemy();
|
||||
|
||||
if( !isDefined( target ) )
|
||||
{
|
||||
self.parasiteEnemy = undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.parasiteEnemy = target;
|
||||
//update hunted_by
|
||||
self.parasiteEnemy.hunted_by += 1;
|
||||
self SetLookAtEnt( self.parasiteEnemy );
|
||||
self SetTurretTargetEnt( self.parasiteEnemy );
|
||||
}
|
||||
|
||||
wait 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
function parasite_initialize()
|
||||
{
|
||||
self useanimtree( #animtree );
|
||||
|
||||
// AI SPECIFIC INITIALIZATION
|
||||
blackboard::CreateBlackBoardForEntity( self );
|
||||
self Blackboard::RegisterVehicleBlackBoardAttributes();
|
||||
ai::CreateInterfaceForEntity( self );
|
||||
|
||||
Blackboard::RegisterBlackBoardAttribute(self,"_parasite_firing_rate","slow",&getParasiteFiringRate); if( IsActor(self) ) { /#self TrackBlackBoardAttribute("_parasite_firing_rate");#/ };
|
||||
|
||||
self.health = self.healthdefault;
|
||||
|
||||
self vehicle::friendly_fire_shield();
|
||||
|
||||
self EnableAimAssist();
|
||||
self SetNearGoalNotifyDist( 25 );
|
||||
|
||||
self SetDrawInfrared( true );
|
||||
|
||||
self.fovcosine = 0;
|
||||
self.fovcosinebusy = 0;
|
||||
|
||||
self.vehAirCraftCollisionEnabled = true;
|
||||
|
||||
assert( isdefined( self.scriptbundlesettings ) );
|
||||
|
||||
self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
self.goalRadius = 999999;
|
||||
self.goalHeight = 4000;
|
||||
self SetGoal( self.origin, false, self.goalRadius, self.goalHeight );
|
||||
|
||||
self.is_parasite = true;
|
||||
|
||||
self thread vehicle_ai::nudge_collision();
|
||||
|
||||
if( IsDefined( level.vehicle_initializer_cb ) )
|
||||
{
|
||||
[[level.vehicle_initializer_cb]]( self );
|
||||
}
|
||||
|
||||
defaultRole();
|
||||
}
|
||||
|
||||
function defaultRole()
|
||||
{
|
||||
self vehicle_ai::init_state_machine_for_role( "default" );
|
||||
|
||||
self vehicle_ai::get_state_callbacks( "combat" ).enter_func = &state_combat_enter;
|
||||
self vehicle_ai::get_state_callbacks( "combat" ).update_func = &state_combat_update;
|
||||
|
||||
self vehicle_ai::get_state_callbacks( "death" ).update_func = &state_death_update;
|
||||
|
||||
self vehicle_ai::call_custom_add_state_callbacks();
|
||||
|
||||
vehicle_ai::StartInitialState( "combat" );
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
//BB getter functions
|
||||
// ----------------------------------------------
|
||||
function getParasiteFiringRate()
|
||||
{
|
||||
return self ai::get_behavior_attribute( "firing_rate" );
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// State: death
|
||||
// ----------------------------------------------
|
||||
function state_death_update( params )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
self ASMRequestSubstate( "death@stationary" );
|
||||
|
||||
if( IsDefined( self.parasiteEnemy ) && IsDefined( self.parasiteEnemy.hunted_by ) )
|
||||
{
|
||||
self.parasiteEnemy.hunted_by--;
|
||||
}
|
||||
|
||||
self SetPhysAcceleration( ( 0, 0, -300 ) );
|
||||
self.vehcheckforpredictedcrash = true;
|
||||
|
||||
self thread vehicle_death::death_fx();
|
||||
self playsound( "zmb_parasite_explo" );
|
||||
|
||||
self util::waittill_notify_or_timeout( "veh_predictedcollision", 4.0 );
|
||||
|
||||
self clientfield::set( "parasite_secondary_deathfx", 1 );
|
||||
|
||||
//make sure the client gets a chance to play the second fx before deleting
|
||||
wait 0.2;
|
||||
|
||||
self Delete();
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// State: combat
|
||||
// ----------------------------------------------
|
||||
function state_combat_enter( params )
|
||||
{
|
||||
if ( IsDefined( self.owner ) && IsDefined( self.owner.enemy ) )
|
||||
{
|
||||
self.parasiteEnemy = self.owner.enemy;
|
||||
}
|
||||
self thread parasite_target_selection();
|
||||
}
|
||||
|
||||
function state_combat_update( params )
|
||||
{
|
||||
self endon( "change_state" );
|
||||
self endon( "death" );
|
||||
|
||||
lastTimeChangePosition = 0;
|
||||
self.shouldGotoNewPosition = false;
|
||||
self.lastTimeTargetInSight = 0;
|
||||
self.lastTimeJuked = false;
|
||||
|
||||
//request movement animations
|
||||
self ASMRequestSubstate( "locomotion@movement" );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if( IsDefined( self._override_parasite_combat_speed ) )
|
||||
{
|
||||
self SetSpeed( self._override_parasite_combat_speed );
|
||||
}
|
||||
else
|
||||
{
|
||||
self SetSpeed( self.settings.defaultMoveSpeed );
|
||||
}
|
||||
|
||||
if ( ( isdefined( self.inpain ) && self.inpain ) )
|
||||
{
|
||||
wait 0.1;
|
||||
}
|
||||
else if ( !IsDefined( self.parasiteEnemy ) )
|
||||
{
|
||||
//no enemy, do nothing
|
||||
wait( 0.25 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( self.goalforced )
|
||||
{
|
||||
returnData = [];
|
||||
returnData[ "origin" ] = self GetClosestPointOnNavVolume( self.goalpos, 100 );
|
||||
returnData[ "centerOnNav" ] = IsPointInNavVolume( self.origin, "navvolume_small" );
|
||||
}
|
||||
//prevent two consecutive forward jukes, and force juke if path was interrupted ( possibly due to collision )
|
||||
else if( ( RandomInt( 100 ) < self.settings.jukeprobability && !( isdefined( self.lastTimeJuked ) && self.lastTimeJuked ) ) || ( isdefined( self._override_juke ) && self._override_juke ) )
|
||||
{
|
||||
returnData = GetNextMovePosition_forwardjuke();
|
||||
self.lastTimeJuked = true;
|
||||
self._override_juke = undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnData = GetNextMovePosition_tactical();
|
||||
self.lastTimeJuked = false;
|
||||
}
|
||||
self.current_pathto_pos = returnData[ "origin" ];
|
||||
if ( IsDefined( self.current_pathto_pos ) )
|
||||
{
|
||||
if( IsDefined( self.stuckTime ) )
|
||||
{
|
||||
self.stuckTime = undefined;
|
||||
}
|
||||
if ( self SetVehGoalPos( self.current_pathto_pos, true, returnData[ "centerOnNav" ] ) )
|
||||
{
|
||||
self thread path_update_interrupt();
|
||||
|
||||
//AUDIO: Was on JUST the juke, but I've moved it for any movement to make it more interesting
|
||||
self playsound( "zmb_vocals_parasite_juke" );
|
||||
|
||||
self vehicle_ai::waittill_pathing_done( 5 );
|
||||
}
|
||||
else
|
||||
{
|
||||
//failsafe, cannot pathfind
|
||||
wait( 0.1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !( isdefined( returnData[ "centerOnNav" ] ) && returnData[ "centerOnNav" ] ) )
|
||||
{
|
||||
//not on navmesh, no valid goto points, kill parasite as failsafe
|
||||
if( !IsDefined( self.stuckTime ) )
|
||||
{
|
||||
self.stuckTime = GetTime();
|
||||
}
|
||||
if( GetTime() - self.stuckTime > 10000 )
|
||||
{
|
||||
self DoDamage( self.health + 100, self.origin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( isdefined( self.lastTimeJuked ) && self.lastTimeJuked ) )
|
||||
{
|
||||
if( RandomInt( 100 ) < 50 && IsDefined( self.parasiteEnemy ) && Distance2DSquared( self.origin, self.parasiteEnemy.origin ) < ( (64) * (64) ) )
|
||||
{
|
||||
//parasite melee bite
|
||||
self.parasiteEnemy DoDamage( self.settings.meleedamage, self.parasiteEnemy.origin, self );
|
||||
}
|
||||
else
|
||||
{
|
||||
self fire_pod_logic( self.lastTimeJuked );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( RandomInt( 100 ) < 30 )
|
||||
{
|
||||
self fire_pod_logic( self.lastTimeJuked );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fire_pod_logic( choseToJuke )
|
||||
{
|
||||
if( IsDefined( self.parasiteEnemy ) && self VehCanSee( self.parasiteEnemy ) && Distance2DSquared( self.parasiteEnemy.origin, self.origin ) < ( (0.5 * ( self.settings.engagementDistMin + self.settings.engagementDistMax ) * 3) * (0.5 * ( self.settings.engagementDistMin + self.settings.engagementDistMax ) * 3) ) )
|
||||
{
|
||||
//switch to fire animation
|
||||
self ASMRequestSubstate( "fire@stationary" );
|
||||
|
||||
//do the tell
|
||||
self PlaySound( "zmb_vocals_parasite_preattack" );
|
||||
self clientfield::set( "parasite_tell_fx", 1 );
|
||||
|
||||
//reached the point in the animation to adjust the turret
|
||||
self waittill( "pre_fire" );
|
||||
|
||||
if( IsDefined( self.parasiteEnemy ) && self VehCanSee( self.parasiteEnemy ) && Distance2DSquared( self.parasiteEnemy.origin, self.origin ) < ( (0.5 * ( self.settings.engagementDistMin + self.settings.engagementDistMax ) * 3) * (0.5 * ( self.settings.engagementDistMin + self.settings.engagementDistMax ) * 3) ) )
|
||||
{
|
||||
//fire the projectile at the predicted player position
|
||||
self SetTurretTargetEnt( self.parasiteEnemy, self.parasiteEnemy GetVelocity() * 0.3 );
|
||||
}
|
||||
|
||||
self vehicle_ai::waittill_asm_complete( "fire@stationary", 5 );
|
||||
|
||||
//switch back to locomotion
|
||||
self ASMRequestSubstate( "locomotion@movement" );
|
||||
|
||||
//cleanup the fx
|
||||
self clientfield::set( "parasite_tell_fx", 0 );
|
||||
|
||||
if( !choseToJuke )
|
||||
{
|
||||
wait RandomFloatRange( 0.25, 0.5 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wait RandomFloatRange( 1, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
function GetNextMovePosition_tactical() // has self.parasiteEnemy
|
||||
{
|
||||
self endon( "change_state" );
|
||||
self endon( "death" );
|
||||
|
||||
// distance based multipliers
|
||||
selfDistToTarget = Distance2D( self.origin, self.parasiteEnemy.origin );
|
||||
|
||||
goodDist = 0.5 * ( self.settings.engagementDistMin + self.settings.engagementDistMax );
|
||||
|
||||
closeDist = 1.2 * goodDist;
|
||||
farDist = 3 * goodDist;
|
||||
|
||||
queryMultiplier = MapFloat( closeDist, farDist, 1, 3, selfDistToTarget );
|
||||
|
||||
//the preferred height range should be half the max possible difference to not exceed valid heights for points near the goalheight
|
||||
preferedHeightRange = 0.5 * ( self.settings.engagementHeightMax - self.settings.engagementHeightMin );
|
||||
randomness = 30;
|
||||
|
||||
// query
|
||||
queryResult = PositionQuery_Source_Navigation( self.origin, 75, 225 * queryMultiplier, 75, 20 * queryMultiplier, self, 20 * queryMultiplier );
|
||||
//turn off collision, we are not on the navvolume
|
||||
if( !( isdefined( queryResult.centerOnNav ) && queryResult.centerOnNav ) )
|
||||
{
|
||||
self.vehAirCraftCollisionEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.vehAirCraftCollisionEnabled = true;
|
||||
}
|
||||
// filter
|
||||
PositionQuery_Filter_DistanceToGoal( queryResult, self );
|
||||
vehicle_ai::PositionQuery_Filter_OutOfGoalAnchor( queryResult );
|
||||
self vehicle_ai::PositionQuery_Filter_EngagementDist( queryResult, self.parasiteEnemy, self.settings.engagementDistMin, self.settings.engagementDistMax );
|
||||
|
||||
goalHeight = self.parasiteEnemy.origin[2] + 0.5 * ( self.settings.engagementHeightMin + self.settings.engagementHeightMax );
|
||||
|
||||
// score points
|
||||
best_point = undefined;
|
||||
best_score = -999999;
|
||||
trace_count = 0;
|
||||
foreach ( point in queryResult.data )
|
||||
{
|
||||
if( !( isdefined( queryResult.centerOnNav ) && queryResult.centerOnNav ) )
|
||||
{
|
||||
if( SightTracePassed( self.origin, point.origin, false, undefined ) )
|
||||
{
|
||||
trace_count++;
|
||||
if( trace_count > 3 )
|
||||
{
|
||||
{wait(.05);};
|
||||
trace_count = 0;
|
||||
}
|
||||
if( !BulletTracePassed( self.origin, point.origin, false, self ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "random" ] = randomFloatRange( 0, randomness ); #/ point.score += randomFloatRange( 0, randomness );;
|
||||
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "engagementDist" ] = -point.distAwayFromEngagementArea; #/ point.score += -point.distAwayFromEngagementArea;;
|
||||
|
||||
// height
|
||||
distFromPreferredHeight = abs( point.origin[2] - goalHeight );
|
||||
if ( distFromPreferredHeight > preferedHeightRange )
|
||||
{
|
||||
heightScore = MapFloat( 0, 500, 0, 2000, distFromPreferredHeight );
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "height" ] = -heightScore; #/ point.score += -heightScore;;
|
||||
}
|
||||
|
||||
if ( point.score > best_score )
|
||||
{
|
||||
best_score = point.score;
|
||||
best_point = point;
|
||||
}
|
||||
}
|
||||
self vehicle_ai::PositionQuery_DebugScores( queryResult );
|
||||
|
||||
/#
|
||||
if ( ( isdefined( GetDvarInt("hkai_debugPositionQuery") ) && GetDvarInt("hkai_debugPositionQuery") ) )
|
||||
{
|
||||
recordLine( self.origin, best_point.origin, (0.3,1,0) );
|
||||
recordLine( self.origin, self.parasiteEnemy.origin, (1,0,0.4) );
|
||||
}
|
||||
#/
|
||||
returnData = [];
|
||||
returnData[ "origin" ] = ( ( IsDefined( best_point ) ) ? best_point.origin : undefined );
|
||||
returnData[ "centerOnNav" ] = queryResult.centerOnNav;
|
||||
return returnData;
|
||||
}
|
||||
|
||||
|
||||
function GetNextMovePosition_forwardjuke() // has self.parasiteEnemy
|
||||
{
|
||||
self endon( "change_state" );
|
||||
self endon( "death" );
|
||||
|
||||
// distance based multipliers
|
||||
selfDistToTarget = Distance2D( self.origin, self.parasiteEnemy.origin );
|
||||
|
||||
goodDist = 0.5 * ( self.settings.forwardJukeEngagementDistMin + self.settings.forwardJukeEngagementDistMax );
|
||||
|
||||
closeDist = 1.2 * goodDist;
|
||||
farDist = 3 * goodDist;
|
||||
|
||||
queryMultiplier = MapFloat( closeDist, farDist, 1, 3, selfDistToTarget );
|
||||
|
||||
preferedHeightRange = 0.5 * ( self.settings.forwardJukeEngagementHeightMax - self.settings.forwardJukeEngagementHeightMin );
|
||||
randomness = 30;
|
||||
|
||||
// query
|
||||
queryResult = PositionQuery_Source_Navigation( self.origin, 75, 300 * queryMultiplier, 75, 20 * queryMultiplier, self, 20 * queryMultiplier );
|
||||
if( !( isdefined( queryResult.centerOnNav ) && queryResult.centerOnNav ) )
|
||||
{
|
||||
self.vehAirCraftCollisionEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.vehAirCraftCollisionEnabled = true;
|
||||
}
|
||||
// filter
|
||||
PositionQuery_Filter_DistanceToGoal( queryResult, self );
|
||||
vehicle_ai::PositionQuery_Filter_OutOfGoalAnchor( queryResult );
|
||||
self vehicle_ai::PositionQuery_Filter_EngagementDist( queryResult, self.parasiteEnemy, self.settings.forwardJukeEngagementDistMin, self.settings.forwardJukeEngagementDistMax );
|
||||
|
||||
goalHeight = self.parasiteEnemy.origin[2] + 0.5 * ( self.settings.forwardJukeEngagementHeightMin + self.settings.forwardJukeEngagementHeightMax );
|
||||
|
||||
// score points
|
||||
best_point = undefined;
|
||||
best_score = -999999;
|
||||
trace_count = 0;
|
||||
|
||||
foreach ( point in queryResult.data )
|
||||
{
|
||||
if( !( isdefined( queryResult.centerOnNav ) && queryResult.centerOnNav ) )
|
||||
{
|
||||
if( SightTracePassed( self.origin, point.origin, false, undefined ) )
|
||||
{
|
||||
trace_count++;
|
||||
if( trace_count > 3 )
|
||||
{
|
||||
{wait(.05);};
|
||||
trace_count = 0;
|
||||
}
|
||||
if( !BulletTracePassed( self.origin, point.origin, false, self ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "random" ] = randomFloatRange( 0, randomness ); #/ point.score += randomFloatRange( 0, randomness );;
|
||||
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "engagementDist" ] = -point.distAwayFromEngagementArea; #/ point.score += -point.distAwayFromEngagementArea;;
|
||||
|
||||
// height
|
||||
distFromPreferredHeight = abs( point.origin[2] - goalHeight );
|
||||
if ( distFromPreferredHeight > preferedHeightRange )
|
||||
{
|
||||
heightScore = MapFloat( 0, 500, 0, 2000, distFromPreferredHeight );
|
||||
/# if ( !isdefined( point._scoreDebug ) ) { point._scoreDebug = []; } point._scoreDebug[ "height" ] = -heightScore; #/ point.score += -heightScore;;
|
||||
}
|
||||
|
||||
if ( point.score > best_score )
|
||||
{
|
||||
best_score = point.score;
|
||||
best_point = point;
|
||||
}
|
||||
}
|
||||
self vehicle_ai::PositionQuery_DebugScores( queryResult );
|
||||
|
||||
/#
|
||||
if ( ( isdefined( GetDvarInt("hkai_debugPositionQuery") ) && GetDvarInt("hkai_debugPositionQuery") ) )
|
||||
{
|
||||
recordLine( self.origin, best_point.origin, (0.3,1,0) );
|
||||
recordLine( self.origin, self.parasiteEnemy.origin, (1,0,0.4) );
|
||||
}
|
||||
#/
|
||||
|
||||
returnData = [];
|
||||
returnData[ "origin" ] = ( ( IsDefined( best_point ) ) ? best_point.origin : undefined );
|
||||
returnData[ "centerOnNav" ] = queryResult.centerOnNav;
|
||||
return returnData;
|
||||
}
|
||||
|
||||
function path_update_interrupt()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "change_state" );
|
||||
self endon( "near_goal" );
|
||||
self endon( "reached_end_node" );
|
||||
|
||||
wait 1;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( isdefined( self.current_pathto_pos ) )
|
||||
{
|
||||
if( distance2dSquared( self.current_pathto_pos, self.goalpos ) > ( (self.goalradius) * (self.goalradius) ) )
|
||||
{
|
||||
wait 0.2;
|
||||
self._override_juke = true;
|
||||
self notify( "near_goal" );
|
||||
}
|
||||
}
|
||||
wait 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
// pain/hit reaction
|
||||
// ----------------------------------------------
|
||||
function drone_pain_for_time( time, stablizeParam, restoreLookPoint )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
self.painStartTime = GetTime();
|
||||
|
||||
if ( !( isdefined( self.inpain ) && self.inpain ) )
|
||||
{
|
||||
self.inpain = true;
|
||||
|
||||
self PlaySound( "zmb_vocals_parasite_pain" );
|
||||
|
||||
while ( GetTime() < self.painStartTime + time * 1000 )
|
||||
{
|
||||
self SetVehVelocity( self.velocity * stablizeParam );
|
||||
self SetAngularVelocity( self GetAngularVelocity() * stablizeParam );
|
||||
wait 0.1;
|
||||
}
|
||||
|
||||
if ( isdefined( restoreLookPoint ) )
|
||||
{
|
||||
restoreLookEnt = Spawn( "script_model", restoreLookPoint );
|
||||
restoreLookEnt SetModel( "tag_origin" );
|
||||
|
||||
self ClearLookAtEnt();
|
||||
self SetLookAtEnt( restoreLookEnt );
|
||||
self setTurretTargetEnt( restoreLookEnt );
|
||||
wait 1.5;
|
||||
|
||||
self ClearLookAtEnt();
|
||||
self ClearTurretTarget();
|
||||
restoreLookEnt delete();
|
||||
}
|
||||
|
||||
self.inpain = false;
|
||||
}
|
||||
}
|
||||
|
||||
function drone_pain( eAttacker, damageType, hitPoint, hitDirection, hitLocationInfo, partName )
|
||||
{
|
||||
if ( !( isdefined( self.inpain ) && self.inpain ) )
|
||||
{
|
||||
yaw_vel = math::randomSign() * RandomFloatRange( 280, 320 );
|
||||
|
||||
ang_vel = self GetAngularVelocity();
|
||||
ang_vel += ( RandomFloatRange( -120, -100 ), yaw_vel, RandomFloatRange( -200, 200 ) );
|
||||
self SetAngularVelocity( ang_vel );
|
||||
|
||||
self thread drone_pain_for_time( 0.8, 0.7 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\filter_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
#namespace quadtank;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("quadtank",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
vehicle::add_vehicletype_callback( "quadtank", &_setup_ );
|
||||
|
||||
clientfield::register( "toplayer", "player_shock_fx", 1, 1, "int", &player_shock_fx_handler, !true, !true );
|
||||
clientfield::register( "vehicle", "quadtank_trophy_state", 1, 1, "int", &update_trophy_system_state, !true, !true );
|
||||
}
|
||||
|
||||
function _setup_( localClientNum )
|
||||
{
|
||||
player = GetLocalPlayer( localClientNum );
|
||||
if( isdefined( player ) )
|
||||
{
|
||||
filter::init_filter_ev_interference( player );
|
||||
}
|
||||
//set code field to get notifies to play impact effects
|
||||
self.notifyOnBulletImpact = true;
|
||||
self thread wait_for_bullet_impact( localClientNum );
|
||||
|
||||
//trophy state
|
||||
self.trophy_on = false;
|
||||
}
|
||||
|
||||
|
||||
function player_shock_fx_handler( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
|
||||
{
|
||||
if ( isdefined( self ) )
|
||||
{
|
||||
self thread player_shock_fx_fade_off( localClientNum, 1.0, 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
function player_shock_fx_fade_off( localClientNum, amount, fadeoutTime )
|
||||
{
|
||||
// not ending on death or shutdown, cause we have to clean ourselves up
|
||||
self endon( "disconnect" );
|
||||
self notify( "player_shock_fx_fade_off_end" ); // kill previous threads
|
||||
self endon( "player_shock_fx_fade_off_end" );
|
||||
|
||||
if ( !isAlive( self ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
startTime = GetTime();
|
||||
|
||||
filter::set_filter_ev_interference_amount( self, 4, amount );
|
||||
filter::enable_filter_ev_interference( self, 4 );
|
||||
|
||||
while ( GetTime() <= startTime + fadeoutTime * 1000 && isAlive( self ) )
|
||||
{
|
||||
ratio = ( GetTime() - startTime ) / ( fadeoutTime * 1000 );
|
||||
currentValue = LerpFloat( amount, 0, ratio );
|
||||
setfilterpassconstant( localClientNum, 4, 0, 0, currentValue ); // use code function instead of script wrapper cause player can be undefined
|
||||
|
||||
wait .016;
|
||||
}
|
||||
|
||||
setfilterpassenabled( localClientNum, 4, 0, false );
|
||||
}
|
||||
|
||||
function update_trophy_system_state( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
|
||||
{
|
||||
self thread set_trophy_state( localClientNum, newval === 1 );
|
||||
}
|
||||
|
||||
function set_trophy_state( localClientNum, isOn )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
self notify( "stop_set_trophy_state" );
|
||||
self endon( "stop_set_trophy_state" );
|
||||
|
||||
if ( isdefined( self.trophydestroy_fx_handle ) )
|
||||
{
|
||||
StopFX( localClientNum, self.trophydestroy_fx_handle );
|
||||
}
|
||||
|
||||
if ( isdefined( self.trophylight_fx_handle ) )
|
||||
{
|
||||
StopFX( localClientNum, self.trophylight_fx_handle );
|
||||
}
|
||||
|
||||
vehicle::wait_for_DObj( localClientNum );
|
||||
|
||||
if( isdefined( self.scriptbundlesettings ) )
|
||||
{
|
||||
settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
}
|
||||
|
||||
if ( !isdefined( settings ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isOn === 1 )
|
||||
{
|
||||
warmuptime = (isdefined(settings.trophywarmup)?settings.trophywarmup:0.1);
|
||||
|
||||
start = GetTime();
|
||||
interval = 0.3;
|
||||
while ( GetTime() <= start + warmuptime * 1000 )
|
||||
{
|
||||
if ( isdefined( settings.trophylight_fx_1 ) && isdefined( settings.trophylight_tag_1 ) )
|
||||
{
|
||||
self.trophylight_fx_handle = PlayFXOnTag( localClientNum, settings.trophylight_fx_1, self, settings.trophylight_tag_1 );
|
||||
}
|
||||
|
||||
wait 0.05;
|
||||
|
||||
if ( isdefined( self.trophylight_fx_handle ) )
|
||||
{
|
||||
StopFX( localClientNum, self.trophylight_fx_handle );
|
||||
}
|
||||
|
||||
wait max( interval, 0.05 );
|
||||
interval *= 0.8;
|
||||
}
|
||||
|
||||
if ( isdefined( settings.trophylight_fx_1 ) && isdefined( settings.trophylight_tag_1 ) )
|
||||
{
|
||||
self.trophylight_fx_handle = PlayFXOnTag( localClientNum, settings.trophylight_fx_1, self, settings.trophylight_tag_1 );
|
||||
}
|
||||
|
||||
self.trophy_on = true;
|
||||
|
||||
self PlayLoopSound ( "wpn_trophy_spin_loop");
|
||||
|
||||
rate = 0.0;
|
||||
while ( isdefined( settings.trophyanim ) && rate < 1 )
|
||||
{
|
||||
rate += 0.02;
|
||||
self SetAnim( settings.trophyanim, 1.0, 0.1, rate );
|
||||
{wait(.016);};
|
||||
}
|
||||
self SetAnim( settings.trophyanim, 1.0, 0.1, 1.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
self.trophy_on = false;
|
||||
|
||||
self StopAllLoopSounds();
|
||||
|
||||
if ( isdefined( settings.trophyanim ) )
|
||||
{
|
||||
self SetAnim( settings.trophyanim, 0.0, 0.2, 1.0 );
|
||||
}
|
||||
|
||||
if ( isdefined( settings.trophydestroyfx ) )
|
||||
{
|
||||
self.trophydestroy_fx_handle = PlayFXOnTag( localClientNum, settings.trophydestroyfx, self, "tag_target_lower" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function wait_for_bullet_impact( localClientNum )
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
|
||||
if( isdefined( self.scriptbundlesettings ) )
|
||||
{
|
||||
settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
self waittill( "damage", attacker, impactPos, effectDir, partname );
|
||||
if( partName == "tag_target_lower" || partName == "tag_target_upper" || partName == "tag_defense_active" || partName == "tag_body_animate" )
|
||||
{
|
||||
if( self.trophy_on )
|
||||
{
|
||||
if( IsDefined( attacker ) && attacker IsPlayer() && attacker.team != self.team )
|
||||
{
|
||||
PlayFx( localClientNum, settings.weakspotfx, impactPos, effectDir );
|
||||
self playsound( 0, "veh_quadtank_panel_hit" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,89 @@
|
||||
Line truncated
|
||||
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
|
||||
#namespace raps;
|
||||
|
||||
function autoexec main()
|
||||
{
|
||||
// clientfield setup
|
||||
clientfield::register( "vehicle", "raps_side_deathfx", 1, 1, "int", &do_side_death_fx, !true, !true );
|
||||
}
|
||||
|
||||
function adjust_side_death_dir_if_trace_fail( origin, side_dir, fxlength, up_dir )
|
||||
{
|
||||
end = origin + side_dir * fxlength;
|
||||
trace = BulletTrace( origin, end, false, self, true );
|
||||
|
||||
if ( trace["fraction"] < 1.0 )
|
||||
{
|
||||
new_side_dir = VectorNormalize( side_dir + up_dir );
|
||||
end = origin + new_side_dir * fxlength;
|
||||
new_trace = BulletTrace( origin, end, false, self, true );
|
||||
if ( new_trace["fraction"] > trace["fraction"] )
|
||||
{
|
||||
side_dir = new_side_dir;
|
||||
}
|
||||
}
|
||||
|
||||
return side_dir;
|
||||
}
|
||||
|
||||
function do_side_death_fx(localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump)
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
|
||||
vehicle::wait_for_DObj( localClientNum );
|
||||
|
||||
radius = 1;
|
||||
fxlength = 40;
|
||||
fxtag = "tag_body";
|
||||
|
||||
if( newVal && !bInitialSnap )
|
||||
{
|
||||
if(!isdefined(self.settings))
|
||||
{
|
||||
self.settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
}
|
||||
|
||||
forward_direction = AnglesToForward( self.angles );
|
||||
up_direction = AnglesToUp( self.angles );
|
||||
|
||||
origin = self GetTagOrigin( fxtag );
|
||||
if ( !isdefined( origin ) )
|
||||
{
|
||||
origin = self.origin + (0,0,15);
|
||||
}
|
||||
|
||||
right_direction = VectorCross(forward_direction, up_direction);
|
||||
right_direction = VectorNormalize(right_direction);
|
||||
right_start = origin + right_direction * radius;
|
||||
right_direction = adjust_side_death_dir_if_trace_fail( right_start, right_direction, fxlength, up_direction );
|
||||
|
||||
left_direction = -right_direction;
|
||||
left_start = origin + left_direction * radius;
|
||||
left_direction = adjust_side_death_dir_if_trace_fail( left_start, left_direction, fxlength, up_direction );
|
||||
|
||||
if( isdefined( self.settings.sideExplosionFx ) )
|
||||
{
|
||||
playfx(localClientNum, self.settings.sideExplosionFx, right_start, right_direction );
|
||||
playfx(localClientNum, self.settings.sideExplosionFx, left_start, left_direction );
|
||||
}
|
||||
|
||||
if( isdefined( self.settings.killedexplosionfx ) )
|
||||
{
|
||||
playfx(localClientNum, self.settings.killedexplosionfx, origin, (0,0,1) );
|
||||
}
|
||||
|
||||
self PlaySound( localClientNum, self.deathfxsound );
|
||||
|
||||
if ( isdefined( self.deathquakescale ) && self.deathquakescale > 0 )
|
||||
{
|
||||
self Earthquake( self.deathquakescale, self.deathquakeduration, origin, self.deathquakeradius );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,30 @@
|
||||
Line truncated
|
||||
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\callbacks_shared;
|
||||
|
||||
#using scripts\shared\weapons\spike_charge_siegebot;
|
||||
|
||||
#namespace siegebot;
|
||||
|
||||
function autoexec main()
|
||||
{
|
||||
vehicle::add_vehicletype_callback( "siegebot", &_setup_ );
|
||||
}
|
||||
|
||||
function _setup_( localClientNum )
|
||||
{
|
||||
if( isdefined( self.scriptbundlesettings ) )
|
||||
{
|
||||
settings = struct::get_script_bundle( "vehiclecustomsettings", self.scriptbundlesettings );
|
||||
}
|
||||
|
||||
if ( !isdefined( settings ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,45 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\clientfield_shared;
|
||||
#using scripts\shared\filter_shared;
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\vehicle_shared;
|
||||
#using scripts\shared\archetype_shared\archetype_shared;
|
||||
|
||||
Line truncated
|
||||
|
||||
|
||||
#namespace wasp;
|
||||
|
||||
function autoexec __init__sytem__() { system::register("wasp",&__init__,undefined,undefined); }
|
||||
|
||||
function __init__()
|
||||
{
|
||||
// clientfield setup
|
||||
clientfield::register( "vehicle", "rocket_wasp_hijacked", 1, 1, "int", &handle_lod_display_for_driver, !true, !true );
|
||||
|
||||
level.sentinelBundle = struct::get_script_bundle( "killstreak", "killstreak_sentinel" );
|
||||
if( isdefined( level.sentinelBundle ) )
|
||||
vehicle::add_vehicletype_callback( level.sentinelBundle.ksVehicle, &spawned );
|
||||
}
|
||||
|
||||
function spawned( localClientNum )
|
||||
{
|
||||
self.killstreakBundle = level.sentinelBundle;
|
||||
}
|
||||
|
||||
function handle_lod_display_for_driver(localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump)
|
||||
{
|
||||
self endon( "entityshutdown" );
|
||||
if( isDefined( self ) )
|
||||
{
|
||||
if( self IsLocalClientDriver( localClientNum ))
|
||||
{
|
||||
self SetHighDetail( true );
|
||||
wait 0.05;
|
||||
self vehicle::lights_off( localClientNum );
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user