diff options
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/titan/_titan_health.gnut')
-rw-r--r-- | Northstar.CustomServers/scripts/vscripts/titan/_titan_health.gnut | 1072 |
1 files changed, 0 insertions, 1072 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/titan/_titan_health.gnut b/Northstar.CustomServers/scripts/vscripts/titan/_titan_health.gnut deleted file mode 100644 index d600cb03b..000000000 --- a/Northstar.CustomServers/scripts/vscripts/titan/_titan_health.gnut +++ /dev/null @@ -1,1072 +0,0 @@ -global function TitanHealth_Init - -global function Titan_PlayerTookDamage -global function Titan_NPCTookDamage - -global function GetShieldRegenTime -global function GetShieldRegenDelay -global function PlayerHasAutoEject -global function SetTitanCoreTimer -global function GetTitanCoreTimer - -global function AddCreditToTitanCoreBuilderForTitanDamageInflicted -global function AddCreditToTitanCoreBuilderForTitanDamageReceived -global function AddCreditToTitanCoreBuilderForDoomInflicted -global function AddCreditToTitanCoreBuilderForDoomEntered -global function AddCreditToTitanCoreBuilder - -global function TitanShieldRegenThink - -global function IsRodeoDamageFromBatteryPack -global function IsKillshot - -global function DoomedHealthThink -global function UndoomTitan -global function RestoreTitan - -global const SIGNAL_TITAN_HEALTH_REGEN = "BeginTitanHealthRegen" -global const SIGNAL_TITAN_SHIELD_REGEN = "BeginTitanShieldRegen" - -global const TITAN_HEALTH_REGEN_DELAY_MAX = 0.7 // 2.2 - -#if MP -// PROTO : Was 99, 49 is for test -global const TITAN_REGEN_MIN_DAMAGE = 49 -global const TITAN_REGEN_MIN_DAMAGE_DELAY = 0.5 -#elseif SP -global const TITAN_REGEN_MIN_DAMAGE = 70 -global const TITAN_REGEN_MIN_DAMAGE_DELAY = 0.5 -#endif - -// titan health system -const TITAN_HEALTH_HISTORY_FALLOFF_START = 0 // how many seconds until shield begins to regen - -const float TITAN_HEALTH_HISTORY_FALLOFF_END = 4.0 - -struct -{ - float earn_meter_titan_multiplier -} file - -void function TitanHealth_Init() -{ - RegisterSignal( SIGNAL_TITAN_HEALTH_REGEN ) - RegisterSignal( SIGNAL_TITAN_SHIELD_REGEN ) - RegisterSignal( "Doomed" ) - RegisterSignal( "TitanUnDoomed" ) - RegisterSignal( "StopShieldRegen" ) - RegisterSignal( "WeakTitanHealthInitialized" ) - - file.earn_meter_titan_multiplier = GetCurrentPlaylistVarFloat( "earn_meter_titan_multiplier", 1.0 ) - - if ( IsMenuLevel() ) - return - - HealthRegenInit() - AddSoulInitFunc( TitanShieldRegenThink ) //This runs even if playlist var titan_shield_regen is set to 0 because it also does stuff like give friendly Pilots protection with shield, etc - AddSoulDeathCallback( Titan_MonarchCleanup ) -} - -void function UndoomTitan( entity titan, int numSegments ) -{ - entity soul = titan.GetTitanSoul() - string settings = GetSoulPlayerSettings( soul ) - - soul.DisableDoomed() - int maxHealth - int segmentHealth = GetSegmentHealthForTitan( titan ) - if ( titan.IsNPC() ) - { - maxHealth = int( GetPlayerSettingsFieldForClassName_Health( settings ) ) - if ( titan.ai.titanSpawnLoadout.setFileMods.contains( "fd_health_upgrade" ) ) - maxHealth += segmentHealth - if ( soul.soul.titanLoadout.setFileMods.contains( "core_health_upgrade" ) ) - maxHealth += segmentHealth - } - else - { - maxHealth = int( titan.GetPlayerModHealth() ) - } - titan.SetMaxHealth( maxHealth ) - titan.SetHealth( segmentHealth * numSegments ) - SetSoulBatteryCount( soul, numSegments ) - - titan.Signal( "TitanUnDoomed" ) - UndoomTitan_Body( titan ) - thread TitanShieldRegenThink( soul ) -} - -void function RestoreTitan( entity titan, float percent = 0.625 ) -{ - entity soul = titan.GetTitanSoul() - if ( soul.IsDoomed() ) - UndoomTitan( titan, 1 ) - - soul.nextRegenTime = 0.0 - soul.SetShieldHealth( soul.GetShieldHealthMax() ) - int minHealth = int( titan.GetMaxHealth() * percent ) - if ( titan.GetHealth() < minHealth ) - { - titan.SetHealth( minHealth ) - int segmentHealth = GetSegmentHealthForTitan( titan ) - int segments = int( minHealth / float( segmentHealth ) ) - SetSoulBatteryCount( soul, segments ) - } -} - -bool function IsRodeoDamage( entity soul, var damageInfo ) -{ - entity titan = soul.GetTitan() - entity attacker = DamageInfo_GetAttacker( damageInfo ) - if ( !attacker.IsPlayer() ) - { - entity rider = GetRodeoPilot( titan ) - if ( rider == attacker ) - return true - else - return false - } - - if ( attacker.GetTitanSoulBeingRodeoed() != soul ) - return false - - return true -} - -bool function IsCoopRodeoDamage( entity soul, var damageInfo ) -{ - entity titan = soul.GetTitan() - entity attacker = DamageInfo_GetAttacker( damageInfo ) - entity rider = GetRodeoPilot( titan ) - if ( rider == attacker ) - return true - else - return false - - unreachable -} - - -void function CheckRodeoRiderHitsTitan( entity soul, var damageInfo ) -{ - if ( IsRodeoDamage( soul, damageInfo ) ) - { - //Set Last Attack Time so warning is triggered - soul.SetLastRodeoHitTime( Time() ) - - DamageInfo_AddCustomDamageType( damageInfo, DF_RODEO ) - } -} - -bool function ShouldMultiplyRodeoDamage( var damageInfo ) -{ - switch ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) ) - { - case eDamageSourceId.mp_weapon_smr: - case eDamageSourceId.mp_titanability_smoke: - return false - - case eDamageSourceId.mp_weapon_defender : - return true - } - - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_EXPLOSION ) - return false - - return true -} - -bool function IsRodeoDamageFromBatteryPack( entity soul, var damageInfo ) -{ - if ( !IsRodeoDamage( soul, damageInfo ) ) - return false - - if ( DamageInfo_GetCustomDamageType( damageInfo ) != damageTypes.rodeoBatteryRemoval ) - return false - - return true -} - - -int function ShieldHealthUpdate( entity titan, var damageInfo, bool critHit ) -{ - entity soul = titan.GetTitanSoul() - if ( DamageInfo_GetForceKill( damageInfo ) ) - { - soul.SetShieldHealth( 0 ) - return 0 - } - - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_BYPASS_SHIELD ) - return 0 - - float damage = DamageInfo_GetDamage( damageInfo ) - int damageType = DamageInfo_GetCustomDamageType( damageInfo ) - - Assert( soul == titan.GetTitanSoul() ) - int shieldHealth = soul.GetShieldHealth() - - if ( soul.e.forcedRegenTime <= Time() ) - soul.nextRegenTime = CalculateNextRegenTime( damage, damageType, critHit, expect float( soul.nextRegenTime ), GetShieldRegenDelay( soul ) ) - - int result = 0 - if ( shieldHealth ) - { - DamageInfo_AddCustomDamageType( damageInfo, DF_SHIELD_DAMAGE ) - result = int( ShieldModifyDamage( titan, damageInfo ) ) - } - else - { - TakeAwayFriendlyRodeoPlayerProtection( titan ) - } - - return result -} - - -void function PlayerOrNPCTitanTookDamage( entity titan, var damageInfo, bool critHit, TitanDamage titanDamage ) -{ - entity soul = titan.GetTitanSoul() - - if ( !IsValid( soul ) ) //Defensive fix for transient times in frame where Titan can have no soul but be damaged, e.g. immediately after embark - return - - // zero out small forces - if ( LengthSqr( DamageInfo_GetDamageForce( damageInfo ) ) < 30000 * 30000 ) - DamageInfo_SetDamageForce( damageInfo, < 0, 0, 0 > ) - - titanDamage.shieldDamage = CheckSpecialCaseShieldDamage( soul, titan, damageInfo ) - if ( titanDamage.shieldDamage < 0 ) - { - CheckRodeoRiderHitsTitan( soul, damageInfo ) - titanDamage.shieldDamage = ShieldHealthUpdate( titan, damageInfo, critHit ) - } - - HandleKillshot( titan, damageInfo, titanDamage ) - - // health regen based on how much damage dealt to titan - float damage = DamageInfo_GetDamage( damageInfo ) - int damageType = DamageInfo_GetCustomDamageType( damageInfo ) - bool rodeoDamage = ( ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_RODEO ) > 0 ) - - if ( soul.e.forcedRegenTime <= Time() ) - soul.nextHealthRegenTime = CalculateNextRegenTime( damage, damageType, critHit || rodeoDamage, expect float( soul.nextHealthRegenTime ), GetHealthRegenDelay( soul ) ) -} - -int function CheckSpecialCaseShieldDamage( entity soul, entity titan, var damageInfo ) -{ - if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) == damagedef_suicide ) - return 0 - - // no protection from doomed health loss - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_DOOMED_HEALTH_LOSS ) - return 0 - - if ( IsTitanWithinBubbleShield( titan ) || TitanHasBubbleShieldWeapon( titan ) ) - { - DamageInfo_SetDamage( damageInfo, 0 ) - return 0 - } - - return -1 -} - -void function Titan_NPCTookDamage( entity titan, var damageInfo, TitanDamage titanDamage ) -{ - Assert( titan.IsTitan() ) - Assert( DamageInfo_GetDamage( damageInfo ) > 0 ) - - // dead entities can take damage - if ( !IsAlive( titan ) ) - return - - entity soul = titan.GetTitanSoul() - - if ( !IsValid( soul ) ) //Defensive fix for transient times in frame where Titan can have no soul but be damaged, e.g. immediately after embark - return - - bool critHit = false - if ( CritWeaponInDamageInfo( damageInfo ) ) - critHit = IsCriticalHit( DamageInfo_GetAttacker( damageInfo ), titan, DamageInfo_GetHitBox( damageInfo ), DamageInfo_GetDamage( damageInfo ), DamageInfo_GetDamageType( damageInfo ) ) - - if ( critHit ) - DamageInfo_AddCustomDamageType( damageInfo, DF_CRITICAL ) - - entity attacker = DamageInfo_GetAttacker( damageInfo ) - if ( HeavyArmorCriticalHitRequired( damageInfo ) && CritWeaponInDamageInfo( damageInfo ) && !critHit && IsValid( attacker ) && !attacker.IsTitan()) - { - float shieldHealth = float( titan.GetTitanSoul().GetShieldHealth() ) - float damage = DamageInfo_GetDamage( damageInfo ) - if ( shieldHealth - damage <= 0 ) - { - if ( shieldHealth > 0 ) - DamageInfo_SetDamage( damageInfo, shieldHealth ) - else - DamageInfo_SetDamage( damageInfo, 0 ) - } - } - - PlayerOrNPCTitanTookDamage( titan, damageInfo, critHit, titanDamage ) - - RecordDamageToNPCTitanSoul( soul, damageInfo ) - - entity owner = GetPetTitanOwner( titan ) - if ( IsValid( owner ) ) - AutoTitan_TryMultipleTitanCallout( titan, damageInfo ) - - if ( GetDoomedState( titan ) ) - titanDamage.shieldDamage = 0 -} - -void function Titan_PlayerTookDamage( entity player, var damageInfo, entity attacker, bool critHit, TitanDamage titanDamage ) -{ - Assert( player.IsTitan() ) - - float damage = DamageInfo_GetDamage( damageInfo ) - - if ( !IsAlive( player ) ) - return - - entity soul = player.GetTitanSoul() - if ( !IsValid( soul ) ) //Defensive fix for transient times in frame where Titan can have no soul but be damaged, e.g. immediately after embark - return - - if ( damage > 0 ) - AdjustVelocityFromHit( player, damageInfo, attacker, damage, critHit ) - - if ( IsDemigod( player ) ) - EntityDemigod_TryAdjustDamageInfo( player, damageInfo ) - - bool critHit = false - if ( CritWeaponInDamageInfo( damageInfo ) ) - critHit = IsCriticalHit( attacker, player, DamageInfo_GetHitBox( damageInfo ), DamageInfo_GetDamage( damageInfo ), DamageInfo_GetDamageType( damageInfo ) ) - - if ( critHit ) - DamageInfo_AddCustomDamageType( damageInfo, DF_CRITICAL ) - - #if MP - if ( HeavyArmorCriticalHitRequired( damageInfo ) && CritWeaponInDamageInfo( damageInfo ) && !critHit && IsValid( attacker ) && !attacker.IsTitan()) - { - float shieldHealth = float( player.GetTitanSoul().GetShieldHealth() ) - if ( shieldHealth - damage <= 0 ) - { - if ( shieldHealth > 0 ) - DamageInfo_SetDamage( damageInfo, shieldHealth ) - else - DamageInfo_SetDamage( damageInfo, 0 ) - } - } - #endif - - PlayerOrNPCTitanTookDamage( player, damageInfo, critHit, titanDamage ) -} - -bool function IsKillshot( entity ent, var damageInfo, entity titanSoul ) -{ - float damage = DamageInfo_GetDamage( damageInfo ) - int health = ent.GetHealth() - - if ( health - damage > DOOMED_MIN_HEALTH ) - return false - - return true -} - -bool function ShouldDoomTitan( entity ent, var damageInfo ) -{ - if ( DoomStateDisabled() ) - return false - - if ( GetDoomedState( ent ) ) - return false - - if ( DamageInfo_GetForceKill( damageInfo ) ) - return false - - float doomedHealth = GetTitanSoulDoomedHealth( ent.GetTitanSoul() ) - if ( doomedHealth <= 0 ) - return false - - entity soul = ent.GetTitanSoul() - if ( soul.soul.skipDoomState ) - return false - - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_SKIP_DAMAGE_PROT ) - return doomedHealth > ( DamageInfo_GetDamage( damageInfo ) - ent.GetHealth() ) - - bool skipDoom = ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_SKIPS_DOOMED_STATE ) > 0 - return !skipDoom -} - -bool function HandleKillshot( entity ent, var damageInfo, TitanDamage titanDamage ) -{ - #if NPC_TITAN_PILOT_PROTOTYPE - if ( TitanHasNpcPilot( ent ) ) //an npc titan that was dropped by an npc human - { - float damage = DamageInfo_GetDamage( damageInfo ) - int health = ent.GetHealth() - - if ( health - damage <= 0 ) - { - DamageInfo_SetDamage( damageInfo, 0 ) - thread TitanEjectPlayer( ent ) - } - - return - } - #endif - - if ( ent.IsPlayer() && ent.IsBuddhaMode() ) - return false - - entity titanSoul = ent.GetTitanSoul() - - if ( IsKillshot( ent, damageInfo, titanSoul ) ) - { - entity boss = titanSoul.GetBossPlayer() - Soul_SetLastAttackInfo( titanSoul, damageInfo ) - - if ( ShouldDoomTitan( ent, damageInfo ) ) - { - // Added via AddCallback_OnTitanDoomed - foreach ( callbackFunc in svGlobal.onTitanDoomedCallbacks ) - { - callbackFunc( ent, damageInfo ) - } - - if ( IsMultiplayer() ) - { - entity attacker = expect entity( expect table( titanSoul.lastAttackInfo ).attacker ) - if ( IsValid( attacker ) ) - { - entity bossPlayer = attacker.GetBossPlayer() - if ( attacker.IsNPC() && IsValid( bossPlayer ) ) - attacker = bossPlayer - - if ( attacker.IsPlayer() ) - ScoreEvent_TitanDoomed( ent, attacker, damageInfo ) - } - } - - thread DoomedHealthThink( titanSoul, damageInfo ) - - titanDamage.doomedNow = true - titanDamage.doomedDamage = int( DamageInfo_GetDamage( damageInfo ) ) - - int health = ent.GetHealth() - DamageInfo_SetDamage( damageInfo, health - 1 ) - return true - } - else - { - // handle auto eject here - if ( ent.IsPlayer() && PlayerHasAutoEject( ent ) ) - { - int health = ent.GetHealth() - DamageInfo_SetDamage( damageInfo, health - 1 ) - thread HandleAutoEject( ent, titanSoul ) - return false - } - } - } - - // Handle doom state damage - if ( GetDoomedState( ent ) ) - { - // as long as we're dying but not yet ejecting, the last player to damage us gets credit - if ( titanSoul.IsEjecting() ) - { - Soul_SetLastAttackInfo( titanSoul, damageInfo ) - } - else if ( ent.IsPlayer() && PlayerHasAutoEject( ent ) ) //Handle auto eject for when the frame in which Titan became doomed was not valid for ejecting, e.g. melee - { - int health = ent.GetHealth() - DamageInfo_SetDamage( damageInfo, health - 1 ) - thread HandleAutoEject( ent, titanSoul ) - return false - } - - // protect players who eject early - // if ( ent.IsPlayer() && IsEjectProtected( ent, damageInfo ) ) - // DamageInfo_SetDamage( damageInfo, 0 ) - - // slight protection to prevent multiple rapid damage events from eating through doomed state health - if ( Time() - titanSoul.soul.doomedStartTime < TITAN_DOOMED_INVUL_TIME && !DamageInfo_GetForceKill( damageInfo ) ) - DamageInfo_SetDamage( damageInfo, 0 ) - } - else - { - Soul_SetLastAttackInfo( titanSoul, damageInfo ) - } - - return false -} - -bool function PlayerHasAutoEject( entity player ) -{ - if ( player.IsBot() ) - return false - - if ( !PlayerHasPassive( player, ePassives.PAS_AUTO_EJECT ) ) - return false - - return true -} - - -void function AdjustVelocityFromHit( entity player, var damageInfo, entity attacker, float damage, bool critHit ) -{ -/* - if ( DamageInfo_GetDamageCriticalHitScale( damageInfo ) > 1.0 ) - { - // if you can crit, you have to crit! - if ( !critHit ) - return - } -*/ - - //printt( " " ) - //printt( "damage: " + damage ) - - vector damageForward = DamageInfo_GetDamageForce( damageInfo ) - damageForward.z = 0 - //printt( "damageForward " + damageForward ) - - damageForward.Norm() - - //vector org = DamageInfo_GetDamagePosition( damageInfo ) - //DebugDrawLine( org, org + damageForward * 250, 255, 0, 0, true, 5.0 ) - - vector velocity = player.GetVelocity() - vector velForward = player.GetVelocity() - velForward.z = 0 - velForward.Norm() - - //DebugDrawLine( org, org + velForward * 250, 0, 255, 0, true, 5.0 ) - - float dot = DotProduct( velForward, damageForward ) - - // only stop from the ~front cone - if ( dot >= -0.5 ) - return - - float speedPercent - - switch ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) ) - { - //case eDamageSourceId.mp_titanweapon_40mm: - // speedPercent = GraphCapped( damage, 0, 750, 1, 0 ) - // break - - case eDamageSourceId.mp_titanweapon_xo16: - speedPercent = 0.075 - break - - default: - speedPercent = GraphCapped( damage, 0, 2500, 0, 1.0 ) - } - - //float dif = GraphCapped( dot, -1, -0.5, 1, 0 ) - //speedPercent = speedPercent * dif + ( 1.0 - dif ) - - speedPercent *= GraphCapped( dot, -1.0, -0.5, 1, 0 ) - - //printt( " " ) - //printt( "Damage: " + damage ) - //printt( "dot: " + dot ) - //printt( "speedPercent: " + speedPercent ) - speedPercent = 1.0 - speedPercent - // make the dot into a tighter range - //dot += 0.5 - //dot *= -2.0 - - //printt( "modifier: " + ( speedPercent ) ) - velocity *= ( speedPercent ) - player.SetVelocity( velocity ) -} - - - -void function DoomedHealthThink( entity titanSoul, var damageInfo ) -{ - Assert( expect table( titanSoul.lastAttackInfo ).attacker, "Player entered reserve health with no attacker" ) - - entity soulOwner = titanSoul.GetTitan() - Assert( IsValid( soulOwner ), "Invalid owner " + soulOwner ) - - titanSoul.soul.doomedStartTime = Time() - - // kill any existing health regen thread - titanSoul.Signal( SIGNAL_TITAN_HEALTH_REGEN ) - titanSoul.Signal( SIGNAL_TITAN_SHIELD_REGEN ) - - titanSoul.EndSignal( "OnDestroy" ) - titanSoul.EndSignal( "OnTitanDeath" ) - - float tickRate = 0.15 - float maxDoomedHealth = GetTitanSoulDoomedHealth( titanSoul ) - float doomedHealth = maxDoomedHealth - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_SKIP_DAMAGE_PROT ) - doomedHealth = min( doomedHealth + soulOwner.GetHealth() - DamageInfo_GetDamage( damageInfo ), doomedHealth ) - - float DPS = (doomedHealth / TITAN_DOOMED_MAX_DURATION ) - - titanSoul.EnableDoomed() - titanSoul.doomedTime = Time() - soulOwner.SetDoomed() - DoomTitan( soulOwner ) - soulOwner.Signal( "Doomed" ) - titanSoul.Signal( "Doomed" ) - - // allow the damage to go through before resetting the health, so that we get proper damage indicators, etc... - // this process should also be in code - WaitEndFrame() - - // grab the soul owner again since there was a wait - soulOwner = titanSoul.GetTitan() - if ( !IsValid( soulOwner ) ) - return - - if ( PROTO_AlternateDoomedState() ) - { - //printt( soulOwner.GetHealth() ) - soulOwner.SetHealth( doomedHealth ) - soulOwner.SetMaxHealth( maxDoomedHealth ) - //soulOwner.SetHealthPerSegment( 0 ) - - soulOwner.ClearDoomed() - - if ( soulOwner.IsPlayer() && PlayerHasAutoEject( soulOwner ) ) - { - HandleAutoEject( soulOwner, titanSoul ) - } - else - { - //If it's an auto-titan with auto-eject, this just instantly kills it. - var attacker = ( "attacker" in titanSoul.lastAttackInfo ) ? expect table( titanSoul.lastAttackInfo ).attacker : null - expect entity( attacker ) - var inflictor = ( "inflictor" in titanSoul.lastAttackInfo ) ? expect table( titanSoul.lastAttackInfo ).inflictor : null - expect entity( inflictor ) - var damageSource = ( "damageSourceId" in titanSoul.lastAttackInfo ) ? expect table( titanSoul.lastAttackInfo ).damageSourceId : -1 - int damageFlags = expect int( expect table( titanSoul.lastAttackInfo ).scriptType ) - if ( SoulHasPassive( titanSoul, ePassives.PAS_AUTO_EJECT ) ) - { - int scriptDamageType = damageTypes.titanEjectExplosion | damageFlags - soulOwner.Die( attacker, inflictor, { scriptType = scriptDamageType, damageSourceId = damageSource } ) - } - } - return - } - soulOwner.SetHealth( doomedHealth ) - soulOwner.SetMaxHealth( maxDoomedHealth ) - //soulOwner.SetHealthPerSegment( 0 ) - - string settings = GetSoulPlayerSettings( titanSoul ) - float damageMod = 1.0 - while ( true ) - { - table lastAttackInfo = expect table( titanSoul.lastAttackInfo ) - - table extraDeathInfo = {} - extraDeathInfo.scriptType <- (DF_NO_INDICATOR | DF_DOOMED_HEALTH_LOSS) - if ( expect int( lastAttackInfo.scriptType ) & DF_BURN_CARD_WEAPON ) - extraDeathInfo.scriptType = expect int( extraDeathInfo.scriptType ) | DF_BURN_CARD_WEAPON - if ( expect int( lastAttackInfo.scriptType ) & DF_VORTEX_REFIRE ) - extraDeathInfo.scriptType = expect int( extraDeathInfo.scriptType ) | DF_VORTEX_REFIRE - - extraDeathInfo.damageSourceId <- lastAttackInfo.damageSourceId - - entity soulOwner = titanSoul.GetTitan() - if ( !IsValid( soulOwner ) ) - return - if ( soulOwner.IsPlayer() ) - { - //if ( PlayerHasPassive( soulOwner, ePassives.PAS_DOOMED_TIME ) ) - // damageMod = 0.4 - //else - // damageMod = 1.0 - - if ( PlayerHasAutoEject( soulOwner ) ) - { - //printt( "About to Auto Eject" ) - // do it in the loop cause player could somehow get in a titan in doomed state - HandleAutoEject( soulOwner, titanSoul ) - } - } - - float dmgAmount = DPS * tickRate * damageMod - - soulOwner.TakeDamage( dmgAmount, expect entity( lastAttackInfo.attacker ), expect entity( lastAttackInfo.inflictor ), extraDeathInfo ) - - wait tickRate - } -} - -void function HandleAutoEject( entity rider, entity soul ) -{ - soul.EndSignal( "OnDestroy" ) - soul.EndSignal( "OnTitanDeath" ) - - thread TitanEjectPlayer( rider ) - if ( soul.IsEjecting() ) - { - // so we don't cloak the titan during the ejection animation - if ( GetNuclearPayload( rider ) > 0 ) - wait 2.0 - else - wait 1.0 - - EnableCloak( rider, 7.0 ) - return - } -} - -void function TitanShieldRegenThink( entity soul ) -{ - thread TitanShieldRegenThink_Internal( soul ) -} - -// HACK: this technically doesn't work properly because server framerate and all that jazz. Should really be in code. -void function TitanShieldRegenThink_Internal( entity soul ) -{ - soul.EndSignal( "OnDestroy" ) - soul.EndSignal( "Doomed" ) - soul.EndSignal( "StopShieldRegen" ) - - //Shield starts at 0 health for now - string settings = GetSoulPlayerSettings( soul ) - bool hasShield = Dev_GetPlayerSettingByKeyField_Global( settings, "start_with_shields" ) == 1 - - if ( !hasShield ) - soul.SetShieldHealth( 0 ) - - int lastShieldHealth = soul.GetShieldHealth() - bool shieldHealthSound = false - int maxShield = soul.GetShieldHealthMax() - float lastTime = Time() - - while ( true ) - { - entity titan = soul.GetTitan() - if ( !IsValid( titan ) ) - return - - int shieldHealth = soul.GetShieldHealth() - Assert( titan ) - - if ( lastShieldHealth <= 0 && shieldHealth && titan.IsPlayer() ) - { - EmitSoundOnEntityOnlyToPlayer( titan, titan, "titan_energyshield_up_1P" ) - shieldHealthSound = true - if ( titan.IsTitan() ) - { - GiveFriendlyRodeoPlayerProtection( titan ) - } - else - { - if ( titan.IsPlayer() ) - { - printt( "Player was " + titan.GetPlayerSettings() ) - } - - printt( "ERROR! Expected Titan, but got " + titan ) - } - } - else if ( shieldHealthSound && shieldHealth == soul.GetShieldHealthMax() ) - { - shieldHealthSound = false - } - else if ( lastShieldHealth > shieldHealth && shieldHealthSound ) - { - StopSoundOnEntity( titan, "titan_energyshield_up_1P" ) - shieldHealthSound = false - } - - if ( Time() >= soul.nextRegenTime && TitanHasRegenningShield( soul ) ) - { - float shieldRegenRate = maxShield / ( GetShieldRegenTime( soul ) / SHIELD_REGEN_TICK_TIME ) - - if ( SoulHasPassive( soul, ePassives.PAS_SHIELD_BOOST ) ) - shieldRegenRate = SHIELD_BEACON_REGEN_RATE - - float frameTime = max( 0.0, Time() - lastTime ) - shieldRegenRate = shieldRegenRate * frameTime / SHIELD_REGEN_TICK_TIME - // Faster shield recharge if we have Fusion Core active ability ( Stryder Signature ) - //if ( titan.IsPlayer() && PlayerHasPassive( titan, ePassives.PAS_FUSION_CORE ) ) - // shieldRegenRate *= 1.25 - - soul.SetShieldHealth( minint( soul.GetShieldHealthMax(), int( shieldHealth + shieldRegenRate ) ) ) - } - - lastShieldHealth = shieldHealth - lastTime = Time() - WaitFrame() - } -} - -float function GetShieldRegenTime( entity soul ) -{ - float time - if ( SoulHasPassive( soul, ePassives.PAS_SHIELD_REGEN ) ) - time = TITAN_SHIELD_REGEN_TIME * 0.5 - else - time = TITAN_SHIELD_REGEN_TIME - - return time -} - -float function GetHealthRegenDelay( entity soul ) -{ - if ( GetDoomedState( soul.GetTitan() ) ) - return TITAN_DOOMED_REGEN_DELAY - - return GetShieldRegenDelay( soul ) -} - -float function GetShieldRegenDelay( entity soul ) -{ - float regenDelay = TITAN_SHIELD_REGEN_DELAY - - string settings = GetSoulPlayerSettings( soul ) - regenDelay = expect float( Dev_GetPlayerSettingByKeyField_Global( settings, "titan_regen_delay" ) ) - - float delay - if ( SoulHasPassive( soul, ePassives.PAS_SHIELD_REGEN ) ) - delay = regenDelay - 1.0 - else - delay = regenDelay - - if ( SoulHasPassive( soul, ePassives.PAS_SHIELD_BOOST ) ) - delay = 2.0 - - return delay -} - -void function RecordDamageToNPCTitanSoul( entity soul, var damageInfo ) -{ - float damage = DamageInfo_GetDamage( damageInfo ) - - vector inflictOrigin = <0.0,0.0,0.0> - entity inflictor = DamageInfo_GetInflictor( damageInfo ) - if ( IsValid( inflictor ) ) - inflictOrigin = inflictor.GetOrigin() - - entity attacker = DamageInfo_GetAttacker( damageInfo ) - - entity weapon = DamageInfo_GetWeapon( damageInfo ) - array<string> weaponMods - if ( IsValid( weapon ) ) - weaponMods = weapon.GetMods() - - StoreDamageHistoryAndUpdate( soul, TITAN_HEALTH_HISTORY_FALLOFF_END, damage, inflictOrigin, DamageInfo_GetCustomDamageType( damageInfo ), DamageInfo_GetDamageSourceIdentifier( damageInfo ), attacker, weaponMods ) -} - -void function AutoTitan_TryMultipleTitanCallout( entity titan, var damageInfo ) -{ - array<entity> titans = GetTitansHitMeInTime( titan.GetTitanSoul(), 5 ) - entity enemy = titan.GetEnemy() - if ( IsAlive( enemy ) && enemy.IsTitan() && !titans.contains( enemy ) ) - titans.append( enemy ) - - int totalEngagedTitans = titans.len() - - if ( totalEngagedTitans == 1 ) - PlayAutoTitanConversation( titan, "autoEngageTitan" ) - else if ( totalEngagedTitans > 1 ) - PlayAutoTitanConversation( titan, "autoEngageTitans" ) -} - -float function CalculateNextRegenTime( float damage, int damageType, bool critHit, float oldNextRegenTime, float maxRegenDelay ) -{ - if ( damage >= TITAN_REGEN_MIN_DAMAGE || critHit || damageType & DF_STOPS_TITAN_REGEN ) - { - if ( PROTO_VariableRegenDelay() ) - { - // regen delay based on damage dealt - float minRegenDelay = 1.0 - float regenDelay = GraphCapped( damage, 100, 1000, minRegenDelay, maxRegenDelay ) - - float nextRegenTime = oldNextRegenTime - float delayBasedOnCurrentTime = Time() + regenDelay - float delayBasedOnPreviousDelay = nextRegenTime + regenDelay - maxRegenDelay = Time() + maxRegenDelay - - delayBasedOnCurrentTime = min( delayBasedOnCurrentTime, maxRegenDelay ) - delayBasedOnPreviousDelay = min( delayBasedOnPreviousDelay, maxRegenDelay ) - nextRegenTime = max( delayBasedOnCurrentTime, delayBasedOnPreviousDelay ) - - return nextRegenTime - } - else - { - // old style - return Time() + maxRegenDelay - } - } - else - { - float addTime = TITAN_REGEN_MIN_DAMAGE_DELAY - - if ( oldNextRegenTime <= Time() + addTime ) - return Time() + addTime - } - - return oldNextRegenTime -} - -void function AddCreditToTitanCoreBuilderForTitanDamageInflicted( entity titanAttacker, float damage ) -{ - Assert( TitanDamageRewardsTitanCoreTime() ) - - float rateRaw = CORE_BUILD_PERCENT_FROM_TITAN_DAMAGE_INFLICTED - float rate = (rateRaw * 0.01) - float credit = (rate * damage) - if ( credit > 0.0 ) - AddCreditToTitanCoreBuilder( titanAttacker, credit ) -} - -void function AddCreditToTitanCoreBuilderForTitanDamageReceived( entity titanVictim, float damage ) -{ - Assert( TitanDamageRewardsTitanCoreTime() ) - - float rateRaw = CORE_BUILD_PERCENT_FROM_TITAN_DAMAGE_RECEIVED - float rate = (rateRaw * 0.01) - float credit = (rate * damage) - if ( credit > 0.0 ) - AddCreditToTitanCoreBuilder( titanVictim, credit ) -} - -void function AddCreditToTitanCoreBuilderForDoomInflicted( entity titanAttacker ) -{ - Assert( TitanDamageRewardsTitanCoreTime() ) - - float valueRaw = CORE_BUILD_PERCENT_FROM_DOOM_INFLICTED - float credit = (valueRaw * 0.01) - if ( credit > 0.0 ) - AddCreditToTitanCoreBuilder( titanAttacker, credit ) -} - -void function AddCreditToTitanCoreBuilderForDoomEntered( entity titanVictim ) -{ - Assert( TitanDamageRewardsTitanCoreTime() ) - - float valueRaw = CORE_BUILD_PERCENT_FROM_DOOM_ENTERED - float credit = (valueRaw * 0.01) - if ( credit > 0.0 ) - AddCreditToTitanCoreBuilder( titanVictim, credit ) -} - -void function AddCreditToTitanCoreBuilder( entity titan, float credit ) -{ - Assert( TitanDamageRewardsTitanCoreTime() ) - - entity soul = titan.GetTitanSoul() - if ( !IsValid( soul ) ) - return - - entity bossPlayer = soul.GetBossPlayer() - - if ( titan.IsPlayer() ) - { - if ( !IsValid( bossPlayer ) ) - return - - if ( bossPlayer.IsTitan() && TitanCoreInUse( bossPlayer ) ) - return - } - else - { - Assert( titan.IsNPC() ) - if ( TitanCoreInUse( titan ) ) - return - } - - if ( !IsAlive( titan ) ) - return - - if ( SoulHasPassive( soul, ePassives.PAS_VANGUARD_COREMETER ) ) - credit *= 1.10 - - credit *= file.earn_meter_titan_multiplier - #if MP - if ( titan.IsPlayer() ) - { - float coreModifier = titan.GetPlayerNetFloat( "coreMeterModifier" ) - if ( coreModifier >= 0.5 ) - credit *= FD_HOT_STREAK_MULTIPLIER - } - #endif - - bool coreWasAvailable = false - - if ( IsValid( bossPlayer ) ) - coreWasAvailable = IsCoreChargeAvailable( bossPlayer, soul ) - - float oldTotalCredit = SoulTitanCore_GetNextAvailableTime( soul ) - float newTotalCredit = (credit + oldTotalCredit) - if ( newTotalCredit >= 0.998 ) //JFS - the rui has a +0.001 for showing the meter as full. This fixes the case where the core meter displays 100 but can't be fired. - newTotalCredit = 1.0 - SoulTitanCore_SetNextAvailableTime( soul, newTotalCredit ) - - if ( IsValid( bossPlayer ) && !coreWasAvailable && IsCoreChargeAvailable( bossPlayer, soul ) ) - { - AddPlayerScore( bossPlayer, "TitanCoreEarned" ) - #if MP - UpdateTitanCoreEarnedStat( bossPlayer, titan ) - PIN_PlayerAbilityReady( bossPlayer, "core" ) - #endif - } - - #if MP - if ( IsValid( bossPlayer ) ) - JFS_PlayerEarnMeter_CoreRewardUpdate( titan, oldTotalCredit, newTotalCredit ) - #endif - - #if HAS_TITAN_TELEMETRY - if ( titan.IsPlayer() ) - { - if ( IsCoreChargeAvailable( titan, soul ) ) - { - TitanHints_TryShowHint( titan, [OFFHAND_EQUIPMENT] ) - } - } - #endif -} - -float function GetTitanCoreTimer( entity titan ) -{ - Assert( titan.IsTitan() ) - entity soul = titan.GetTitanSoul() - Assert( soul ) - - return SoulTitanCore_GetNextAvailableTime( soul ) - Time() -} - - - -void function SetTitanCoreTimer( entity titan, float timeDiff ) -{ - Assert( !TitanDamageRewardsTitanCoreTime() ) - - Assert( titan.IsTitan() ) - entity soul = titan.GetTitanSoul() - Assert( soul ) - - float newTime = Time() + timeDiff - SoulTitanCore_SetNextAvailableTime( soul, max( Time() - 1, newTime ) ) -} - - -void function Titan_MonarchCleanup( entity soul, var damageInfo ) -{ - entity titan = soul.GetTitan() - - if ( !IsValid( titan ) ) - return - - int statesIndex = titan.FindBodyGroup( "states" ) - if ( statesIndex <= -1 ) - return - - titan.SetBodygroup( statesIndex, 2 ) -}
\ No newline at end of file |