untyped global function Dogfighter_Init global function CreateDogFighterAttack global function LaunchRandomDogFighterAttacks global function CreateDogFighter global function CreateDogFighterAssist global function GetGunshipModel const TURRET_WEAPON_BULLETS = "mp_weapon_yh803_bullet" function Dogfighter_Init() { AddDeathCallback( "npc_dropship", OnDogFighterDeath ) RegisterSignal( "new_attack_thread" ) RegisterSignal( "GunshipForceLeave" ) } function LaunchRandomDogFighterAttacks( int team ) { svGlobal.levelEnt.Signal( "new_attack_thread" ) svGlobal.levelEnt.EndSignal( "new_attack_thread" ) for ( ;; ) { thread CreateDogFighterAttack( team ) wait RandomFloatRange( 3, 9 ) } } function CreateDogFighterAttack( int team ) { FlightPath flightPath = GetAnalysisForModel( GetFlightPathModel( "fp_straton_model" ), STRATON_ATTACK_FULL ) CallinData drop InitCallinData( drop ) SetCallinStyle( drop, eDropStyle.RANDOM_FROM_YAW ) SetCallinYaw( drop, RandomFloat( 360 ) ) SpawnPointFP spawnPoint = GetSpawnPointForStyle( flightPath, drop ) if ( !spawnPoint.valid ) return entity ship = CreateDogFighter( Vector(0,0,0), Vector(0,0,0), team ) int hornet_health = 2000 ship.SetHealth( hornet_health ) ship.SetMaxHealth( hornet_health ) ship.EndSignal( "OnDeath" ) //AddBulletTurrets( ship, team ) waitthread PlayAnimTeleport( ship, "st_AngelCity_IMC_Win_ComeIn", spawnPoint.origin, spawnPoint.angles ) thread PlayAnim( ship, "st_AngelCity_IMC_Win_Idle", spawnPoint.origin, spawnPoint.angles ) waitthread DogFighterWaitsUntilLeave( ship ) waitthread PlayAnim( ship, "st_AngelCity_IMC_Win_Leave", spawnPoint.origin, spawnPoint.angles, 0.5 ) ship.Kill_Deprecated_UseDestroyInstead() } function DogFighterWaitsUntilLeave( ship, idleMin = 10, idleMax = 15 ) { local duration = ship.GetSequenceDuration( "st_AngelCity_IMC_Win_Idle" ) // make it play full increments of the idle anim local maxHealth = ship.GetMaxHealth().tofloat() local idleTime = RandomFloatRange( idleMin, idleMax ) local reps = ( duration / idleTime ).tointeger() local totalTime = reps * duration local endTime = Time() + totalTime for ( ;; ) { if ( ship.GetHealth().tofloat() / maxHealth < 0.2 ) return if ( Time() >= endTime ) return wait 0.1 } } entity function CreateDogFighter( vector origin, vector angles, int team ) { entity hornet if ( GetBugReproNum() == 81765 ) { hornet = CreateEntity( "npc_dropship" ) } else { // HACK: using a prop script for now since NPC dropships are still buggy // Jiesang told me to do it! hornet = CreatePropScript( GetGunshipModel( team ), origin, angles, 8 ) hornet.EnableAttackableByAI( 50, 0, AI_AP_FLAG_NONE ) SetTeam( hornet, team ) hornet.SetOrigin( origin ) hornet.SetAngles( angles ) } hornet.s.dogfighter <- true hornet.kv.teamnumber = team local title switch ( team ) { case TEAM_MILITIA: hornet.SetModel( GetFlightPathModel( "fp_hornet_model" ) ) title = "Militia Hornet" break case TEAM_IMC: hornet.SetModel( GetFlightPathModel( "fp_straton_model" ) ) title = "IMC Phantom" break } hornet.SetTitle( title ) hornet.SetOrigin( origin ) hornet.SetAngles( angles ) // DispatchSpawn( hornet ) //hornet.EnableRenderAlways() //hornet.SetAimAssistAllowed( false ) return hornet } void function OnDogFighterDeath( entity ent, var damageInfo ) { if ( !IsValid( ent ) ) return if ( !( "dogfighter" in ent.s ) ) return if ( ent.GetHealth() <= 0 ) FighterExplodes( ent ) } function AddRocketTurrets( entity ship, int team, int prof = eWeaponProficiency.VERYGOOD ) { entity turret = AddTurret( ship, team, "mp_weapon_yh803", "l_exhaust_front_1" ) turret.kv.WeaponProficiency = prof turret.NotSolid() turret.Show() entity weapon = turret.GetActiveWeapon() weapon.Show() turret = AddTurret( ship, team, "mp_weapon_yh803", "r_exhaust_front_1" ) turret.kv.WeaponProficiency = prof turret.NotSolid() turret.Show() weapon = turret.GetActiveWeapon() weapon.Show() } void function AddBulletTurrets( entity ship, int team, int prof = eWeaponProficiency.VERYGOOD ) { entity turret = AddTurret( ship, team, TURRET_WEAPON_BULLETS, "l_exhaust_front_1" ) turret.kv.WeaponProficiency = prof turret.NotSolid() turret = AddTurret( ship, team, TURRET_WEAPON_BULLETS, "r_exhaust_front_1" ) turret.kv.WeaponProficiency = prof turret.NotSolid() } asset function GetGunshipModel( int team ) { switch ( team ) { case TEAM_MILITIA: return GetFlightPathModel( "fp_hornet_model" ) case TEAM_IMC: return GetFlightPathModel( "fp_straton_model" ) } unreachable } void function CreateDogFighterAssist( int team, vector origin, vector angles, float duration = 10.0, entity ship = null, float dropHeight = 1500 ) { angles += <0,90,0> angles = < 0, angles.y%360, 0 > // DebugDrawSphere( origin, 256, 255, 0, 0, true, 10.0 ) // warp in effect before Point start = GetWarpinPosition( GetFighterModelForTeam( team ), "st_AngelCity_IMC_Win_ComeIn_fast", origin, angles ) if ( !IsValid( ship ) ) { ship = CreateDogFighter( start.origin, start.angles, team ) } else { ship.SetOrigin( start.origin ) ship.SetAngles( start.angles ) } waitthread __WarpInEffectShared( start.origin, start.angles, "", 0.0 ) ship.SetHealth( 10000 ) ship.SetMaxHealth( 10000 ) ship.EndSignal( "OnDeath" ) #if R1_VGUI_MINIMAP ship.Minimap_SetDefaultMaterial( GetMinimapMaterial( "VIP_friendly" ) ) ship.Minimap_SetFriendlyMaterial( GetMinimapMaterial( "VIP_friendly" ) ) ship.Minimap_SetEnemyMaterial( GetMinimapMaterial( "VIP_enemy" ) ) ship.Minimap_SetBossPlayerMaterial( GetMinimapMaterial( "VIP_friendly" ) ) #endif ship.Minimap_SetObjectScale( 0.11 ) ship.Minimap_SetZOrder( MINIMAP_Z_NPC ) entity mover = CreateScriptMover( origin, angles ) OnThreadEnd( function () : ( ship, mover ) { if ( IsValid( mover ) ) mover.Destroy() if ( IsValid( ship ) ) ship.Destroy() } ) float SHIP_SIZE = 530 vector SHIP_MIN = Vector( -SHIP_SIZE/2, -SHIP_SIZE/2, -250 ) vector SHIP_MAX = Vector( SHIP_SIZE/2, SHIP_SIZE/2, 100 ) entity turret turret = CreateEntity( "npc_turret_sentry" ) SetSpawnOption_AISettings( turret, "npc_turret_sentry_rockets_dropship" ) SetSpawnOption_Weapon( turret, "mp_turretweapon_blaster" ) SetSpawnOption_Alert( turret ) SetTeam( turret, team ) DispatchSpawn( turret ) turret.SetInvulnerable() turret.SetParent( ship, "r_turret_attach", false, 0.0 ) turret.SetTitle( ship.GetTitle() ) NPC_NoTarget( turret ) turret = CreateEntity( "npc_turret_sentry" ) SetSpawnOption_AISettings( turret, "npc_turret_sentry_rockets_dropship" ) SetSpawnOption_Weapon( turret, "mp_turretweapon_blaster" ) SetSpawnOption_Alert( turret ) SetTeam( turret, team ) DispatchSpawn( turret ) turret.SetInvulnerable() turret.SetParent( ship, "l_turret_attach", false, 0.0 ) turret.SetTitle( ship.GetTitle() ) NPC_NoTarget( turret ) // DrawArrow( origin, angles, 10, 50 ) waitthread PlayAnimTeleport( ship, "st_AngelCity_IMC_Win_ComeIn_fast", origin, angles ) // ------------------------------------------------- // now we want to drop the ship close to the ground // ------------------------------------------------- vector shipOrigin = ship.GetOrigin() vector newOrigin = shipOrigin if ( dropHeight > 0 ) { // TRACE to find the floor float traceFrac = TraceLineSimple( shipOrigin, shipOrigin - Vector(0,0,dropHeight), ship ) vector floorPos = shipOrigin - Vector(0,0,dropHeight * traceFrac) floorPos += Vector( 0,0,400 ) //we don't want the ship to land! // TRACE to see if anything is in the way float result = TraceHullSimple( shipOrigin, floorPos, SHIP_MIN, SHIP_MAX, ship ) vector offset = ( shipOrigin - floorPos ) * result // This is where we will move the spawnpoint newOrigin = origin - offset } // float duration = ship.GetSequenceDuration( "st_AngelCity_IMC_Win_Idle" ) ship.SetParent( mover, "REF" ) ship.Anim_EnableUseAnimatedRefAttachmentInsteadOfRootMotion() // Ship comes in... thread PlayAnim( ship, "st_AngelCity_IMC_Win_Idle", mover, "REF" ) // Ship goes down... float dropDuration = 5.0 if ( dropHeight > 0 ) { mover.NonPhysicsMoveTo( newOrigin, dropDuration, dropDuration*0.4, dropDuration*0.4 ) wait dropDuration } // Ship hangs out for a while... waitthread GunshipWaitLeave( ship, duration ) // Ship raises before it leaves... if ( dropHeight > 0 ) { mover.NonPhysicsMoveTo( origin, dropDuration, dropDuration*0.4, dropDuration*0.4 ) wait dropDuration } ship.ClearParent() // Ship leaves... waitthread PlayAnim( ship, "st_AngelCity_IMC_Win_Leave", origin, angles, 0.5 ) } void function GunshipWaitLeave( entity ship, float duration ) { ship.EndSignal( "GunshipForceLeave" ) wait duration } asset function GetFighterModelForTeam( int team ) { switch ( team ) { case TEAM_MILITIA: return GetFlightPathModel( "fp_hornet_model" ) case TEAM_IMC: return GetFlightPathModel( "fp_straton_model" ) } unreachable }