diff options
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/ai/_ai_mortar_titans.gnut')
-rw-r--r-- | Northstar.CustomServers/scripts/vscripts/ai/_ai_mortar_titans.gnut | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/ai/_ai_mortar_titans.gnut b/Northstar.CustomServers/scripts/vscripts/ai/_ai_mortar_titans.gnut deleted file mode 100644 index 08598808a..000000000 --- a/Northstar.CustomServers/scripts/vscripts/ai/_ai_mortar_titans.gnut +++ /dev/null @@ -1,395 +0,0 @@ -untyped - -global function MortarTitanThink -global function MortarTitans_Init - -global function MortarTitanDeathCleanup -global function MortarMissileFiredCallback -global function MoveToMortarPosition - -global function MortarTitanKneelToAttack - -global function MortarTitanAttack - -global function MortarTitanStopAttack - -//global function MortarAIWaitToEngage - -const float MORTAR_TITAN_ABORT_ATTACK_HEALTH_FRAC = 0.90 // will stop mortar attack if he's health gets below 90% of his current health. -const float MORTAR_TITAN_POSITION_SEARCH_RANGE = 1024 //3072 // How far away from his spawn point a mortar titan will look for positions to mortar from. -const float MORTAR_TITAN_ENGAGE_DELAY = 3.0 // How long before a mortar titan start to attack the generator if he's taken damage getting to his mortar position. -const float MORTAR_TITAN_REENGAGE_DELAY = 7.0 // How long before a mortar titan goes back to attacking the generator after breaking of an attack. - -// -------------------------------------------------------------------- -// MORTAR TITAN LOGIC -// -------------------------------------------------------------------- - -function MortarTitans_Init() -{ - RegisterSignal( "InterruptMortarAttack" ) - RegisterSignal( "BeginMortarAttack" ) -} - -void function MortarTitanDeathCleanup( entity titan ) -{ - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - - OnThreadEnd( - function() : ( titan ) - { - entity animEnt = titan.ai.carryBarrel - - if ( IsValid( animEnt ) ) - animEnt.Destroy() - - if ( IsAlive( titan ) ) - { - titan.Signal( "InterruptMortarAttack" ) - titan.Anim_Stop() - } - } - ) - - WaitForever() -} - -void function MortarMissileFiredCallback( entity missile, entity weaponOwner ) -{ - thread MortarMissileThink( missile, weaponOwner ) -} - -void function MortarMissileThink( entity missile, entity weaponOwner ) -{ - Assert( IsValid( missile ) ) - - missile.EndSignal( "OnDestroy" ) - missile.EndSignal( "OnDeath" ) - - if ( !IsValid( weaponOwner.ai.mortarTarget ) ) - return - - entity targetEnt = weaponOwner.ai.mortarTarget - - missile.DamageAliveOnly( true ) - missile.kv.lifetime = 6.0 - missile.s.mortar <- true - vector startPos = missile.GetOrigin() - - // made a hacky way to get the mortar arc to go higher and still have it hit it's target. - - float dist = Distance( startPos, targetEnt.GetOrigin() ) - - // radius tightens over time - float radius = GraphCapped( Time() - weaponOwner.ai.spawnTime, 60.0, 180.0, 220, 100 ) - missile.SetMissileTarget( targetEnt, < RandomFloatRange( -radius, radius ), RandomFloatRange( -radius, radius ), 0 > ) - - string sound = "weapon_spectremortar_projectile" - if ( weaponOwner.IsTitan() ) - sound = "Weapon_FlightCore_Incoming_Projectile" - - EmitSoundAtPosition( weaponOwner.GetTeam(), targetEnt.GetOrigin(), sound ) - - float homingSpeedMin = 10.0 - float homingSpeedMax = Graph( dist, 2500, 7000, 400, 200 ) - float estTravelTime = GraphCapped( dist, 0, 7000, 0, 5 ) - - float startTime = Time() - while( true ) - { - float frac = min( 1, pow( ( Time() - startTime ) / estTravelTime, 2.0 ) ) - - if ( frac > 1.0 ) - break - - float homingSpeed = GraphCapped( frac, 0, 1, homingSpeedMin, homingSpeedMax ) - - missile.SetHomingSpeeds( homingSpeed, 0 ) - - wait 0.25 - } - - missile.ClearMissileTargetPosition() -} - -void function MoveToMortarPosition( entity titan, vector origin, entity target ) -{ - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - - titan.SetLookDistOverride( 320 ) - titan.SetHearingSensitivity( 0 ) - titan.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT ) - - local animEnt = titan.ai.carryBarrel - - local dir = target.GetOrigin() - origin - local dist = dir.Norm() - local angles = VectorToAngles( dir ) - angles.x = 0 - angles.z = 0 - - float frac = TraceLineSimple( origin + < 0, 0, 32 >, origin + < 0, 0, -32 >, titan ) - if ( frac > 0 && frac < 1 ) - origin = origin + < 0, 0, 32 > - < 0, 0, 64 * frac > - - animEnt.SetOrigin( origin ) - animEnt.SetAngles( angles ) - - float goalRadius = titan.GetMinGoalRadius() - - OnThreadEnd( - function() : ( titan ) - { - if ( !IsValid( titan ) ) - return - - local classname = titan.GetClassName() - titan.DisableLookDistOverride() - titan.SetHearingSensitivity( 1 ) - titan.DisableNPCMoveFlag( NPCMF_PREFER_SPRINT ) - } - ) - - local tries = 0 - while( true ) - { - local dist = Distance( titan.GetOrigin(), origin ) - if ( dist <= goalRadius * 2 ) - break - - printt( "Mortar titan moving toward his goal", dist, tries++ ) - titan.AssaultPoint( origin ) - titan.AssaultSetGoalRadius( goalRadius ) - - local result = WaitSignal( titan, "OnFinishedAssault", "OnEnterGoalRadius" ) - } -} - -void function MortarTitanKneelToAttack( entity titan ) -{ - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - - entity animEnt = titan.ai.carryBarrel - waitthread PlayAnim( titan, "at_mortar_stand2knee", animEnt ) -} - -function MortarTitanAttack( entity titan, entity target ) -{ - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - titan.EndSignal( "InterruptMortarAttack" ) - - OnThreadEnd( - function() : ( titan ) - { - if ( !IsValid( titan ) ) - return - - if ( "selectedPosition" in titan.s ) - { - titan.s.selectedPosition.inUse = false - delete titan.s.selectedPosition - } - - if ( IsAlive( titan ) ) - thread MortarTitanAttackEnd( titan ) - } - ) - - titan.ai.mortarTarget = target - entity animEnt = titan.ai.carryBarrel - - entity weapon = titan.GetActiveWeapon() - - while ( weapon.IsWeaponOffhand() ) - { - WaitFrame() - weapon = titan.GetActiveWeapon() - } - - weapon.SetMods( [ "coop_mortar_titan" ] ) - - while( true ) - { - waitthread PlayAnim( titan, "at_mortar_knee", animEnt ) - } -} - -function MortarTitanAttackEnd( entity titan ) -{ - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - - entity animEnt = titan.ai.carryBarrel - - // remove the mortar mod, we do this so that we don't get mortar sound and fx when firing normal - entity weapon = titan.GetActiveWeapon() - - while ( weapon.IsWeaponOffhand() ) - { - WaitFrame() - weapon = titan.GetActiveWeapon() - } - - weapon.SetMods( [] ) - - WaitEndFrame() // if I didn't add this PlayAnim, below, would return immediately for some unknown reason. - - if ( IsValid( animEnt ) && IsAlive( titan ) ) - waitthread PlayAnim( titan, "at_mortar_knee2stand", animEnt ) -} - -function MortarTitanStopAttack( titan ) -{ - titan.Signal( "InterruptMortarAttack" ) -} - -function MortarTitanStopAttack_Internal( titan ) -{ - titan.Signal( "InterruptMortarAttack" ) - titan.Anim_Stop() -} - -void function MortarAIWaitToEngage( entity titan, float timeFrame, int minDamage = 75 ) -{ - entity soul = titan.GetTitanSoul() - float endtime = Time() + timeFrame - int lastHealth = titan.GetHealth() + soul.GetShieldHealth() - float tickTime = 1.0 - - while ( Time() < endtime ) - { - wait tickTime - - int currentHealth = titan.GetHealth() + soul.GetShieldHealth() - if ( lastHealth > ( currentHealth + minDamage ) ) // add minDamage so that we ignore low amounts of damage. - { - lastHealth = currentHealth - endtime = Time() + timeFrame - } - } -} - - -/*******************************************************************\ - MORTAR TITANS -\*******************************************************************/ -//Function assumes that given Titan is spawned as npc_titan_atlas_tracker_mortar. Changing the Titan's AISettings post-spawn -//disrupts the Titan's titanfall animations and can result in the Titan landing outside the level. -void function MortarTitanThink( entity titan, entity generator ) -{ - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - - entity soul = titan.GetTitanSoul() - soul.EndSignal( "OnDestroy" ) - - titan.ai.carryBarrel = CreateScriptRef() - titan.TakeWeaponNow( titan.GetActiveWeapon().GetWeaponClassName() ) - titan.GiveWeapon( "mp_titanweapon_rocketeer_rocketstream" ) - titan.SetActiveWeaponByName( "mp_titanweapon_rocketeer_rocketstream" ) - titan.SetScriptName( "mortar_titan" ) - - entity weapon = titan.GetActiveWeapon() - weapon.w.missileFiredCallback = MortarMissileFiredCallback - thread MortarTitanDeathCleanup( titan ) - - WaitTillHotDropComplete( titan ) - - float minEngagementDuration = 5 - StationaryAIPosition ornull mortarPosition = GetRandomStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN ) - while ( mortarPosition == null ) - { - // incase all stationary titan positions are in use wait for one to become available - wait 5 - mortarPosition = GetRandomStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN ) - } - - expect StationaryAIPosition( mortarPosition ) - - ClaimStationaryAIPosition( mortarPosition ) - - OnThreadEnd( - function() : ( mortarPosition ) - { - // release mortar position when dead - ReleaseStationaryAIPosition( mortarPosition ) - } - ) - - float minDamage = 75 // so that the titan doesn't care about small amounts of damage. - - while( true ) - { - vector origin = mortarPosition.origin - - float startHealth = float( titan.GetHealth() + soul.GetShieldHealth() ) - waitthread MoveToMortarPosition( titan, origin, generator ) - - if ( startHealth > ( ( titan.GetHealth() + soul.GetShieldHealth() ) + minDamage ) || !titan.IsInterruptable() ) - { - // we took damage getting to the mortar location lets wait until we stop taking damage - waitthread MortarAIWaitToEngage( titan, MORTAR_TITAN_ENGAGE_DELAY ) - continue - } - - waitthread MortarTitanKneelToAttack( titan ) - thread MortarTitanAttack( titan, generator ) - - wait minEngagementDuration // aways mortar the target for a while before potentially breaking out - - // wait for interruption - waitthread WaitForInteruption( titan ) - - MortarTitanStopAttack_Internal( titan ) - - // lets wait until we stop taking damage before going back to attacking the generator - waitthread MortarAIWaitToEngage( titan, MORTAR_TITAN_REENGAGE_DELAY ) - } -} - -void function WaitForInteruption( entity titan ) -{ - Assert( IsNewThread(), "Must be threaded off" ) - - titan.EndSignal( "OnSyncedMeleeVictim" ) - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "OnDestroy" ) - titan.EndSignal( "InterruptMortarAttack" ) - - entity soul = titan.GetTitanSoul() - soul.EndSignal( "OnDestroy" ) - - float playerProximityDistSqr = pow( 256, 2 ) - float healthBreakOff = ( titan.GetHealth() + soul.GetShieldHealth() ) * MORTAR_TITAN_ABORT_ATTACK_HEALTH_FRAC - - while( true ) - { - if ( IsEnemyWithinDist( titan, playerProximityDistSqr ) ) - break - if ( ( titan.GetHealth() + soul.GetShieldHealth() ) < healthBreakOff ) - break - wait 1 - } -} - -bool function IsEnemyWithinDist( entity titan, float dist ) -{ - vector origin = titan.GetOrigin() - array<entity> players = GetPlayerArrayOfEnemies_Alive( titan.GetTeam() ) - - foreach( player in players ) - { - if ( DistanceSqr( player.GetOrigin(), origin ) < dist ) - return true - } - - return false -}
\ No newline at end of file |