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

314 lines
17 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\callbacks_shared;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\flagsys_shared;
#using scripts\shared\killcam_shared;
#using scripts\shared\player_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\visionset_mgr_shared;
#using scripts\shared\weapons\_weaponobjects;
#precache( "fx", "weapon/fx_lightninggun_arc" );
#namespace lightninggun;
function init_shared()
{
level.weaponLightningGun = GetWeapon( "hero_lightninggun" );
level.weaponLightningGunArc = GetWeapon( "hero_lightninggun_arc" );
level.weaponLightningGunKillcamTime = GetDvarFloat( "scr_lightningGunKillcamTime", 0.35 );
level.weaponLightningGunKillcamDecelPercent = GetDvarFloat( "scr_lightningGunKillcamDecelPercent", 0.25 );
level.weaponLightningGunKillcamOffset = GetDvarFloat( "scr_lightningGunKillcamOffset", 150.0 );
level.lightninggun_arc_range = 300;
level.lightninggun_arc_range_sq = level.lightninggun_arc_range * level.lightninggun_arc_range;
level.lightninggun_arc_speed = 650;
level.lightninggun_arc_speed_sq = level.lightninggun_arc_speed * level.lightninggun_arc_speed;
level.lightninggun_arc_fx_min_range = 1;
level.lightninggun_arc_fx_min_range_sq = level.lightninggun_arc_fx_min_range * level.lightninggun_arc_fx_min_range;
level._effect["lightninggun_arc"] = "weapon/fx_lightninggun_arc";
callback::add_weapon_damage( level.weaponLightningGun, &on_damage_lightninggun );
/#
level thread update_dvars();
#/
}
/#
function update_dvars()
{
while(1)
{
wait(1);
level.weaponLightningGunKillcamTime = GetDvarFloat( "scr_lightningGunKillcamTime", 0.35 );
level.weaponLightningGunKillcamDecelPercent = GetDvarFloat( "scr_lightningGunKillcamDecelPercent", 0.25 );
level.weaponLightningGunKillcamOffset = GetDvarFloat( "scr_lightningGunKillcamOffset", 150.0 );
}
}
#/
function lightninggun_start_damage_effects( eAttacker )
{
self endon( "disconnect" );
/#
If ( IsGodMode( self ) )
{
return;
}
#/
self SetElectrifiedState( true );
self.electrifiedBy = eAttacker;
self PlayRumbleOnEntity( "lightninggun_victim" );
wait( 2 );
self.electrifiedBy = undefined;
self SetElectrifiedState( false );
}
function lightninggun_arc_killcam( arc_source_pos, arc_target, arc_target_pos, original_killcam_ent, waitTime )
{
arc_target.killcamKilledByEnt = create_killcam_entity( original_killcam_ent.origin, original_killcam_ent.angles, level.weaponLightningGunArc );
arc_target.killcamKilledByEnt killcam::store_killcam_entity_on_entity(original_killcam_ent);
arc_target.killcamKilledByEnt killcam_move( arc_source_pos, arc_target_pos, waitTime );
}
function lightninggun_arc_fx( arc_source_pos, arc_target, arc_target_pos, distanceSq, original_killcam_ent )
{
if ( !isdefined( arc_target ) || !isdefined( original_killcam_ent ) )
return;
waitTime = 0.25;
if ( level.lightninggun_arc_speed_sq > 100 && distanceSq > 1 )
{
waitTime = distanceSq / level.lightninggun_arc_speed_sq;
}
lightninggun_arc_killcam( arc_source_pos, arc_target, arc_target_pos, original_killcam_ent, waitTime );
killcamEntity = arc_target.killcamKilledByEnt;
if ( !isdefined( arc_target ) || !isdefined( original_killcam_ent ) )
return;
if ( distanceSq < level.lightninggun_arc_fx_min_range_sq )
{
wait( waitTime );
killcamEntity delete();
if ( isdefined( arc_target ) )
{
arc_target.killcamKilledByEnt = undefined;
}
//Not playing arcing FX. Enemies too close
return;
}
// this needs to be clientsided.
fxOrg = spawn( "script_model", arc_source_pos );
fxOrg SetModel( "tag_origin" );
fx = PlayFxOnTag( level._effect["lightninggun_arc"], fxOrg, "tag_origin" );
playsoundatposition( "wpn_lightning_gun_bounce", fxOrg.origin );
fxOrg MoveTo( arc_target_pos, waitTime );
fxOrg waittill( "movedone" );
util::wait_network_frame();
util::wait_network_frame();
util::wait_network_frame();
fxOrg delete();
killcamEntity delete();
if ( isdefined( arc_target ) )
{
arc_target.killcamKilledByEnt = undefined;
}
}
function lightninggun_arc( delay, eAttacker, arc_source, arc_source_origin, arc_source_pos, arc_target, arc_target_pos, distanceSq )
{
if ( delay )
{
wait( delay );
if ( !IsDefined( arc_target ) || !IsAlive( arc_target ) )
{
return;
}
// make sure we're still in range after the delay
distanceSq = DistanceSquared( arc_target.origin, arc_source_origin );
if ( distanceSq > level.lightninggun_arc_range_sq )
{
return;
}
}
if ( !isdefined( arc_source ) )
{
return;
}
if ( !isdefined( arc_source.killcamKilledByEnt ) )
{
return;
}
level thread lightninggun_arc_fx( arc_source_pos, arc_target, arc_target_pos, distanceSq, arc_source.killcamKilledByEnt );
arc_target thread lightninggun_start_damage_effects( eAttacker );
arc_target DoDamage( arc_target.health, arc_source_pos, eAttacker, arc_source, "none", "MOD_PISTOL_BULLET", 0, level.weaponLightningGunArc );
}
// arc_source_origin is the origin of the player initially hit, arc_source_pos is the pos of the tag the arc will be emanating from
function lightninggun_find_arc_targets( eAttacker, arc_source, arc_source_origin, arc_source_pos )
{
delay = 0.05;
if ( !isdefined( eAttacker ) )
return;
allEnemyAlivePlayers = util::get_other_teams_alive_players_s( eAttacker.team );
closestPlayers = ArraySort( allEnemyAlivePlayers.a, arc_source_origin, true );
foreach( player in closestPlayers )
{
if ( IsDefined( arc_source ) && player == arc_source )
{
continue;
}
if ( player player::is_spawn_protected() )
{
continue;
}
distanceSq = DistanceSquared( player.origin, arc_source_origin );
if ( distanceSq > level.lightninggun_arc_range_sq )
{
break;
}
if ( eAttacker != player && weaponobjects::friendlyFireCheck( eAttacker, player ) )
{
if ( isdefined( self ) && !player DamageConeTrace( arc_source_pos, self ) )
{
continue;
}
level thread lightninggun_arc( delay, eAttacker, arc_source, arc_source_origin, arc_source_pos, player, player GetTagOrigin( "j_spineupper" ), distanceSq );
delay += 0.05;
}
}
}
function create_killcam_entity( origin, angles, weapon )
{
killcamKilledByEnt = spawn( "script_model", origin );
killcamKilledByEnt SetModel( "tag_origin" );
killcamKilledByEnt.angles = angles;
killcamKilledByEnt SetWeapon( weapon );
return killcamKilledByEnt;
}
function killcam_move( start_origin, end_origin, time )
{
delta = end_origin - start_origin;
dist = Length( delta );
delta = VectorNormalize( delta );
move_to_dist = dist - level.weaponLightningGunKillcamOffset;
end_angles = (0,0,0);
if ( move_to_dist > 0 )
{
move_to_pos = start_origin + (delta * move_to_dist);
self MoveTo( move_to_pos, time, 0, time * level.weaponLightningGunKillcamDecelPercent );
end_angles = VectorToAngles( delta );
}
else
{
delta = end_origin - self.origin;
end_angles = VectorToAngles( delta );
}
//self RotateTo( end_angles, time, 0, time * level.weaponLightningGunKillcamDecelPercent );
}
function lightninggun_damage_response( eAttacker, eInflictor, weapon, meansOfDeath, damage )
{
source_pos = eAttacker.origin;
bolt_source_pos = eAttacker GetTagOrigin( "tag_flash" );
arc_source = self;
arc_source_origin = self.origin;
arc_source_pos = self GetTagOrigin( "j_spineupper" );
delta = arc_source_pos - bolt_source_pos;
angles = (0,0,0); //VectorToAngles( delta );
arc_source.killcamKilledByEnt = create_killcam_entity( bolt_source_pos, angles, weapon );
arc_source.killcamKilledByEnt killcam_move( bolt_source_pos, arc_source_pos, level.weaponLightningGunKillcamTime );
killcamEntity = arc_source.killcamKilledByEnt;
self thread lightninggun_start_damage_effects( eAttacker );
// self DoDamage( self.health, source_pos, eAttacker, eAttacker, "none", "MOD_PISTOL_BULLET", 0, level.weaponLightningGunArc );
wait( 2 );
if ( !IsDefined( self ) )
{
self thread lightninggun_find_arc_targets( eAttacker, undefined, arc_source_origin, arc_source_pos );
return;
}
// get latest positioning
if ( IsDefined( self.body ) )
{
arc_source_origin = self.body.origin;
arc_source_pos = self.body GetTagOrigin( "j_spineupper" );
}
self thread lightninggun_find_arc_targets( eAttacker, arc_source, arc_source_origin, arc_source_pos );
// wait the maximum amount of time that we could still be arcing. The other players
// will use this killcamEntity
wait( 0.05 * 9 );
killcamEntity delete();
if ( IsDefined( arc_source ) )
{
arc_source.killcamKilledByEnt = undefined;
}
}
function on_damage_lightninggun( eAttacker, eInflictor, weapon, meansOfDeath, damage )
{
if ( "MOD_PISTOL_BULLET" != meansOfDeath && "MOD_HEAD_SHOT" != meansOfDeath )
return;
// no additional lightning gun damage response if the player has armor on for now.
// if ( self flagsys::get( "gadget_armor_on" ) )
// return;
self thread lightninggun_damage_response( eAttacker, eInflictor, weapon, meansOfDeath, damage );
}