aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut545
1 files changed, 545 insertions, 0 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut b/Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut
new file mode 100644
index 00000000..72ff58b7
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/rodeo/_rodeo.gnut
@@ -0,0 +1,545 @@
+untyped
+
+global function Rodeo_Init
+
+global function CodeCallback_StartRodeo
+global function CodeCallback_ForceEndRodeo
+global function CodeCallback_EmbarkTitan
+global function CodeCallback_EmbarkTitanFromGrapple
+
+global function PlayerBeginsRodeo
+global function WatchForPlayerJumpingOffRodeo
+global function PlayerJumpsOffRodeoTarget
+global function PlayerClimbsIntoRodeoPosition
+global function rodeodebug
+
+//-----------------------------------------------------------------------------
+// _rodeo.nut
+//
+// The central location for rodeo, mostly a place to put code callbacks that
+// then call other things in other files based on the thing being rodeod.
+//
+//-----------------------------------------------------------------------------
+//
+// HOW TO ADD A NEW RODEO TYPE
+//
+// Create a new file for the rodeo type like _rodeo_prowler.nut and:
+// Implement "IsValid_NEWTYPE_RodeoTarget()"
+// Implement "GetRodeoPackage_RIDER_to_NEWTYPE_()"
+// Implement "_RIDER_Begins_NEWTYPE_Rodeo()"
+// Implement "_RIDER_LerpsInto_NEWTYPE_Rodeo()"
+//
+// _RIDER_ is the rodeo rider type like "Player" or "Prowler"
+// _NEWTYPE_ is the new kind of rodeo target like "SuperSpectre" or "Drone"
+//
+// In _rodeo_shared.nut:
+// IncludeFile() the NEWTYPE file
+// Add a hook for NEWTYPE in CodeCallback_OnRodeoAttach()
+// Add a hook for NEWTYPE in CodeCallback_IsValidRodeoTarget()
+// Add a hook for NEWTYPE in GetRodeoPackage() if needed
+//
+//-----------------------------------------------------------------------------
+
+function Rodeo_Init()
+{
+ RodeoShared_Init()
+ RodeoTitan_Init()
+ RegisterSignal( "RodeoPointOfNoReturn" )
+ AddCallback_OnTitanDoomed( OnTitanDoomed_Rodeo )
+}
+
+
+void function CodeCallback_EmbarkTitan( entity player, entity titan )
+{
+ if ( player.Lunge_IsActive() && (titan == player.Lunge_GetTargetEntity()) )
+ {
+ if ( PlayerCanImmediatelyEmbarkTitan( player, titan ) )
+ {
+ table embarkDirection = expect table( FindBestEmbark( player, titan ) )
+ thread PlayerEmbarksTitan( player, titan, embarkDirection )
+ }
+ }
+}
+
+bool function CodeCallback_EmbarkTitanFromGrapple( entity player, entity titan )
+{
+ Assert( player.IsHuman() )
+ Assert( titan.IsTitan() )
+
+ if ( !PlayerCanEmbarkIntoTitan( player, titan ) )
+ return false
+
+ table ornull embarkDirection = expect table ornull( FindBestEmbark( player, titan, false ) )
+ if ( !embarkDirection )
+ return false
+
+ expect table( embarkDirection )
+ thread PlayerEmbarksTitan( player, titan, embarkDirection )
+
+ return true
+}
+
+
+void function CodeCallback_StartRodeo( entity player, entity rodeoTarget )
+{
+ if ( IsMenuLevel() )
+ return
+
+ // Review: Good to remove?
+ if ( GetBugReproNum() == 7205 )
+ {
+ thread RodeoTest( player, rodeoTarget )
+ return
+ }
+
+ thread PlayerBeginsRodeo( player, player.p.rodeoPackage, rodeoTarget )
+}
+
+
+void function CodeCallback_ForceEndRodeo( entity player )
+{
+ ForceEndRodeo( player )
+}
+
+void function ForceEndRodeo( entity player )
+{
+ player.Signal( "RodeoOver" )
+}
+
+
+function RodeoTest( player, rodeoTarget )
+{
+ player.SetParent( rodeoTarget, "RODEO", false, 1 )
+ wait 5
+ player.ClearParent()
+ Rodeo_Detach( player )
+}
+
+function PlayerBeginsRodeo( entity player, RodeoPackageStruct rodeoPackage, entity rodeoTarget )
+{
+ Assert( player.GetParent() == null )
+ player.Lunge_ClearTarget()
+
+ Assert( IsValid( player ) )
+ Assert( IsValid( rodeoTarget ) )
+ Assert( !player.IsTitan() )
+
+ if ( rodeoTarget.IsTitan() )
+ PlayerBeginsTitanRodeo( player, rodeoPackage, rodeoTarget )
+ else
+ PlayerBeginsNPCRodeo( player, rodeoPackage, rodeoTarget ) //Not tested very well since non-Titan Rodeo never really became a thing. Should work thought
+}
+
+function PlayerBeginsNPCRodeo( entity player, RodeoPackageStruct rodeoPackage, entity rodeoTarget )
+{
+ bool sameTeam = player.GetTeam() == rodeoTarget.GetTeam()
+ bool playerWasEjecting = player.p.pilotEjecting // have to store this off here because the "RodeoStarted" signal below ends eject, so it will be too late to check it in actual rodeo function
+
+ player.Signal( "RodeoStarted" )
+
+ OnThreadEnd(
+ function () : ( player, rodeoTarget )
+ {
+ RodeoPackageStruct rodeoPackage = player.p.rodeoPackage
+
+ entity newRodeoTarget = rodeoTarget
+ if ( IsValid( player ) )
+ {
+ player.Signal( "RodeoOver" )
+
+ // Added via AddCallback_OnRodeoEnded
+ foreach ( callbackFunc in level.onRodeoEndedCallbacks ) //TODO: Remove this!
+ {
+ callbackFunc( player )
+ }
+
+ // show name of the pilot again
+ player.SetNameVisibleToFriendly( true )
+ player.SetNameVisibleToEnemy( true )
+
+ ClearPlayerAnimViewEntity( player )
+
+ // blend out the clear anim view entity
+ player.AnimViewEntity_SetLerpOutTime( 0.4 )
+
+ player.ClearParent()
+ player.Anim_Stop()
+ player.SetOneHandedWeaponUsageOff()
+ player.SetTitanSoulBeingRodeoed( null )
+ player.UnforceStand()
+ player.kv.PassDamageToParent = false
+ player.TouchGround() // so you can double jump off
+
+ StopSoundOnEntity( player, rodeoPackage.cockpitSound )
+ StopSoundOnEntity( player, rodeoPackage.worldSound )
+
+ if ( Rodeo_IsAttached( player ) )
+ {
+ Rodeo_Detach( player )
+ }
+
+ if ( IsAlive( player ) )
+ {
+ int attachIndex = newRodeoTarget.LookupAttachment( rodeoPackage.attachPoint )
+ vector startPos = newRodeoTarget.GetAttachmentOrigin( attachIndex )
+
+ if ( !PlayerCanTeleportHere( player, startPos, newRodeoTarget ) )
+ {
+ startPos = newRodeoTarget.GetOrigin()
+ if ( !PlayerCanTeleportHere( player, startPos, newRodeoTarget ) )
+ startPos = player.GetOrigin()
+ }
+
+ thread PlayerJumpsOffRodeoTarget( player, newRodeoTarget, startPos )
+ }
+ }
+ }
+ )
+
+ rodeoTarget.EndSignal( "OnDestroy" )
+ player.EndSignal( "OnDeath" )
+ player.EndSignal( "RodeoOver" )
+
+ string rodeoTargetType = rodeoPackage.rodeoTargetType
+
+ thread WatchForPlayerJumpingOffRodeo( player )
+
+ player.SetNameVisibleToFriendly( false ) // hide name of the pilot while he is rodeoing
+ player.SetNameVisibleToEnemy( false )
+ player.ForceStand()
+ HolsterAndDisableWeapons( player )
+ player.SetOneHandedWeaponUsageOn()
+ player.TouchGround() // so you can double jump off
+
+ waitthread PlayerClimbsIntoRodeoPosition( player, rodeoTarget, rodeoPackage, playerWasEjecting )
+
+ #if FACTION_DIALOGUE_ENABLED
+ if ( !sameTeam )
+ PlayFactionDialogueToPlayer( "kc_rodeo", player )
+ #endif
+
+ // Go straight into idle animations
+ FirstPersonSequenceStruct sequence
+ sequence.thirdPersonAnimIdle = GetAnimFromAlias( rodeoTargetType, "pt_rodeo_panel_aim_idle" )
+ sequence.firstPersonAnimIdle = GetAnimFromAlias( rodeoTargetType, "ptpov_rodeo_panel_aim_idle" )
+
+ if ( !rodeoPackage.useAttachAngles )
+ player.Anim_IgnoreParentRotation( true )
+
+ sequence.useAnimatedRefAttachment = true
+
+ thread FirstPersonSequence( sequence, player, rodeoTarget )
+
+ if ( sameTeam )
+ {
+ player.GetFirstPersonProxy().HideFirstPersonProxy()
+ OpenViewCone( player )
+ }
+ else
+ {
+ PlayerRodeoViewCone( player, rodeoTargetType ) // TODO: Add air_drone and make enum in this func()
+ }
+
+ // look! he rodeoed!
+ thread AIChatter( "aichat_rodeo_cheer", player.GetTeam(), player.GetOrigin() )
+
+ Rodeo_OnFinishClimbOnAnimation( player ) // This is to let code know the player has finished climbing on the rodeo and ready to fire
+
+ if ( sameTeam )
+ {
+ player.PlayerCone_Disable()
+ player.EnableWorldSpacePlayerEyeAngles()
+ }
+
+ DeployAndEnableWeapons( player )
+
+ WaitForever()
+}
+
+void function PlayerClimbsIntoRodeoPosition( entity player, entity rodeoTarget, RodeoPackageStruct rodeoPackage, bool playerWasEjecting = false ) //TODO: Rename this function since new style rodeo anims have climbing as part of the anim
+{
+ player.EndSignal( "OnDeath" )
+
+
+ // The only thing that should have a soul is titans now. Legacy. Can't remove without major code feature work.
+ entity soul
+ if ( rodeoTarget.IsTitan() )
+ {
+ soul = rodeoTarget.GetTitanSoul()
+ soul.EndSignal( "OnTitanDeath" )
+ soul.EndSignal( "OnDestroy" )
+ }
+ else
+ {
+ rodeoTarget.EndSignal( "OnTitanDeath" )
+ rodeoTarget.EndSignal( "OnDestroy" )
+ }
+
+ FirstPersonSequenceStruct sequence
+ sequence.attachment = rodeoPackage.attachPoint
+ SetRodeoAnimsFromPackage( sequence, rodeoPackage )
+
+ switch ( rodeoPackage.method )
+ {
+ case RODEO_APPROACH_FALLING_FROM_ABOVE:
+ table animStartPos = player.Anim_GetStartForRefEntity_Old( sequence.thirdPersonAnim, rodeoTarget, rodeoPackage.attachPoint )
+ float dist = Distance( player.GetOrigin(), animStartPos.origin )
+ float speed = Length( player.GetVelocity() )
+ float fallTime = dist / speed
+ fallTime *= 0.95
+
+ sequence.blendTime = clamp( fallTime, 0.4, 1 )
+
+ break
+
+ case RODEO_APPROACH_JUMP_ON:
+ sequence.blendTime = 0.6
+ break
+
+ default:
+ Assert( 0, "Unhandled rodeo method " + rodeoPackage.method )
+ }
+
+ if ( !PlayerHasPassive( player, ePassives.PAS_STEALTH_MOVEMENT ) )
+ EmitDifferentSoundsOnEntityForPlayerAndWorld( rodeoPackage.cockpitSound, rodeoPackage.worldSound, player, rodeoTarget )
+
+ string titanType
+
+ // Titans only
+ if ( IsValid( soul ) )
+ {
+ if ( !( player in soul.rodeoRiderTracker ) )
+ {
+ soul.rodeoRiderTracker[ player ] <- true
+ if ( rodeoTarget.GetTeam() == player.GetTeam() )
+ {
+ AddPlayerScore( player, "HitchRide" )
+ AddPlayerScore( rodeoTarget, "GiveRide" )
+ }
+ else
+ {
+ AddPlayerScore( player, "RodeoEnemyTitan" )
+
+ #if HAS_STATS
+ UpdatePlayerStat( player, "misc_stats", "rodeos" )
+
+ if ( playerWasEjecting )
+ UpdatePlayerStat( player, "misc_stats", "rodeosFromEject" )
+ #endif
+
+ #if SERVER && MP
+ PIN_AddToPlayerCountStat( player, "rodeos" )
+ if ( rodeoTarget.IsPlayer() )
+ PIN_AddToPlayerCountStat( rodeoTarget, "rodeo_receives" )
+ #endif
+ }
+ }
+
+ titanType = GetSoulTitanSubClass( soul )
+ }
+
+ MessageToPlayer( player, eEventNotifications.Rodeo_HideBatteryHint )
+
+ float time = player.GetSequenceDuration( sequence.thirdPersonAnim )
+
+ if ( !rodeoPackage.useAttachAngles )
+ player.Anim_IgnoreParentRotation( true )
+
+ thread FirstPersonSequence( sequence, player, rodeoTarget )
+ wait time
+}
+
+void function WatchForPlayerJumpingOffRodeo( entity player )
+{
+ player.EndSignal( "OnDeath" )
+ player.EndSignal( "RodeoOver" )
+ player.EndSignal( "RodeoPointOfNoReturn" )
+
+ wait 0.6 // debounce so you dont accihop
+
+ AddButtonPressedPlayerInputCallback( player, IN_JUMP, ForceEndRodeo )
+
+ OnThreadEnd(
+ function() : ( player )
+ {
+ //RodeoOver is signalled at the end of PlayerBeginsRodeo, so even if Rodeo ends via the Titan disconnecting etc this will run
+ RemoveButtonPressedPlayerInputCallback( player, IN_JUMP, ForceEndRodeo )
+ }
+ )
+
+ WaitForever()
+}
+
+
+void function PlayerJumpsOffRodeoTarget( entity player, entity rodeoTarget, vector startPos )
+{
+ #if DEV
+ if ( GetDebugRodeoPrint() )
+ printt( "PlayerJumpsOffRodeoTarget, playerPos: " + player.GetOrigin() + " playerAngles: " + player.GetAngles() + " rodeoTargetPos: " + rodeoTarget.GetOrigin() + " rodeoTargetAngles: " + rodeoTarget.GetAngles() + ", startPos: " + startPos )
+ #endif
+
+ // ejected, or rip off battery, etc. Those adjust velocity for the rodeo player anyway, so don't do any more adjustments for them.
+ if ( player.p.rodeoShouldAdjustJumpOffVelocity == false )
+ return
+
+ if ( !IsValid( rodeoTarget ) )
+ {
+ PutEntityInSafeSpot( player, null, null, startPos, player.GetOrigin() )
+
+ #if DEV
+ if ( GetDebugRodeoPrint() )
+ printt( "PlayerJumpsOffRodeoTarget, playerPos after PutEntityInSafeSpot, !ISValid(rodeoTarget): " + player.GetOrigin() )
+ #endif
+ return
+ }
+
+ PutEntityInSafeSpot( player, rodeoTarget, null, startPos, player.GetOrigin() )
+ #if DEV
+ if ( GetDebugRodeoPrint() )
+ printt( "PlayerJumpsOffRodeoTarget, playerPos after PutEntityInSafeSpot, rodeoTarget valid: " + player.GetOrigin() )
+ #endif
+
+ EmitDifferentSoundsOnEntityForPlayerAndWorld( "Rodeo_Jump_Off_Interior", "Rodeo_Jump_Off", player, rodeoTarget )
+
+ vector forward = player.GetViewForward()
+ vector right = player.GetViewRight()
+
+ forward.z = 0
+ right.z = 0
+
+ // map the player's controls to his angles, and add that velocity
+ float xAxis = player.GetInputAxisRight()
+ float yAxis = player.GetInputAxisForward()
+
+ vector velocity
+ if ( fabs( xAxis ) < 0.2 && fabs( yAxis ) < 0.2 )
+ {
+ // no press = back press
+ velocity = Vector(0,0,0)
+ }
+ else
+ {
+ vector forwardVec = forward * yAxis
+ vector rightVec = right * xAxis
+ vector directionVec = ( rightVec + forwardVec )
+
+ //printt( "ForwardVec: " + forwardVec + ", rightVec: " + rightVec + ", directionVec :" + directionVec + ", directionVec scaled: " + (directionVec * 350 ) ) // for bug 123013
+
+ float speed = 350
+ velocity = directionVec * speed
+ }
+
+ // IMPORTANT: Don't give boost pilots too much vertical or they go sky high
+ if ( player.GetPlayerSettingsField( "boostEnabled" ).tointeger() > 0 )
+ velocity += Vector(0,0,200)
+ else
+ velocity += Vector(0,0,390 )
+
+ //printt( "Setting velocity to: " + velocity ) // for bug 123013
+
+ player.SetVelocity( velocity )
+ player.JumpedOffRodeo()
+}
+
+void function rodeodebug()
+{
+ // console command for forcing rodeo amongst 2 players
+ thread makerodeothread()
+}
+
+void function makerodeothread()
+{
+ array<entity> players = GetPlayerArray()
+ vector titanOrg
+ bool titanOrgSet = false
+ entity titan, pilot
+
+ for ( int i = players.len() - 1; i >= 0; i-- )
+ {
+ entity player = players[i]
+
+ if ( player.IsTitan() )
+ {
+ titan = player
+ }
+ else
+ {
+ pilot = player
+ }
+ }
+
+ if ( !titan )
+ {
+ for ( int i = players.len() - 1; i >= 0; i-- )
+ {
+ entity player = players[i]
+
+ if ( !player.IsTitan() )
+ {
+ player.SetPlayerSettings( "titan_atlas" )
+ titan = player
+ break
+ }
+ }
+ }
+ else
+ if ( !pilot )
+ {
+ for ( int i = players.len() - 1; i >= 0; i-- )
+ {
+ entity player = players[i]
+
+ if ( player.IsTitan() )
+ {
+ thread TitanEjectPlayer( player )
+ wait 1.5
+ pilot = player
+ break
+ }
+ }
+ }
+
+ for ( int i = players.len() - 1; i >= 0; i-- )
+ {
+ entity player = players[i]
+
+ if ( player.IsTitan() )
+ {
+ titanOrg = player.GetOrigin()
+ titanOrgSet = true
+ }
+ }
+
+ if ( !titanOrgSet )
+ return
+
+ for ( int i = players.len() - 1; i >= 0; i-- )
+ {
+ entity player = players[i]
+
+ if ( !player.IsTitan() )
+ {
+ vector angles = titan.GetAngles()
+ vector forward = AnglesToForward( angles )
+ titanOrg += forward * -100
+ titanOrg.z += 500
+ angles.x = 30
+ player.SetAngles( angles )
+ player.SetOrigin( titanOrg )
+ player.SetVelocity( Vector(0,0,0) )
+ break
+ }
+ }
+}
+
+void function OnTitanDoomed_Rodeo( entity titan, var damageInfo )
+{
+ if ( !IsAlive( titan ) )
+ return
+
+ entity rodeoPilot = GetRodeoPilot( titan )
+ if ( !IsValid( rodeoPilot ) )
+ return
+
+ Remote_CallFunction_NonReplay( rodeoPilot, "ServerCallback_UpdateRodeoRiderHud" )
+} \ No newline at end of file