649 lines
17 KiB
Plaintext
649 lines
17 KiB
Plaintext
#include maps\mp\alien\_utility;
|
|
|
|
ALIEN_CHARGE_ATTACK_DISTANCE_MAX = 500;
|
|
ALIEN_CHARGE_ATTACK_DISTANCE_MIN = 350;
|
|
ALIEN_CHARGE_COOLDOWN_MSEC = 12000;
|
|
|
|
ALIEN_SLAM_MIN_DISTANCE = 175;
|
|
ALIEN_SLAM_RADIUS = 250;
|
|
ELITE_SWIPE_OFFSET_XY = 125; // how far in front of player we want to swipe (so the player can actually see it.)
|
|
ELITE_MAX_SWIPE_DAMAGE_DIST = 175;
|
|
|
|
ANGERED_DAMAGE_SCALAR = 1.25;
|
|
|
|
ELITE_ATTACK_START_SOUND = "";
|
|
CHARGE_HIT_SOUND = "";
|
|
CHARGE_ATTACK_START_SOUND = "";
|
|
ELITE_REGEN_START_SOUND = "";
|
|
|
|
elite_approach( enemy, attack_counter )
|
|
{
|
|
/# maps\mp\agents\alien\_alien_think::debug_alien_ai_state( "elite_approach" ); #/
|
|
/# maps\mp\agents\alien\_alien_think::debug_alien_attacker_state( "attacking" ); #/
|
|
|
|
// Run near enemy
|
|
if ( DistanceSquared( enemy.origin, self.origin ) > ALIEN_CHARGE_ATTACK_DISTANCE_MAX * ALIEN_CHARGE_ATTACK_DISTANCE_MAX )
|
|
self maps\mp\agents\alien\_alien_think::run_near_enemy( ALIEN_CHARGE_ATTACK_DISTANCE_MAX, enemy );
|
|
|
|
while ( true )
|
|
{
|
|
if ( can_do_charge_attack( enemy ) )
|
|
{
|
|
return "charge";
|
|
}
|
|
else if ( run_to_slam( enemy ) )
|
|
{
|
|
return "slam";
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
run_to_slam( enemy )
|
|
{
|
|
self thread monitor_charge_range( enemy );
|
|
self thread run_to_enemy( enemy );
|
|
|
|
msg = self common_scripts\utility::waittill_any_return( "run_to_slam_complete", "in_charge_range", "enemy", "bad_path" );
|
|
if ( !self AgentCanSeeSentient( enemy ) )
|
|
return false;
|
|
|
|
return ( msg == "run_to_slam_complete" );
|
|
}
|
|
|
|
run_to_enemy( enemy )
|
|
{
|
|
enemy endon( "death" );
|
|
self endon( "enemy" );
|
|
self endon( "bad_path" );
|
|
|
|
startTime = GetTime();
|
|
|
|
self maps\mp\agents\alien\_alien_think::run_near_enemy( ALIEN_SLAM_MIN_DISTANCE, enemy );
|
|
|
|
// need to make sure a frame passes before we send the notify
|
|
if ( startTime == GetTime() )
|
|
wait 0.05;
|
|
|
|
self notify( "run_to_slam_complete" );
|
|
}
|
|
|
|
monitor_charge_range( enemy )
|
|
{
|
|
self endon( "goal_reached" );
|
|
enemy endon( "death" );
|
|
self endon( "enemy" );
|
|
self endon( "bad_path" );
|
|
|
|
chargeRangeSquared = ALIEN_CHARGE_ATTACK_DISTANCE_MIN * ALIEN_CHARGE_ATTACK_DISTANCE_MIN;
|
|
wait 0.05;
|
|
|
|
while ( true )
|
|
{
|
|
if ( DistanceSquared( self.origin, enemy.origin ) >= chargeRangeSquared )
|
|
break;
|
|
|
|
wait 0.2;
|
|
}
|
|
|
|
self notify( "in_charge_range" );
|
|
}
|
|
|
|
can_do_charge_attack( enemy )
|
|
{
|
|
if ( gettime() < self.last_charge_time + ALIEN_CHARGE_COOLDOWN_MSEC )
|
|
return false;
|
|
|
|
if ( DistanceSquared( self.origin, enemy.origin ) < ALIEN_CHARGE_ATTACK_DISTANCE_MIN * ALIEN_CHARGE_ATTACK_DISTANCE_MIN )
|
|
return false;
|
|
|
|
if ( !maps\mp\agents\_scriptedagents::CanMovePointToPoint( self.origin, enemy.origin) )
|
|
return false;
|
|
|
|
return self maps\mp\alien\_utility::is_normal_upright( anglesToUp( self.angles ) );
|
|
}
|
|
|
|
ground_slam( enemy )
|
|
{
|
|
self.melee_type = "slam";
|
|
maps\mp\agents\alien\_alien_think::alien_melee( enemy );
|
|
}
|
|
|
|
ALIEN_ELITE_GROUND_SLAM_IMPULSE = 800;
|
|
|
|
do_ground_slam( enemy )
|
|
{
|
|
self endon( "death" );
|
|
|
|
self maps\mp\agents\alien\_alien_anim_utils::turnTowardsEntity( enemy );
|
|
self ScrAgentSetOrientMode( "face enemy" );
|
|
|
|
self maps\mp\agents\alien\_alien_melee::try_preliminary_swipes( "swipe", enemy, ELITE_SWIPE_OFFSET_XY, ELITE_MAX_SWIPE_DAMAGE_DIST );
|
|
self maps\mp\agents\_scriptedagents::PlayAnimNUntilNotetrack( "attack_melee_swipe", 2, "attack_melee", "alien_slam_big" );
|
|
|
|
min_damage = level.alien_types[ self.alien_type ].attributes[ "slam_min_damage" ];
|
|
max_damage = level.alien_types[ self.alien_type ].attributes[ "slam_max_damage" ];
|
|
|
|
if ( IsDefined( self.elite_angered ) )
|
|
{
|
|
min_damage *= get_angered_damage_scalar();
|
|
max_damage *= get_angered_damage_scalar();
|
|
}
|
|
self area_damage_and_impulse( ALIEN_SLAM_RADIUS, min_damage, max_damage, ALIEN_ELITE_GROUND_SLAM_IMPULSE );
|
|
self maps\mp\agents\_scriptedagents::WaitUntilNotetrack( "attack_melee", "end" );
|
|
|
|
if ( !isDefined( self.elite_angered ) )
|
|
meleeSuccess = self maps\mp\agents\alien\_alien_melee::move_back( enemy, true );
|
|
self set_alien_emissive_default( 0.2 );
|
|
}
|
|
|
|
charge_attack( enemy )
|
|
{
|
|
/# maps\mp\agents\alien\_alien_think::debug_alien_ai_state( "charge_attack" ); #/
|
|
|
|
if ( enemy being_charged() )
|
|
{
|
|
wait 0.2;
|
|
return;
|
|
}
|
|
|
|
self.melee_type = "charge";
|
|
maps\mp\agents\alien\_alien_think::alien_melee( enemy );
|
|
enemy.being_charged = false;
|
|
}
|
|
|
|
angered( enemy )
|
|
{
|
|
/# maps\mp\agents\alien\_alien_think::debug_alien_ai_state( "health_regen" ); #/
|
|
|
|
self.melee_type = "angered";
|
|
maps\mp\agents\alien\_alien_think::alien_melee( enemy );
|
|
}
|
|
|
|
do_charge_attack( enemy )
|
|
{
|
|
self endon( "death" );
|
|
|
|
enemy.being_charged = true;
|
|
self.last_charge_time = gettime();
|
|
self set_alien_emissive( 0.2, 1.0 );
|
|
self maps\mp\agents\alien\_alien_anim_utils::turnTowardsEntity( enemy );
|
|
|
|
self ScrAgentSetAnimMode( "anim deltas" );
|
|
self ScrAgentSetPhysicsMode( "gravity" );
|
|
self ScrAgentSetOrientMode( "face enemy" );
|
|
|
|
charge_start_index = get_charge_start_index();
|
|
self maps\mp\agents\_scriptedagents::PlayAnimNAtRateUntilNotetrack( "charge_attack_start", charge_start_index, 1.15, "charge_attack_start", "end", ::chargeStartNotetrackHandler );
|
|
|
|
if ( isAlive( enemy ) && can_see_enemy( enemy ) )
|
|
{
|
|
self thread track_enemy( enemy );
|
|
self SetAnimState( "charge_attack", charge_start_index, 1.0);
|
|
|
|
result = watch_charge_hit( enemy, charge_start_index );
|
|
self notify( "charge_complete" );
|
|
self ScrAgentSetOrientMode( "face angle abs", self.angles );
|
|
|
|
if ( !IsDefined( result ) ) // enemy died mid charge, play stop anim
|
|
result = "fail";
|
|
|
|
switch ( result )
|
|
{
|
|
case "success":
|
|
self maps\mp\agents\_scriptedagents::SafelyPlayAnimNAtRateUntilNotetrack( "charge_attack_bump", charge_start_index, 1.0, "charge_attack_bump", "end", ::chargeEndNotetrackHandler );
|
|
break;
|
|
case "fail":
|
|
self play_stop_anim( charge_start_index );
|
|
break;
|
|
default:
|
|
assertmsg( "Unknown charge hit result: " + result );
|
|
break;
|
|
}
|
|
self ScrAgentSetAnimMode( "code_move" );
|
|
}
|
|
|
|
self set_alien_emissive_default( 0.2 );
|
|
}
|
|
|
|
can_see_enemy( enemy )
|
|
{
|
|
return SightTracePassed( self getEye(), enemy getEye(), false, self );
|
|
}
|
|
|
|
track_enemy( enemy )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "charge_complete" );
|
|
|
|
STOP_TRACKING_DISTANCE_SQ = 325 * 325;
|
|
self.charge_tracking_enemy = true;
|
|
|
|
while ( true )
|
|
{
|
|
if ( DistanceSquared( self.origin, enemy.origin ) < STOP_TRACKING_DISTANCE_SQ )
|
|
break;
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
self ScrAgentSetOrientMode( "face angle abs", self.angles );
|
|
self.charge_tracking_enemy = false;
|
|
}
|
|
|
|
play_stop_anim( anim_index )
|
|
{
|
|
FORWARD_CLEARANCE = 120;
|
|
|
|
if ( hit_geo( FORWARD_CLEARANCE ) )
|
|
go_hit_geo();
|
|
else
|
|
self maps\mp\agents\_scriptedagents::SafelyPlayAnimNAtRateUntilNotetrack( "charge_attack_stop", anim_index, 1.0, "charge_attack_stop", "end", ::chargeEndNotetrackHandler );
|
|
}
|
|
|
|
go_hit_geo()
|
|
{
|
|
hit_geo_index = get_hit_geo_index();
|
|
hit_geo_anim = self GetAnimEntry( "charge_hit_geo", hit_geo_index );
|
|
notetrack_time = GetNotetrackTimes( hit_geo_anim, "forward_end" );
|
|
forward_delta = length( GetMoveDelta( hit_geo_anim, 0.0, notetrack_time[ 0 ] ) );
|
|
|
|
while ( true )
|
|
{
|
|
if ( hit_geo( forward_delta ) )
|
|
break;
|
|
|
|
common_scripts\utility::waitframe();
|
|
}
|
|
self maps\mp\agents\_scriptedagents::SafelyPlayAnimNAtRateUntilNotetrack( "charge_hit_geo", hit_geo_index, 1.0, "charge_hit_geo", "end", ::chargeEndNotetrackHandler );
|
|
}
|
|
|
|
watch_charge_hit( enemy, anim_index )
|
|
{
|
|
self endon( "death" );
|
|
enemy endon( "death" );
|
|
|
|
MIN_CHARGE_TIME = 3.0;
|
|
MAX_CHARGE_TIME = 6.0;
|
|
FRAME_TIME = 0.05;
|
|
|
|
chargeStopAnim = self GetAnimEntry( "charge_attack_stop", anim_index );
|
|
num_loops = int( randomFloatRange( MIN_CHARGE_TIME, MAX_CHARGE_TIME ) / FRAME_TIME );
|
|
animDistance = Length( GetMoveDelta( chargeStopAnim ) );
|
|
animLength = GetAnimLength( chargeStopAnim );
|
|
shortLookAheadDistance = (animDistance / animLength) * FRAME_TIME * 3;
|
|
|
|
for ( i = 0; i < num_loops; i++ )
|
|
{
|
|
if ( hit_player() )
|
|
return "success";
|
|
|
|
if ( self.charge_tracking_enemy )
|
|
lookAheadDistance = Distance( enemy.origin, self.origin);
|
|
else
|
|
lookAheadDistance = shortlookAheadDistance;
|
|
|
|
if ( hit_geo( lookAheadDistance ) )
|
|
return "fail";
|
|
|
|
if ( !self.charge_tracking_enemy && missed_enemy( enemy ) )
|
|
return "fail";
|
|
|
|
common_scripts\utility::waitframe();
|
|
}
|
|
return "fail"; //time out
|
|
}
|
|
|
|
ALIEN_ELITE_CHARGE_IMPULSE = 1200;
|
|
|
|
hit_player()
|
|
{
|
|
CHARGE_HIT_DIST = 140;
|
|
|
|
foreach( player in level.players )
|
|
{
|
|
if ( distanceSquared ( self.origin, player.origin ) < CHARGE_HIT_DIST * CHARGE_HIT_DIST
|
|
&& might_hit_enemy( player )
|
|
)
|
|
{
|
|
self maps\mp\agents\alien\_alien_melee::melee_DoDamage( player, "charge" );
|
|
player player_fly_back( ALIEN_ELITE_CHARGE_IMPULSE, vectorNormalize( player.origin - self.origin ));
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
hit_geo( lookAheadDistance )
|
|
{
|
|
OFFSET_HEIGHT = 18.0;
|
|
COS_30 = 0.866;
|
|
|
|
traceStart = self.origin + ( 0, 0, OFFSET_HEIGHT );
|
|
traceEnd = traceStart + AnglesToForward(self.angles ) * lookAheadDistance;
|
|
|
|
hitInfo = self AIPhysicsTrace( traceStart, traceEnd, self.radius, self.height - OFFSET_HEIGHT, true, true );
|
|
return hitInfo["fraction"] < 1.0 && hitInfo["normal"][2] < COS_30;
|
|
}
|
|
|
|
player_fly_back( impulse, direction )
|
|
{
|
|
MAX_SPEED = 600.0;
|
|
original_velocity = self GetVelocity();
|
|
impluse_velocity = direction * impulse;
|
|
|
|
final_velocity = ( original_velocity + impluse_velocity ) * ( 1, 1, 0 );
|
|
speed = Length( final_velocity );
|
|
|
|
if ( speed >= 400.0 )
|
|
{
|
|
final_velocity = VectorNormalize( final_velocity ) * 400.0;
|
|
}
|
|
|
|
self SetVelocity( final_velocity );
|
|
}
|
|
|
|
might_hit_enemy( enemy )
|
|
{
|
|
CONE_LIMIT = 0.866; //cos( 30 )
|
|
|
|
can_see_enemy = can_see_enemy( enemy );
|
|
|
|
self_to_enemy = vectorNormalize ( enemy.origin - self.origin );
|
|
self_forward = anglesToForward( self.angles);
|
|
enemy_in_front_cone = VectorDot( self_to_enemy, self_forward ) > CONE_LIMIT;
|
|
|
|
return ( can_see_enemy && enemy_in_front_cone );
|
|
}
|
|
|
|
missed_enemy( enemy )
|
|
{
|
|
pastEnemyDistance = -256;
|
|
can_see_enemy = can_see_enemy( enemy );
|
|
|
|
if ( !can_see_enemy )
|
|
return true;
|
|
|
|
self_to_enemy = enemy.origin - self.origin;
|
|
self_forward = anglesToForward( self.angles);
|
|
distancePast = VectorDot( self_to_enemy, self_forward );
|
|
|
|
if ( distancePast > 0 )
|
|
return false;
|
|
|
|
return distancePast < pastEnemyDistance;
|
|
}
|
|
|
|
being_charged()
|
|
{
|
|
return ( isDefined( self.being_charged ) && self.being_charged );
|
|
}
|
|
|
|
get_charge_start_index()
|
|
{
|
|
animWeights = [ 40 /*Entry 0: ex. alien_queen_charge_start*/,
|
|
30 /*Entry 1: ex. alien_queen_charge_start_v2*/,
|
|
30 /*Entry 2: ex. alien_queen_charge_start_v3*/
|
|
];
|
|
return get_weighted_index( "charge_attack_start", animWeights );
|
|
}
|
|
|
|
get_hit_geo_index()
|
|
{
|
|
animWeights = [ 15 /*alien_drone_run_bump_heavy*/,
|
|
25 /*alien_drone_run_bump_medium*/,
|
|
60 /*alien_drone_run_bump_light*/
|
|
];
|
|
return get_weighted_index( "charge_hit_geo", animWeights );
|
|
}
|
|
|
|
get_weighted_index( animState, animWeights )
|
|
{
|
|
nEntries = self GetAnimEntryCount( animState );
|
|
assert( animWeights.size == nEntries );
|
|
return maps\mp\alien\_utility::GetRandomIndex( animWeights );
|
|
}
|
|
|
|
load_queen_fx()
|
|
{
|
|
level._effect[ "queen_shield_impact" ] = Loadfx( "fx/impacts/large_metalhit_1" );
|
|
level._effect[ "queen_ground_spawn" ] = LoadFX( "vfx/gameplay/alien/vfx_alien_elite_ground_spawn" );
|
|
}
|
|
|
|
elite_init()
|
|
{
|
|
self.next_health_regen_time = getTime();
|
|
self.last_charge_time = gettime();
|
|
if ( !isPlayingSolo() )
|
|
{
|
|
self.elite_angered = true;
|
|
self.moveplaybackrate = 1.2;
|
|
}
|
|
}
|
|
|
|
activate_angered_state()
|
|
{
|
|
prepare_to_regenerate();
|
|
|
|
CONST_HEALTH_REGEN_TIME = 10.0; // in sec
|
|
CONST_HEALTH_REGEN_COOL_DOWN = 60000; // in ms
|
|
|
|
self.elite_angered = true; // Regen is now an "angered" state
|
|
self.moveplaybackrate = 1.2;
|
|
|
|
activate_health_regen_shield();
|
|
}
|
|
|
|
activate_health_regen()
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
|
|
prepare_to_regenerate();
|
|
|
|
CONST_HEALTH_REGEN_TIME = 10.0; // in sec
|
|
CONST_HEALTH_REGEN_COOL_DOWN = 60000; // in ms
|
|
|
|
self.next_health_regen_time = getTime() + CONST_HEALTH_REGEN_COOL_DOWN;
|
|
|
|
thread play_health_regen_anim();
|
|
|
|
activate_health_regen_shield();
|
|
thread queen_health_regen( CONST_HEALTH_REGEN_TIME );
|
|
|
|
self common_scripts\utility::waittill_any_timeout( CONST_HEALTH_REGEN_TIME, "stop_queen_health_regen" );
|
|
|
|
disable_health_regen_shield();
|
|
}
|
|
|
|
ALIEN_ELITE_REGEN_IMPULSE_RADIUS = 200;
|
|
ALIEN_ELITE_REGEN_IMPULSE = 800;
|
|
|
|
prepare_to_regenerate()
|
|
{
|
|
self ScrAgentSetAnimMode( "anim deltas" );
|
|
self ScrAgentSetOrientMode( "face angle abs", self.angles );
|
|
|
|
maps\mp\agents\_scriptedagents::PlayAnimNAtRateUntilNotetrack( "prepare_to_regen", 0, 2.0, "prepare_to_regen", "end" );
|
|
|
|
// TODO: Play the FX off of a notetrack when we have the real prepare_to_regen anim
|
|
// maps\mp\agents\_scriptedagents::PlayAnimUntilNotetrack( "prepare_to_regen", "prepare_to_regen", "impulse", ::handle_pre_regen_notetracks );
|
|
// PlayFX( level._effect[ "queen_regen_AoE" ], self.origin, AnglesToForward( self.angles ), AnglesToUp( self.angles ) );
|
|
|
|
min_damage = level.alien_types[ self.alien_type ].attributes[ "explode_min_damage" ];
|
|
max_damage = level.alien_types[ self.alien_type ].attributes[ "explode_max_damage" ];
|
|
|
|
if ( IsDefined( self.elite_angered ) )
|
|
{
|
|
min_damage *= get_angered_damage_scalar();
|
|
max_damage *= get_angered_damage_scalar();
|
|
}
|
|
area_damage_and_impulse( ALIEN_ELITE_REGEN_IMPULSE_RADIUS, min_damage, max_damage, ALIEN_ELITE_REGEN_IMPULSE );
|
|
}
|
|
|
|
play_health_regen_anim()
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
self endon ( "stop_queen_health_regen" );
|
|
|
|
self ScrAgentSetAnimMode( "anim deltas" );
|
|
self ScrAgentSetOrientMode( "face angle abs", self.angles );
|
|
|
|
anim_state = "regen";
|
|
|
|
while ( true )
|
|
{
|
|
maps\mp\agents\_scriptedagents::PlayAnimUntilNotetrack( anim_state, anim_state, "end" );
|
|
}
|
|
}
|
|
|
|
queen_health_regen( CONST_HEALTH_REGEN_TIME )
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
self endon ( "stop_queen_health_regen" );
|
|
|
|
CONST_HEALTH_REGEN_INTERVAL = 1.0; // in sec
|
|
|
|
num_of_regen = int ( CONST_HEALTH_REGEN_TIME / CONST_HEALTH_REGEN_INTERVAL );
|
|
total_health_to_regen = ( self.maxhealth - self.health ) / 2; // regen only to up the midpoint between current health and max health
|
|
health_each_regen = int ( total_health_to_regen / num_of_regen );
|
|
|
|
for ( i = 0; i < num_of_regen; i++ )
|
|
{
|
|
wait ( CONST_HEALTH_REGEN_INTERVAL );
|
|
self.health += health_each_regen;
|
|
}
|
|
}
|
|
|
|
activate_health_regen_shield()
|
|
{
|
|
/*self.shield_model = deploy_health_regen_shield();
|
|
self.shield_FX = PlayLoopedFX ( level._effect[ "queen_shield" ], 10.0, self.origin,0, AnglesToForward(self.angles), (0,0,1) );
|
|
|
|
self.shield_model thread clean_up_on_owner_death( self );
|
|
self.shield_FX thread clean_up_on_owner_death( self );*/
|
|
}
|
|
|
|
disable_health_regen_shield()
|
|
{
|
|
self SetScriptablePartState( "body", "normal" );
|
|
/*
|
|
self.shield_model delete();
|
|
self.shield_FX delete();*/
|
|
}
|
|
|
|
clean_up_on_owner_death( owner )
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
owner endon ( "stop_queen_health_regen" );
|
|
|
|
owner waittill ( "death" );
|
|
self delete();
|
|
}
|
|
|
|
deploy_health_regen_shield()
|
|
{
|
|
shield = spawn ( "script_model", self.origin );
|
|
shield setModel ( "alien_shield_bubble_distortion" );
|
|
shield linkTo ( self, "tag_origin" );
|
|
shield setCanDamage ( true );
|
|
|
|
return shield;
|
|
}
|
|
|
|
//<TODO JC> Remove this as the impact effect will eventually be played from the character model's surface type
|
|
play_shield_impact_fx( vPoint, vDir )
|
|
{
|
|
if ( isDefined ( vDir ) )
|
|
forward_vector = vDir * -1;
|
|
else
|
|
forward_vector = anglesToForward( self.angles );
|
|
|
|
up_vector = anglesToUp ( vectorToAngles ( forward_vector ) );
|
|
PlayFX( level._effect[ "queen_shield_impact" ], vPoint, forward_vector, up_vector );
|
|
}
|
|
|
|
ALIEN_ELITE_EXPLOSIVE_RESISTANCE = 0.5;
|
|
|
|
eliteDamageProcessing( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
|
|
{
|
|
// Explosive resistance
|
|
switch ( sMeansOfDeath )
|
|
{
|
|
case "MOD_EXPLOSIVE":
|
|
case "MOD_GRENADE_SPLASH":
|
|
case "MOD_GRENADE":
|
|
case "MOD_PROJECTILE":
|
|
case "MOD_PROJECTILE_SPLASH":
|
|
iDamage *= ALIEN_ELITE_EXPLOSIVE_RESISTANCE;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return iDamage;
|
|
}
|
|
|
|
ALIEN_ELITE_JUMP_IMPULSE = 500;
|
|
|
|
on_jump_impact()
|
|
{
|
|
DAMAGE_RADIUS = 256;
|
|
MAX_DAMAGE = 30;
|
|
MIN_DAMAGE = 10;
|
|
|
|
alienUp = anglesToUp( self.angles );
|
|
if ( !maps\mp\alien\_utility::is_normal_upright( alienUp ) )
|
|
return;
|
|
|
|
area_damage_and_impulse( DAMAGE_RADIUS, MIN_DAMAGE, MAX_DAMAGE, ALIEN_ELITE_JUMP_IMPULSE );
|
|
}
|
|
|
|
area_damage_and_impulse( damage_radius, min_damage, max_damage, impulse )
|
|
{
|
|
RadiusDamage( self.origin, damage_radius, max_damage, min_damage, self, "MOD_EXPLOSIVE", "alienrhinoslam_mp" );
|
|
damage_radius_squared = damage_radius * damage_radius;
|
|
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( DistanceSquared( self.origin, player.origin ) > damage_radius_squared )
|
|
continue;
|
|
|
|
pushDirection = VectorNormalize(player.origin - self.origin );
|
|
player player_fly_back( impulse, pushDirection );
|
|
}
|
|
}
|
|
|
|
get_angered_damage_scalar()
|
|
{
|
|
return ANGERED_DAMAGE_SCALAR;
|
|
}
|
|
|
|
chargeStartNotetrackHandler( note, animState, animIndex, animTime )
|
|
{
|
|
switch ( note )
|
|
{
|
|
case "queen_roll_start":
|
|
self playLoopSound( "queen_roll" );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
chargeEndNotetrackHandler( note, animState, animIndex, animTime )
|
|
{
|
|
switch ( note )
|
|
{
|
|
case "queen_roll_stop":
|
|
self stopLoopSound( "queen_roll" );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} |