2024-12-11 11:28:08 +01:00

1285 lines
41 KiB
Plaintext

#include maps\mp\_utility;
//#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
#include maps\mp\alien\_utility;
#include maps\mp\alien\_perk_utility;
CONST_FALL_DAMAGE_SCALAR = 0.15;
//=======================================================
// Callback_AlienPlayerDamage
//=======================================================
Callback_AlienPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
{
// Vanguard: No damage to player when using Vanguard in any mode
if ( flag_exist( "player_using_vanguard" ) && flag( "player_using_vanguard" ) && IsDefined( self.remoteUAV ) )
{
return;
}
if(isdefined(level.ancestor_projectile_solo_scalar) && isPlayingSolo() && sWeapon == "alien_ancestor_mp")
iDamage = iDamage*level.ancestor_projectile_solo_scalar;
damageAdd = 0;
if( self maps\mp\alien\_perk_utility::has_perk( "perk_rigger", [ 0,1,2,3,4 ] ) && is_trap( eInflictor ) )
iDamage = 0;
// pet spitters can hurt the aliens both with gas cloud and spit projectile but not players
if ( IsDefined ( eAttacker ) && ( sWeapon == "alienspit_mp" || sWeapon == "alienspit_gas_mp") )
{
if ( IsDefined(eAttacker.team) && ( self.team == eAttacker.team ) )
{
return false;
}
}
current_weapon = self GetCurrentPrimaryWeapon();
// Riot shield blockable alien projectile?
blockable_weapon = ( sWeapon == "spider_beam_mp" || sWeapon == "alienspit_mp" || sWeapon == "alienspit_gas_mp" || sWeapon == "spore_beam_mp" || sWeapon == "gargoyle_beam_mp" || sWeapon == "alien_ancestor_mp" );
if ( blockable_weapon && sHitLoc == "shield" && !isDefined( self.spider_shield_block ))
self thread riotshieldAmmoDeplete();
if ( sWeapon == "spider_beam_mp" && isPlayingSolo() && isDefined( level.spider ) && !isDefined( level.spider.has_fired_beam ) )
iDamage = int( iDamage * 0.17 ); //scaling down the spider beam damage in solo play for the first beam fire only
//<TODO J.C.> Remove this special case handling when we figure out why the kill trigger fails to kill the player on contact
if ( sMeansOfDeath == "MOD_TRIGGER_HURT" )
{
maps\mp\alien\_death::onPlayerKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime );
}
else if ( shouldTakeDamage( eAttacker ) )
{
isFriendlyFire = maps\mp\gametypes\_damage::isFriendlyFire( self, eAttacker );
if ( !isFriendlyFire && isDefined( eAttacker ) && eAttacker != self )
iDamage = int( iDamage * level.cycle_damage_scalar );
if ( isDefined( eAttacker ) && eAttacker == self )
{
switch ( sWeapon )
{
case "alienmortar_strike_mp":
case "iw6_alienmk321_mp":
case "iw6_alienmk322_mp":
case "iw6_alienmk323_mp":
case "iw6_alienmk324_mp":
case "alienims_projectile_mp":
case "alienims_projectileradius_mp":
case "alienims_projectiledamage_mp":
case "switchblade_rocket_mp":
case "switchblade_baby_mp":
case "switchblade_babyfast_mp":
case "alienvulture_mp":
case "alienbetty_mp":
case "alienclaymore_mp":
case "aliensoflam_missle_mp":
case "iw6_alienmaaws_mp":
case "alien_semtex_turret_proj":
case "turret_minigun_alien_shock":
case "alienvanguard_projectile_mp":
case "alienvanguard_projectile_mini_mp":
case "iw6_alienrgm_mp":
case "iw6_alienpanzerfaust3_mp":
case "iw6_aliendlc41_mp":
case "iw6_aliendlc42_mp":
iDamage = 0;
break;
default:
if ( !is_hardcore_mode() )
iDamage = int( min( 10, iDamage * 0.05 ) ); // 10 dmg cap for self damage
else
iDamage = int( min( level.ricochetDamageMax, iDamage * 0.10 ) );
break;
}
}
else if ( isFriendlyFire )
{
if ( is_hardcore_mode() )
{
switch ( sWeapon )
{
case "alienmortar_strike_mp":
case "alienims_projectile_mp":
case "alienims_projectileradius_mp":
case "alienims_projectiledamage_mp":
case "switchblade_rocket_mp":
case "switchblade_baby_mp":
case "switchblade_babyfast_mp":
case "alienvulture_mp":
case "alienvanguard_projectile_mp":
case "alienvanguard_projectile_mini_mp":
iDamage = 0;
break;
}
if ( is_ricochet_damage() )
{
if ( IsDefined( eAttacker ) && IsPlayer( eAttacker ) && isDefined( sHitLoc ) && sHitLoc != "shield" )
{
if ( IsDefined( eInflictor ) )
eAttacker DoDamage( iDamage, ( eAttacker.origin - ( 0,0,50)), eAttacker, eInflictor, sMeansOfDeath );
else
eAttacker DoDamage( iDamage, eAttacker.origin, eAttacker );
}
iDamage = 0;
}
}
else
{
iDamage = 0;
}
}
else if ( isdefined( eAttacker )
&& isdefined( eAttacker.classname )
&& eAttacker.classname == "scriptable"
&& isdefined( eAttacker.is_hive )
&& eAttacker.is_hive )
{
// secondary damage triggered by hive explosion only does 1 dmg at a time
iDamage = 1;
}
if ( IsDefined( eAttacker ) && isAgent( eAttacker ) ) //spitters setting off claymores/betties and killing players is not desired
{
if( sWeapon == "alienbetty_mp" || sWeapon == "alienclaymore_mp" )
iDamage = 0;
}
if ( sMeansOfDeath == "MOD_EXPLOSIVE" && isDefined( eInflictor ) && isDefined( eInflictor.targetname) && ( eInflictor.targetname == "scriptable_destructible_barrel" || eInflictor.targetname == "armory_transformer" ) ) //spitters setting off Transformers
{
iDamage = 3;
}
if( sMeansOfDeath == "MOD_FALLING" )
{
if( self _hasPerk( "specialty_falldamage" ) )
{
iDamage = 0;
}
else
{
if ( iDamage > 10 )
{
if ( iDamage > ( self.health * CONST_FALL_DAMAGE_SCALAR ) )
iDamage = int( self.health * CONST_FALL_DAMAGE_SCALAR );
}
else
iDamage = 0;
}
}
if ( isDefined( eAttacker ) && eAttacker should_snare( self ) )
self applyAlienSnare();
if( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
{
if( !is_hardcore_mode() || ( eAttacker == self && shitloc == "none" ) )
iDamage = 0;
}
if ( self has_perk( "perk_medic", [3,4] ) && self.isReviving == true )
{
iDamage = Int( iDamage * self perk_GetReviveDamageScalar() );
}
if ( self has_perk( "perk_rigger", [3,4] ) && self.isRepairing == true )
{
iDamage = Int( iDamage * self perk_GetRepairDamageScalar() );
}
if( ( !isFriendlyFire || ( eAttacker == self && is_ricochet_damage() ) )&& IsDefined( self.bodyArmorHP ) && sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" && !IsDefined( self.ability_invulnerable ))
{
self.bodyArmorHP -= (iDamage + damageAdd);
if( self maps\mp\alien\_perk_utility::has_perk( "perk_rigger", [ 0,1,2,3,4 ] ) && is_trap( eInflictor ) )
iDamage = 0;
else
iDamage = 1;
damageAdd = 0;
if( self.bodyArmorHP <= 0 )
{
// since the light armor is gone, adjust the damage to be the excess damage that happens after the light armor hp is reduced
iDamage = abs( self.bodyArmorHP );
damageAdd = 0;
unsetBodyArmor();
}
if ( isDefined( eAttacker ) && eAttacker != self && eAttacker is_alien_agent() && IsDefined( self.bodyArmorHP ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "stun_armor_upgrade" ) && sMeansOfDeath == "MOD_UNKNOWN" )
{
rand = RandomIntRange( 0,100);
if ( rand <= 25 ) //only stun aliens who attack 25% of the time if wearing armor and having the stun_armor_upgrade purchasable by tokens
eAttacker thread delayed_stun_damage( self );
}
}
//no longer going through all the MP Callback_PLayerDamage_Internal scripts
//maps\mp\gametypes\_damage::Callback_PlayerDamage_internal( eInflictor, eAttacker, self, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime );
stunFraction = 0.0;
if ( isDefined ( eAttacker ) && sWeapon == "alien_minion_explosion" )
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "minion_protection_upgrade" ) )
iDamage *= 0.8; // minion_protection_upgrade scales minion damage to player by this amount
}
prestige_damage_taken_scalar = self maps\mp\alien\_prestige::prestige_getDamageTakenScalar();
iDamage *= prestige_damage_taken_scalar;
iDamage = Int( iDamage );
isUsingRemoteAndWillBeLowHealth = usingRemoteAndWillBeLowHealth ( iDamage );
if ( shouldUseInvulnerability ( iDamage, isUsingRemoteAndWillBeLowHealth ) )
{
useInvulnerability( iDamage );
}
if( IsDefined( self.ability_invulnerable ) )
{
iDamage = Int( 0 );
}
if ( iDamage > 0 )
maps\mp\alien\_hud::playPainOverlay( eAttacker, sWeapon, vDir );
if( !isFriendlyFire || is_hardcore_mode() )
{
self maps\mp\gametypes\_damage::finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
self notify( "player_damaged" );
}
self maps\mp\alien\_gamescore::update_personal_encounter_performance( maps\mp\alien\_gamescore::get_personal_score_component_name(), "damage_taken", iDamage );
// black box data tracking
if ( iDamage > 0 )
{
level.alienBBData[ "damage_taken" ] += iDamage;
// track damage done to player by attacker on attacker
if ( isdefined( eAttacker ) && IsAgent( eAttacker ) )
{
if ( !isdefined( eAttacker.damage_done ) )
eAttacker.damage_done = 0;
else
eAttacker.damage_done += iDamage;
}
self notify("dlc_vo_notify","pain", self);
if(!IsDefined(level.use_dlc_vo))
self thread maps\mp\alien\_music_and_dialog::player_pain_vo();
}
if ( iDamage > 0 && isDefined ( eAttacker ) && isDefined( level.current_challenge) )
{
if ( level.current_challenge == "take_no_damage" )
{
maps\mp\alien\_challenge::update_challenge( "take_no_damage" );
}
else if ( level.current_challenge == "no_ancestor_damage" && IsAgent( eAttacker ) && isDefined( eAttacker.alien_type ) && eAttacker.alien_type == "ancestor" )
{
level notify( "ancestor_damage_taken" );
}
else if ( level.current_challenge == "avoid_minion_explosion" && IsDefined( eAttacker.model ) && eAttacker.model != "alien_seeder" && IsDefined ( sWeapon ) && sWeapon == "alien_minion_explosion" )
{
maps\mp\alien\_challenge::update_challenge( "avoid_minion_explosion" );
}
}
}
}
delayed_stun_damage( attacker )
{
self endon( "death" );
attacker endon( "death" );
wait 0.05;
self doDamage( 2, self.origin, attacker, undefined, "MOD_MELEE" );
}
//=======================================================
// shouldUseInvulnerability
//=======================================================
shouldUseInvulnerability ( iDamage, isUsingRemoteAndWillBeLowHealth )
{
DAMAGE_BUFFER_LIMIT = 20; // If player is taking a huge amount of damage, no Invulnerability
if ( iDamage == 0 )
return false;
if ( isUsingRemoteAndWillBeLowHealth )
return true;
else
return ( self.haveInvulnerabilityAvailable && iDamage > self.health && iDamage < ( self.health + DAMAGE_BUFFER_LIMIT ) );
}
//=======================================================
// usingRemoteAndWillBeLowHealth
//=======================================================
usingRemoteAndWillBeLowHealth ( iDamage )
{
USING_REMOTE_LOW_HEALTH_RATIO = 0.2;
low_health_limit = self.maxhealth * USING_REMOTE_LOW_HEALTH_RATIO;
return ( isUsingRemote() && ( iDamage > self.health || ( self.health - iDamage ) <= low_health_limit ) );
}
//=======================================================
// stopUsingRemote
//=======================================================
stopUsingRemote()
{
self notify ( "stop_using_remote" );
}
//=======================================================
// useInvulnerability
//=======================================================
useInvulnerability( iDamage )
{
self.health = iDamage + 1; // Make sure player has 1 health left
self.haveInvulnerabilityAvailable = false;
}
//=======================================================
// shouldTakeDamage
//=======================================================
shouldTakeDamage( attacker )
{
/* if ( !is_hardcore_mode() && IsDefined ( attacker ) && attacker == self )
return false;
*/
if ( isDefined ( self.inLastStand ) && self.inLastStand )
return false;
if ( getTime() < self.damageShieldExpireTime ) // have damage shield
return false;
return true;
}
ALIEN_AP_DAMAGE_SCALAR = 2.0;
ARMOR_PIERCING_UPGRADE_SCALAR = 1.10;
is_alien_agent_damage_allowed( eInflictor, eAttacker, sWeapon, sMeansOfDeath )
{
if ( level.gameEnded )
return false;
if ( during_host_migration() )
return false;
if ( !IsDefined( self ) || !isReallyAlive( self ) )
return false;
// ignore friendly fire damage for team based modes
isSpiderWeapon = IsDefined( sWeapon ) && sWeapon == "spider_beam_mp";
if ( !isSpiderWeapon && IsDefined( eAttacker ) && IsDefined(eAttacker.team) && ( self.team == eAttacker.team ) && !alienTypeCanDoFriendlyDamage( eAttacker, sWeapon ) )
return false;
// don't let helicopters and other vehicles crush a player, if we want it to then put in a special case here
if ( IsDefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_CRUSH" && IsDefined( eInflictor ) && IsDefined( eInflictor.classname ) && eInflictor.classname == "script_vehicle" )
return false;
if ( IsDefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_FALLING" )
return false;
if ( Isdefined( self.noTriggerHurt ) && self.noTriggerHurt && IsDefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_TRIGGER_HURT" )
return false;
if ( IsDefined( eAttacker ) && IsDefined( eAttacker.classname ) && eAttacker.classname == "script_origin" && IsDefined( eAttacker.type ) && eAttacker.type == "soft_landing" )
return false;
if ( sWeapon == "killstreak_emp_mp" )
return false;
return true;
}
//=======================================================
// onAlienAgentDamaged
//=======================================================
onAlienAgentDamaged( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
{
// HACK: There is a rare case where aliens' health could be negative without actually dying. Catch that case here.
if ( self.health < 0 )
{
self suicide();
return false;
}
if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && sMeansofDeath != "MOD_MELEE" && eAttacker maps\mp\alien\_persistence::is_upgrade_enabled( "sniper_soft_upgrade" ) && getweaponclass ( sWeapon ) == "weapon_sniper" )
sHitLoc = "soft";
if ( !is_alien_agent_damage_allowed( eInflictor, eAttacker, sWeapon, sMeansOfDeath ) )
return false;
//Ark attachment damage scalars and special handling of mammoth
iDamage = scale_alien_damage_func( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
if ( IsDefined( level.custom_scale_alien_damage_func ) )
iDamage = [[level.custom_scale_alien_damage_func]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
if ( IsDefined( level.custom_OnAlienAgentDamaged_func ) )
iDamage = [[level.custom_OnAlienAgentDamaged_func]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
if ( sMeansOfDeath == "MOD_MELEE" && level.players.size == 1 ) //nerfing down the melee damage for solo games to compensate the 10% drop in healh and not have 1 hit melee kills
iDamage = Int( iDamage * 0.9 );
// burning damage (ex: propane tank or fire trap)
is_burning_damage = false;
if ( isdefined( eAttacker ) && isdefined( eAttacker.burning_victim ) && eAttacker.burning_victim )
{
is_burning_damage = eAttacker.burning_victim;
eAttacker.burning_victim = undefined;
}
if ( isdefined( eAttacker ) && isPlayer( eAttacker ) ) //arcing shock upgrades for stun ammo and melee
{
if ( sMeansOfDeath == "MOD_MELEE" )
{
if ( eAttacker maps\mp\alien\_persistence::is_upgrade_enabled( "shock_melee_upgrade" ) && is_true( eAttacker.meleeStrength ) && ( WeaponType( sWeapon ) != "riotshield" ) )
eAttacker thread stun_zap_aliens( self.origin, self, ( iDamage ), sMeansofDeath );
}
else if ( eAttacker has_stun_ammo( sWeapon ) && eAttacker maps\mp\alien\_persistence::is_upgrade_enabled( "stun_ammo_upgrade" ) && sMeansOfDeath != "MOD_UNKNOWN" )
eAttacker thread stun_zap_aliens( self.origin, self, iDamage, sMeansofDeath );
}
//armor spots scale the damage by 0.5 as defined in the mp_lochit_dmgtable.gdt
if ( isDefined( sWeapon ) && sWeapon != "alien_ims_projectile_mp" && isPlayer( eAttacker ) && eAttacker _hasPerk( "specialty_armorpiercing" ) && IsDefined( sHitloc ) && sHitLoc == "armor" )
{
if ( eAttacker maps\mp\alien\_persistence::is_upgrade_enabled( "armor_piercing_upgrade" ) )
iDamage = Int( iDamage * ALIEN_AP_DAMAGE_SCALAR * ARMOR_PIERCING_UPGRADE_SCALAR );
else
iDamage = Int( iDamage * ALIEN_AP_DAMAGE_SCALAR );
}
if ( sWeapon == "alienspit_mp" || sWeapon == "alienspit_gas_mp" )
iDamage = Int( iDamage * 5 );
//Pets do not take damage from players
if ( IsDefined( eAttacker ) && IsDefined ( self.pet ) && IsDefined(eAttacker.team) && ( self.team == eAttacker.team ) )
return false;
maps\mp\alien\_chaos::update_alien_damaged_event( sWeapon );
//if ( isPlayer( eAttacker ) )
//eAttacker check_for_special_damage( self, sWeapon , sMeansOfDeath); //play some FX if specialized ammo is used
iDamage = set_alien_damage_by_weapon_type( sMeansOfDeath, sWeapon, iDamage, eAttacker, iDFlags, vPoint, vDir, sHitLoc, timeOffset, eInflictor );
if ( isPlayer( eAttacker ) && !self is_trap( eInflictor ) )
{
iDamage = scale_alien_damage_by_perks( eAttacker, iDamage, sMeansOfDeath, sWeapon );
iDamage = scale_alien_damage_by_weapon_type( eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc );
if ( isdefined( sWeapon ) )
self thread maps\mp\alien\_achievement::update_achievement_damage_weapon( sWeapon );
}
iDamage = typeSpecificDamageProcessing( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
if( iDamage <= 0 )
return false;
if ( IsDefined( eAttacker ) && eAttacker != self && iDamage > 0 && ( !IsDefined( sHitLoc ) || sHitLoc != "shield" ) )
{
if ( is_burning_damage )
{
typeHit = "standard"; // burning damage ( ex: propane tank or fire trap )
}
else if ( isDefined( eInflictor ) && eInflictor != eAttacker )
{
if ( means_of_explosive_damage( sMeansOfDeath ) )
typeHit = "standard"; // explosives do standard feedback
else
typeHit = "none";
}
else if ( isDefined( eInflictor ) && isDefined( eInflictor.damageFeedback ) && eInflictor.damageFeedback == false )
typeHit = "none";
else if( !maps\mp\gametypes\_damage::shouldWeaponFeedback( sWeapon ) )
typeHit = "none";
else if( iDFlags & level.iDFLAGS_STUN )
typeHit = "stun";
else if ( !eAttacker _hasperk( "specialty_armorpiercing" ) && sHitLoc == "armor" )
typeHit = "hitalienarmor";
else if ( sHitloc == "soft" )
typeHit = "hitaliensoft";
else if ( sMeansOfDeath == "MOD_MELEE" && sWeapon == "meleestun_mp" )
typeHit = "meleestun";
else
typeHit = "standard";
if ( IsDefined( level.attack_heli ) && eAttacker == level.attack_heli )
{
iDamage = Int( iDamage * 0.6 );
}
else
{
if ( IsDefined( eAttacker.owner ) )
{
eAttacker.owner thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit );
}
else
{
eAttacker thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit );
}
}
}
iDamage = scale_alien_damage_by_prestige( eAttacker, iDamage );
update_damage_score( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
/#
self maps\mp\alien\_debug::debugTrackDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
#/
return self [[ self maps\mp\agents\_agent_utility::agentFunc( "on_damaged_finished" ) ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
}
set_alien_damage_by_weapon_type( sMeansOfDeath, sWeapon, iDamage, eAttacker, iDFlags, vPoint, vDir, sHitLoc, timeOffset, eInflictor )
{
if ( IsDefined( sWeapon ) )
{
if ( sWeapon == "xm25_mp" && sMeansOfDeath == "MOD_IMPACT" )
iDamage = 95;
if (sWeapon == "spider_beam_mp" )
iDamage *= 15; // damage multiplier
if ( sWeapon == "alienthrowingknife_mp" && sMeansOfDeath == "MOD_IMPACT" )
{
if ( maps\mp\alien\_utility::can_hypno( eAttacker, false, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset, eInflictor ) )
iDamage = 20000;
else if( self.alien_type != "elite" )
iDamage = 500;
}
if ( sWeapon == "iw6_alienminigun_mp" ||
sWeapon == "iw6_alienminigun1_mp" ||
sWeapon == "iw6_alienminigun2_mp" ||
sWeapon == "iw6_alienminigun3_mp" )
{
iDamage = 55;
}
if( sWeapon == "iw6_alienminigun4_mp" )
iDamage = 75;
}
return iDamage;
}
update_damage_score( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
{
if ( !IsDefined( level.attack_heli ) || eAttacker != level.attack_heli )
{
if ( IsDefined( eAttacker ) && IsDefined( eAttacker.owner ) )
{
maps\mp\alien\_gamescore::giveAssistBonus( eAttacker.owner, ( iDamage * 0.75 ) );
}
else if ( IsDefined( eAttacker ) && IsDefined( eAttacker.pet ) && ( eAttacker.pet == 1 ) )
{
assert( IsDefined( eAttacker.owner ) );
maps\mp\alien\_gamescore::giveAssistBonus( eAttacker.owner, iDamage );
}
else
{
maps\mp\alien\_gamescore::giveAssistBonus( eAttacker, iDamage );
}
if ( isDefined ( eAttacker ) && isDefined ( sWeapon ) )
{
// weaponstats tracking: register weapon shot hit
eAttacker thread maps\mp\alien\_persistence::update_weaponstats_hits( sWeapon, 1, sMeansOfDeath );
level thread maps\mp\alien\_challenge_function::update_alien_damage_challenge( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset, self );
}
}
maps\mp\alien\_gamescore::update_performance_alien_damage( eAttacker, iDamage, sMeansOfDeath );
}
scale_alien_damage_by_weapon_type( eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc )
{
if ( isDefined( sHitLoc ) && sHitLoc != "none" ) //don't modify non impact damage
iDamage = check_for_explosive_shotgun_damage( self, iDamage, eAttacker, sWeapon, sMeansOfDeath );
if ( IsDefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && sHitLoc != "none" ) //only augment direct impacts
{
if ( getweaponclass ( sWeapon ) == "weapon_shotgun" )
{
iDamage += Int( idamage * level.shotgunDamageMod );
}
else
{
iDamage += Int( idamage * level.exploImpactMod );
}
}
return iDamage;
}
scale_alien_damage_by_perks( eAttacker, iDamage, sMeansOfDeath, sWeapon )
{
DAMAGE_BOOSTER_UPGRADE_SCALAR = 1.05; // damage multiplier for the damage_booster_upgrade purchased with tokens
if( isBulletDamage( sMeansOfDeath ) && !isalienturret ( sWeapon ) )
{
if ( !isAlienTurret( sWeapon ) )
{
iDamage = Int( iDamage * eAttacker perk_GetBulletDamageScalar() );
}
else if ( isAlienTrapTurret( sWeapon ) )
{
iDamage = Int( iDamage * eAttacker perk_GetTrapDamageScalar() );
}
if( IsDefined( eAttacker.ability_scalar_bullet ) )
{
iDamage = Int( iDamage * eAttacker.ability_scalar_bullet );
}
}
if ( sMeansOfDeath == "MOD_EXPLOSIVE" )
iDamage = Int( iDamage * eAttacker perk_GetExplosiveDamageScalar() );
//This is the base melee damage check.
if ( sMeansOfDeath == "MOD_MELEE" )
{
if ( WeaponType( sWeapon ) == "riotshield" )
{
eAttacker riotshieldAmmoTracker();
// MagicBullet( "alienmelee_mp", self GetTagOrigin( "tag_eye_2_le" ) , eAttacker GetTagOrigin( "TAG_RIOT_SHIELD" ) );
}
PlayFXOnTag ( level._effect[ "melee_blood" ], eAttacker, "tag_weapon_right" );
iDamage = Int ( iDamage * eAttacker perk_GetMeleeScalar() );
if( IsDefined( eAttacker.ability_scalar_melee ) )
{
iDamage = Int( iDamage * eAttacker.ability_scalar_melee );
}
}
if ( eAttacker maps\mp\alien\_persistence::is_upgrade_enabled( "damage_booster_upgrade" ) )
iDamage = Int( iDamage * DAMAGE_BOOSTER_UPGRADE_SCALAR );
return iDamage;
}
scale_alien_damage_by_prestige( eAttacker, iDamage )
{
if ( isPlayer( eAttacker ) )
{
prestige_damage_done_scalar = eAttacker maps\mp\alien\_prestige::prestige_getWeaponDamageScalar();
iDamage *= prestige_damage_done_scalar;
iDamage = int( iDamage );
}
return iDamage;
}
during_host_migration()
{
return ( isDefined( level.hostMigrationTimer ) );
}
means_of_explosive_damage( sMeansOfDeath )
{
return ( sMeansOfDeath == "MOD_EXPLOSIVE"
|| sMeansOfDeath == "MOD_GRENADE_SPLASH"
|| sMeansOfDeath == "MOD_GRENADE"
|| sMeansOfDeath == "MOD_PROJECTILE"
|| sMeansOfDeath == "MOD_PROJECTILE_SPLASH" );
}
check_for_explosive_shotgun_damage( alien, iDamage, eAttacker, sWeapon, sMeansOfDeath )
{
MAX_DIST = 500;
if ( !IsDefined( alien ) || !isReallyAlive( alien ) )
return iDamage;
if ( !isDefined ( eAttacker ) || !isPlayer ( eAttacker ) || sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" )
return iDamage;
if ( getWeaponClass( sWeapon ) == "weapon_shotgun" )
{
dist = Distance( eAttacker.origin, alien.origin );
scale = max( 1, dist/MAX_DIST );
max_dmg = iDamage * 8;
scaled_damage = max_dmg * scale;
if ( dist > MAX_DIST ) //should not do any scaling if beyond the max range
return ( iDamage );
return int( scaled_damage );
}
return iDamage;
}
typeSpecificDamageProcessing( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
{
//<NOTE J.C.> On a "damage" notify, we are only getting the damage and attacker back. Ideally, we should move this type of
// damage process as a listener running on specific alien type
switch ( get_alien_type() )
{
case "elite":
iDamage = maps\mp\agents\alien\_alien_elite::eliteDamageProcessing( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset );
break;
default:
break;
}
return int( iDamage );
}
// all non-manned turrets go here ( ball drone, automated sentry, etc.. )
isAlienNonMannedTurret( weapon )
{
if( !isDefined( weapon ) )
return false;
switch ( weapon )
{
case "alien_ball_drone_gun_mp": // ball drone
case "alien_ball_drone_gun1_mp": // ball drone
case "alien_ball_drone_gun2_mp": // ball drone
case "alien_ball_drone_gun3_mp": // ball drone
case "alien_ball_drone_gun4_mp": // ball drone
case "alienvulture_mp": // ball drone
case "alien_sentry_minigun_1_mp":
case "alien_sentry_minigun_2_mp":
case "alien_sentry_minigun_3_mp":
case "alien_sentry_minigun_4_mp":
return true;
default:
return false;
}
return false;
}
// ALL turrets go here, including trap turrets
isAlienTurret( weapon )
{
if( !isDefined( weapon ) )
return false;
switch ( weapon )
{
case "alien_ball_drone_gun_mp": // ball drone
case "alien_ball_drone_gun1_mp": // ball drone
case "alien_ball_drone_gun2_mp": // ball drone
case "alien_ball_drone_gun3_mp": // ball drone
case "alien_ball_drone_gun4_mp": // ball drone
case "alienvulture_mp": // ball drone
case "alien_sentry_minigun_1_mp":
case "alien_sentry_minigun_2_mp":
case "alien_sentry_minigun_3_mp":
case "alien_sentry_minigun_4_mp":
case "sentry_minigun_mp":
case "alien_manned_gl_turret_mp": // grenade turret
case "alien_manned_gl_turret1_mp": // grenade turret
case "alien_manned_gl_turret2_mp": // grenade turret
case "alien_manned_gl_turret3_mp": // grenade turret
case "alien_manned_gl_turret4_mp": // grenade turret
case "alien_manned_minigun_turret_mp": // portable minigun turret
case "alien_manned_minigun_turret1_mp": // portable minigun turret
case "alien_manned_minigun_turret2_mp": // portable minigun turret
case "alien_manned_minigun_turret3_mp": // portable minigun turret
case "alien_manned_minigun_turret4_mp": // portable minigun turret
case "turret_minigun_alien":
case "turret_minigun_alien_railgun":
case "turret_minigun_alien_grenade":
case "alientank_turret_mp":
case "alientank_rigger_turret_mp":
return true;
default:
return false;
}
return false;
}
// Only trap turrets go here (trap damage scalar is applied to these)
isAlienTrapTurret( weapon )
{
if( !isDefined( weapon ) )
return false;
switch ( weapon )
{
case "turret_minigun_alien":
case "turret_minigun_alien_railgun":
case "turret_minigun_alien_grenade":
case "alientank_turret_mp":
case "alientank_rigger_turret_mp":
return true;
default:
return false;
}
return false;
}
armorMitigation( vPoint, vDir, sHitLoc )
{
if ( type_has_head_armor( self get_alien_type() ) )
{
return maps\mp\agents\alien\_alien_think::armorMitigation( vPoint, vDir, sHitLoc );
}
return 1.0;
}
alienTypeCanDoFriendlyDamage( attacker, sWeapon )
{
if ( !IsDefined( attacker.alien_type ) )
return true;
if ( isdefined( sWeapon ) && sWeapon == "spider_beam_mp" )
return true;
switch( attacker get_alien_type() )
{
case "minion":
return true;
default:
return false;
}
}
riotshieldAmmoTracker() //self is the player
{
// Safety check
if( !isDefined( self ) || !isAlive( self ))
return;
riot_shield = riotShieldName();
// Make sure they have the weapon
if( !isDefined( riot_shield ) || !self HasWeapon( riot_shield ))
return;
shield_ammo = self GetWeaponAmmoClip( riot_shield );
self SetWeaponAmmoClip( riot_shield, ( shield_ammo - 1 ));
self notify( "riotshield_melee" );
self SetClientOmnvar ( "ui_alien_stowed_riotshield_ammo", shield_ammo - 1 );
self PlaySound( "crate_impact" );
Earthquake( 0.75,0.5,self.origin, 100 );
// Out of ammo, destroy the shield
if( self GetWeaponAmmoClip( riot_shield ) <= 0 )
{
front = true;
// Hit from the back?
if( self.hasRiotShield && !self.hasRiotshieldequipped )
front = false;
self TakeWeapon( riot_shield );
self.hasRiotShield = false;
self.hasRiotshieldequipped = false; // 0 in the back
// Front Block
if( front )
{
self DetachShieldModel( "weapon_riot_shield_iw6", "tag_weapon_right" );
self IPrintLnBold ( &"ALIENS_HANDY_RIOT_DESTROYED" );
// Switch to another weapon
weapon_list = self GetWeaponsList( "primary" );
Assert( weapon_list.size );
if ( weapon_list.size > 0 )
self SwitchToWeapon( weapon_list[0] );
}
// Back Block
else
{
self DetachShieldModel( "weapon_riot_shield_iw6", "tag_shield_back" );
self IPrintLnBold ( &"ALIENS_STOWED_RIOT_DESTROYED" );
}
// Hide the icon
self setclientomnvar ( "ui_alien_riotshield_equipped",-1 );
}
}
riotshieldAmmoDeplete() //self is player with shield getting shot at by spider
{
{
self.spider_shield_block = true;
self riotshieldAmmoTracker();
wait 0.4;
self.spider_shield_block = undefined;
}
}
//===========================================
// Special Alien Hit Effects()
// self = a player
//===========================================
check_for_special_damage( enemy, sWeapon, sMeansOfDeath )
{
//may eventually have specialized melee damage
if ( sMeansOfDeath == "MOD_MELEE" && WeaponType( sWeapon ) != "riotshield" )
return;
if ( isDefined( sWeapon ) && sWeapon == "alienims_projectile_mp" )
return;
//check to see if incendiary rounds are being used or the flaming riotshield
if ( !isDefined( enemy.is_burning ) && IsAlive( enemy ) )
{
if ( isDefined( self.has_incendiary_ammo ) && self.has_incendiary_ammo && sMeansOfDeath != "MOD_UNKNOWN" )
{
enemy thread catch_alien_on_fire( self, undefined, undefined, true );
}
if ( ( sWeapon == "iw5_alienriotshield4_mp" ) && self.fireShield == 1.0 )
{
enemy thread catch_alien_on_fire( self );
}
switch ( sWeapon )
{
case "iw6_alienmk324_mp":
case "iw6_alienmk323_mp":
case "iw6_alienminigun4_mp":
case "iw6_alienminigun3_mp":
case "alienvulture_mp":
case "alien_manned_gl_turret4_mp":
enemy thread catch_alien_on_fire( self );
break;
}
}
else
{
baseweapon = getRawBaseWeaponName( sWeapon ); //stun ammo - slow down for 3 seconds
if ( isDefined ( self.special_ammocount ) && isDefined ( self.special_ammocount[baseweapon] ) && self.special_ammocount[baseweapon] > 0 )
{
//enemy thread stun_alien();
}
}
}
// self = an alien
catch_alien_on_fire( player, burn_time, total_damage, fire_ammo ) //burn_time and total_damage are optional params. If they are not passed default times and damage caps for each alien type are used.
{
self endon( "death" );
self maps\mp\alien\_alien_fx::alien_fire_on();
self damage_alien_over_time( player, burn_time, total_damage, fire_ammo );
self maps\mp\alien\_alien_fx::alien_fire_off();
}
// incendiary constants
CONST_BURN_DAMAGE_DEFAULT = 150;
CONST_BURN_DAMAGE_BRUTE = 250; // brute solo hp=1200
CONST_BURN_DAMAGE_GOON = 150; // goon solo hp=275
CONST_BURN_DAMAGE_SPITTER = 200; // spitter solo hp=1000
CONST_BURN_DAMAGE_ELITE = 500; // queen solo hp=10000
CONST_BURN_DAMAGE_MINION = 100;
CONST_BURN_TIME_DEFAULT = 3; // burn time is only the burning fx time, damage is fixed
CONST_BURN_TIME_BRUTE = 4;
CONST_BURN_TIME_GOON = 3;
CONST_BURN_TIME_SPITTER = 4;
CONST_BURN_TIME_ELITE = 4;
CONST_BURN_TIME_MINION = 2;
CONST_FIRE_AMMO_UPGRADE_TOTAL_DAMAGE_SCALAR = 1.20;
//self = an alien
damage_alien_over_time( player, burn_time, total_damage, fire_ammo )
{
self endon( "death" );
// damage and burn time modifier by type
if ( !IsDefined( burn_time ) && !IsDefined( total_damage ) )
{
if ( self.alien_type == "goon" )
{
total_damage = CONST_BURN_DAMAGE_GOON;
burn_time = CONST_BURN_TIME_GOON;
}
else if ( self.alien_type == "brute" )
{
total_damage = CONST_BURN_DAMAGE_BRUTE;
burn_time = CONST_BURN_TIME_BRUTE;
}
else if ( self.alien_type == "spitter" )
{
total_damage = CONST_BURN_DAMAGE_SPITTER;
burn_time = CONST_BURN_TIME_SPITTER;
}
else if ( self.alien_type == "elite" )
{
total_damage = CONST_BURN_DAMAGE_ELITE;
burn_time = CONST_BURN_TIME_ELITE;
}
else if ( self.alien_type == "minion" )
{
total_damage = CONST_BURN_DAMAGE_MINION;
burn_time = CONST_BURN_TIME_MINION;
}
else
{
total_damage = CONST_BURN_DAMAGE_DEFAULT;
burn_time = CONST_BURN_TIME_DEFAULT;
}
}
else
{
if ( !isDefined( total_damage ) )
total_damage = CONST_BURN_DAMAGE_DEFAULT;
if ( !isDefined( burn_time ) )
burn_time = CONST_BURN_TIME_DEFAULT;
}
if ( isDefined( player ) && isDefined( fire_ammo ) && player maps\mp\alien\_persistence::is_upgrade_enabled( "incendiary_ammo_upgrade" ) && isDefined( fire_ammo ) )
{
total_damage = total_damage * CONST_FIRE_AMMO_UPGRADE_TOTAL_DAMAGE_SCALAR;
}
total_damage *= level.alien_health_per_player_scalar[ level.players.size ];
elapsed_time = 0;
samples = 6;
interval_wait = burn_time / samples;
interval_damage = total_damage / samples;
for ( i=0; i<samples; i++ )
{
wait ( interval_wait );
if ( IsAlive (self ) )
self DoDamage( interval_damage, self.origin, player, player, "MOD_UNKNOWN");
}
}
/////////////////////////////////////////////////////////////////
// ARMOR: give a health boost
setbodyArmor( optionalArmorValue )
{
self notify( "give_light_armor" );
if( IsDefined( self.bodyArmorHP ) )
unsetbodyArmor();
self thread removebodyArmorOnDeath();
self thread removebodyArmorOnMatchEnd();
self.bodyArmorHP = 150;
if( IsDefined(optionalArmorValue) )
self.bodyArmorHP = optionalArmorValue;
}
removebodyArmorOnDeath()
{
self endon ( "disconnect" );
self endon( "give_light_armor" );
self endon( "remove_light_armor" );
self waittill ( "death" );
unsetbodyArmor();
}
unsetbodyArmor()
{
self.bodyArmorHP = undefined;
self notify( "remove_light_armor" );
}
removebodyArmorOnMatchEnd()
{
self endon ( "disconnect" );
self endon ( "remove_light_armor" );
level waittill_any( "round_end_finished", "game_ended" );
self thread unsetbodyArmor();
}
hasbodyArmor()
{
return ( IsDefined( self.bodyArmorHP ) && self.bodyArmorHP > 0 );
}
hasHeavyArmor( player )
{
return ( IsDefined( player.heavyArmorHP ) && (player.heavyArmorHP > 0) );
}
setHeavyArmor( armorValue )
{
if( IsDefined(armorValue) )
{
self.heavyArmorHP = armorValue;
}
}
// END ARMOR
/////////////////////////////////////////////////////////////////
ALIEN_SNARE_AMOUNT = 0.68;
ALIEN_SNARE_AMOUNT_MAX = 0.58;
ALIEN_SNARE_DURATION = 0.80;
applyAlienSnare()
{
self thread applyAlienSnareInternal();
}
applyAlienSnareInternal()
{
self notify( "stop_applyAlienSnare" );
self endon( "stop_applyAlienSnare" );
self endon( "disconnect" );
self endon( "death" );
self.alienSnareCount++;
self.alienSnareSpeedScalar = pow( ALIEN_SNARE_AMOUNT, ( self.alienSnareCount + 1 ) * 0.35 );
self.alienSnareSpeedScalar = max( ALIEN_SNARE_AMOUNT_MAX, self.alienSnareSpeedScalar );
maps\mp\alien\_perkfunctions::updateCombatSpeedScalar();
//iprintln( "SNARE: " + self.alienSnareSpeedScalar );
wait ALIEN_SNARE_DURATION;
self.alienSnareCount = 0;
self.alienSnareSpeedScalar = 1.0;
maps\mp\alien\_perkfunctions::updateCombatSpeedScalar();
//iprintln( "SNARE CLEARED" );
}
scale_alien_damage_func( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, timeOffset )
{
if ( self get_alien_type() == "mammoth" )
iDamage = self adjust_mammoth_damage( iDamage );
weap_class = getWeaponClass ( sWeapon );
if ( level.script == "mp_alien_dlc3" && weap_class != "weapon_pistol" )
{
scalar = 1.25;
if ( isBulletDamage( sMeansOfDeath ) && !isAlienTurret( sWeapon ) )
{
if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) && weapon_has_alien_attachment( sWeapon ) )
{
if ( eAttacker maps\mp\alien\_perk_utility::has_perk( "perk_bullet_damage", [ 0,1,2,3,4 ] ) ) //weapon specialist
scalar = 1.15;
adjusted_damage = int( iDamage * scalar );
return adjusted_damage;
}
}
}
return iDamage;
}
adjust_mammoth_damage( damage_amount )
{
if ( IsDefined( self.burrowing ) && self.burrowing )
return 0;
return damage_amount;
}
//self is player
stun_zap_aliens(current_origin, enemy, iDamage, sMeansofDeath )
{
if(isdefined(self.stun_struct))
return;
dist_sq = 62500;
aliens = maps\mp\alien\_spawnlogic::get_alive_agents();
if(IsDefined(level.seeder_active_turrets))
aliens = array_combine(aliens, level.seeder_active_turrets);
alien_array = [];
foreach ( alien in aliens)
{
if(DistanceSquared(current_origin, alien.origin) < dist_sq)
alien_array[alien_array.size] = alien;
}
if(alien_array.size < 1)
return;
bolt_count = 0;
max_bolts = 1;
if(!isdefined(self.stun_struct))
{
self.stun_struct = SpawnStruct();
self.stun_struct.attack_bolt = spawn( "script_model",current_origin );
self.stun_struct.attack_bolt setmodel( "tag_origin" );
waitframe();
}
self.stun_struct.attack_bolt.origin = current_origin;
stun_ammo_level = self maps\mp\alien\_persistence::get_dpad_up_level();
if( isDefined( sMeansofDeath ) && sMeansofDeath != "MOD_MELEE" )
max_bolts = max_bolts + stun_ammo_level;
else
{
max_bolts = 4;
iDamage = iDamage / 4;
}
foreach(alien in alien_array)
{
if(IsDefined(alien) && alien != enemy && IsAlive( alien ))
{
alien stun_bolt_death(self, iDamage, sMeansofDeath );
bolt_count++;
if(bolt_count >= max_bolts)
break;
wait(.1);
}
}
wait(.05);
KillFXOnTag(level._effect[ "stun_attack" ], self.stun_struct.attack_bolt, "TAG_ORIGIN");
KillFXOnTag(level._effect[ "stun_shock" ], self.stun_struct.attack_bolt, "TAG_ORIGIN");
self.stun_struct.attack_bolt delete();
self.stun_struct = undefined;
}
//self = alien
stun_bolt_death( player, iDamage, sMeansofDeath )
{
waitframe();
PlayFXOnTag(level._effect[ "stun_attack" ], player.stun_struct.attack_bolt, "TAG_ORIGIN");
PlayFXOnTag( level._effect[ "stun_shock" ] , player.stun_struct.attack_bolt, "TAG_ORIGIN" );
move_spot = undefined;
if(IsDefined(self.alien_type) && self.alien_type == "seeder_spore")
move_spot = self GetTagOrigin("J_Spore_46");
else if(IsDefined(self) && isalive(self) && has_tag( self.model, "J_SpineUpper" ))
move_spot = self GetTagOrigin("J_SpineUpper");
if(IsDefined(move_spot))
{
player.stun_struct.attack_bolt moveto( move_spot,.05 );
wait ( .05 );
// if(IsDefined(self) && DistanceSquared(self.origin, player.stun_struct.attack_bolt.origin) > 40000)
// playfxontag( level._effect[ "beacon_turret_hit_fx" ] ,player.stun_struct.attack_bolt, "tag_origin" );
if(IsDefined(self) && sMeansofDeath == "MOD_MELEE" )
self PlaySound( "alien_fence_shock" );
wait ( .05 );
stun_bolt_damage = int( iDamage / 2 );
if(IsDefined(self))
{
guy_to_hurt = self;
if(IsDefined(self.alien_type) && self.alien_type == "seeder_spore")
guy_to_hurt = self.coll_model;
if(IsDefined(guy_to_hurt))
guy_to_hurt doDamage( stun_bolt_damage, self.origin, player, player.stun_struct.attack_bolt, sMeansofDeath );
}
}
StopFXOnTag(level._effect[ "stun_attack" ], player.stun_struct.attack_bolt, "TAG_ORIGIN");
}