aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut600
1 files changed, 0 insertions, 600 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut b/Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut
deleted file mode 100644
index 588b4d75e..000000000
--- a/Northstar.CustomServers/scripts/vscripts/ai/_ai_marvin_jobs.gnut
+++ /dev/null
@@ -1,600 +0,0 @@
-
-/*
- ToDo:
- -if marvin has no jobs to go to make him to back to spawn position instead of standing at last node
-*/
-
-global function MarvinJobs_Init
-global function MarvinJobThink
-global function GetMarvinType
-
-const DEBUG_MARVIN_JOBS = false
-const MAX_JOB_SEARCH_DIST_SQR = 1000 * 1000
-const JOB_NODE_COOLDOWN_TIME = 15.0
-
-struct MarvinJob
-{
- string validMarvinType
- entity node
- entity user
- string jobType
- bool tempJob
- float nextUsableTime = 0
- entity barrel
-}
-
-struct
-{
- array<MarvinJob> marvinJobs
- table<string,void functionref( entity,MarvinJob)> jobFunctions
-} file
-
-
-
-
-// ██╗███╗ ██╗██╗████████╗
-// ██║████╗ ██║██║╚══██╔══╝
-// ██║██╔██╗ ██║██║ ██║
-// ██║██║╚██╗██║██║ ██║
-// ██║██║ ╚████║██║ ██║
-// ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝
-
-void function MarvinJobs_Init()
-{
- file.jobFunctions[ "welding" ] <- SimpleJobAnims
- file.jobFunctions[ "welding_under" ] <- SimpleJobAnims
- file.jobFunctions[ "window" ] <- SimpleJobAnims
- file.jobFunctions[ "fightFire" ] <- SimpleJobAnims
- file.jobFunctions[ "barrel_pickup" ] <- MarvinPicksUpBarrel
- file.jobFunctions[ "barrel_putdown" ] <- MarvinPutsDownBarrel
- file.jobFunctions[ "repair_over_edge" ] <- SimpleJobAnims
- file.jobFunctions[ "repair_above" ] <- SimpleJobAnims
- file.jobFunctions[ "repair_under" ] <- SimpleJobAnims
- file.jobFunctions[ "datacards" ] <- SimpleJobAnims
-
- file.jobFunctions[ "drone_welding" ] <- SimpleJobAnims
- file.jobFunctions[ "drone_inspect" ] <- SimpleJobAnims
-
- RegisterSignal( "pickup_barrel" )
- RegisterSignal( "putdown_barrel" )
- RegisterSignal( "JobStarted" )
- RegisterSignal( "StopDoingJobs" )
-
- AddSpawnCallback( "script_marvin_job", InitMarvinJob )
-
- AddCallback_EntitiesDidLoad( MarvinJobsEntitiesDidLoad )
-}
-
-void function InitMarvinJob( entity node )
-{
- Assert( node.HasKey( "job" ) )
- Assert( node.kv.job != "" )
- Assert( string( node.kv.job ) in file.jobFunctions, "Marvin job node at " + node.GetOrigin() + " has unhandled job type " + string( node.kv.job ) )
- string editorClass = GetEditorClass( node )
-
- // Drop node to ground for certain types or if checked on the entity
- if ( editorClass == "" )
- {
- if ( !node.HasKey( "hover" ) || node.kv.hover != "1" )
- DropToGround( node )
- }
-
- if ( DEBUG_MARVIN_JOBS )
- DebugDrawAngles( node.GetOrigin(), node.GetAngles() )
-
- // Create marvin job struct
- MarvinJob marvinJob
- marvinJob.node = node
- marvinJob.jobType = string( node.kv.job )
- marvinJob.tempJob = node.HasKey( "tempJob" ) && node.kv.tempJob == "1"
-
- if ( marvinJob.jobType == "barrel_pickup" )
- marvinJob.barrel = CreateBarrel( node )
-
- // Set what marvin_type of NPC can use this job
- switch ( editorClass )
- {
- case "script_marvin_drone_job":
- marvinJob.validMarvinType = "marvin_type_drone"
- break
- default:
- marvinJob.validMarvinType = "marvin_type_walker"
- break
- }
-
- file.marvinJobs.append( marvinJob )
-}
-
-void function MarvinJobsEntitiesDidLoad()
-{
- if ( DEBUG_MARVIN_JOBS )
- DebugMarvinJobs()
-}
-
-
-
-
-
-// ████████╗██╗ ██╗██╗███╗ ██╗██╗ ██╗
-// ╚══██╔══╝██║ ██║██║████╗ ██║██║ ██╔╝
-// ██║ ███████║██║██╔██╗ ██║█████╔╝
-// ██║ ██╔══██║██║██║╚██╗██║██╔═██╗
-// ██║ ██║ ██║██║██║ ╚████║██║ ██╗
-// ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝
-
-void function MarvinJobThink( entity marvin )
-{
- EndSignal( marvin, "OnDeath" )
- EndSignal( marvin, "OnDestroy" )
- EndSignal( marvin, "StopDoingJobs" )
-
- // Wait a frame because npcs that are spawned at map load may run this function before job nodes are finished being initialized
- WaitFrame()
-
- // Get all jobs this marvin can do
- array<MarvinJob> jobs = GetJobsForMarvin( marvin )
- if ( jobs.len() == 0 )
- return
-
- OnThreadEnd(
- function() : ( marvin )
- {
- Assert( !IsAlive( marvin ), "MarvinJobThink ended but the marvin is still alive" )
- }
- )
-
- while ( true )
- {
- foreach ( MarvinJob job in jobs )
- {
- waitthread MarvinDoJob( marvin, job )
- WaitFrame()
- }
-
- jobs.randomize()
- WaitFrame()
- }
-}
-
-void function MarvinDoJob( entity marvin, MarvinJob job )
-{
- Assert( IsAlive( marvin ), "Marvin " + marvin + " is not alive" )
- EndSignal( marvin, "OnFailedToPath" )
- EndSignal( marvin, "OnDeath" )
-
- // Don't do a job that's already in use or not ready to be used again
- if ( IsValid( job.user ) || Time() < job.nextUsableTime )
- return
-
- // Don't use a barrel put down job if you can'r carrying a barrel
- if ( job.jobType == "barrel_putdown" && !IsValid( marvin.ai.carryBarrel ) )
- return
-
- // If you're carrying a barrel, only do a barrel put down job
- if ( IsValid( marvin.ai.carryBarrel ) && job.jobType != "barrel_putdown" )
- return
-
- OnThreadEnd(
- function() : ( job )
- {
- job.user = null
- job.nextUsableTime = Time() + JOB_NODE_COOLDOWN_TIME
- }
- )
-
- // Default walk anim
- MarvinDefaultMoveAnim( marvin )
-
- // Node gets occupied
- job.user = marvin
-
- if ( DEBUG_MARVIN_JOBS )
- DebugDrawLine( marvin.GetWorldSpaceCenter(), job.node.GetOrigin(), 255, 0, 0, true, 3.0 )
-
- // Run the job function
- thread DontDisableJobOnPathFailOrDeath( marvin, job )
- waitthread file.jobFunctions[ job.jobType ]( marvin, job )
- if ( IsValid( marvin ) )
- marvin.Anim_Stop()
-}
-
-void function DontDisableJobOnPathFailOrDeath( entity marvin, MarvinJob job )
-{
- EndSignal( marvin, "JobStarted" )
- WaitSignal( marvin, "OnFailedToPath", "OnDeath" )
- job.nextUsableTime = Time()
-}
-
-
-
-
-
-// ██╗ ██████╗ ██████╗ ███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗███████╗
-// ██║██╔═══██╗██╔══██╗ ██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
-// ██║██║ ██║██████╔╝ █████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
-// ██ ██║██║ ██║██╔══██╗ ██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
-// ╚█████╔╝╚██████╔╝██████╔╝ ██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║███████║
-// ╚════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
-
-void function SimpleJobAnims( entity marvin, MarvinJob job )
-{
- // Get the anims to use for the job
- array<string> anims
- switch ( job.jobType )
- {
- // Marvin jobs
- case "welding":
- anims.append( "mv_idle_weld" )
- break
- case "welding_under":
- anims.append( "mv_weld_under" )
- anims.append( "mv_weld_under" )
- anims.append( "mv_weld_under_stumble" )
- break
- case "window":
- anims.append( "mv_idle_wash_window_noloop" )
- anims.append( "mv_idle_buff_window_noloop" )
- break
- case "fightFire":
- anims.append( "mv_fireman_idle" )
- anims.append( "mv_fireman_shift" )
- break
- case "repair_over_edge":
- anims.append( "mv_repair_overedge" )
- anims.append( "mv_repair_overedge" )
- anims.append( "mv_repair_overedge_stumble" )
- break
- case "repair_above":
- anims.append( "mv_repair_ship_above" )
- break
- case "repair_under":
- anims.append( "mv_repair_under" )
- anims.append( "mv_repair_under_stumble" )
- break
- case "datacards":
- anims.append( "mv_job_replace_datacards" )
- break
-
- // Marvin drone jobs
- case "drone_welding":
- anims.append( "dw_jobs_welding_wallpanel" )
- break
- case "drone_inspect":
- anims.append( "inspect1" )
- anims.append( "inspect2" )
- break
- }
- Assert( anims.len() > 0 )
-
- if ( IsMarvinWalker( marvin ) )
- waitthread MarvinRunToAnimStart( marvin, anims[0], job.node )
- else
- waitthread MarvinFlyToAnimStart( marvin, anims[0], job.node )
-
- Signal( marvin, "JobStarted" )
-
- while ( true )
- {
- anims.randomize()
- foreach ( string anim in anims )
- {
- float animLength = marvin.GetSequenceDuration( anim ) // wait anim length because some anims may be looping so we can't wait for them to end
-
- if ( IsMarvinDrone( marvin ) )
- thread PlayAnimTeleport( marvin, anim, job.node )
- else
- thread PlayAnim( marvin, anim, job.node, null, 0.6 )
-
- wait animLength
- }
- if ( job.tempJob )
- break
- }
-}
-
-void function MarvinPicksUpBarrel( entity marvin, MarvinJob job )
-{
- // Don't try to pick up a barrel if there isn't one nearby
- if ( !IsValid( job.barrel ) )
- return
- if ( Distance( job.node.GetOrigin(), job.barrel.GetOrigin() ) > 25 )
- return
-
- EndSignal( job.barrel, "OnDestroy" )
-
- entity info_target = CreateEntity( "info_target" )
- DispatchSpawn( info_target )
-
- OnThreadEnd(
- function () : ( info_target )
- {
- info_target.Destroy()
- }
- )
-
- vector barrelFlatAngles = job.barrel.GetAngles()
- barrelFlatAngles.x = 0
- barrelFlatAngles.z = 0
-
- info_target.SetOrigin( job.barrel.GetOrigin() )
- info_target.SetAngles( barrelFlatAngles )
-
- DropToGround( info_target )
-
- if ( info_target.GetOrigin().z < -MAX_WORLD_COORD )
- return // Fell through map
-
- if ( DEBUG_MARVIN_JOBS )
- thread DrawAnglesForMovingEnt( info_target, 30.0 )
-
-
- // Go to the barrel
- MarvinRunToAnimStart( marvin, "mv_carry_barrel_pickup", info_target )
-
- // Try to pick it up
- thread PlayAnim( marvin, "mv_carry_barrel_pickup", info_target, null, 0.6 )
-
- // Wait until animation should pick up the barrel
- marvin.WaitSignal( "pickup_barrel" )
-
- // Get attachment info
- string attachment = "PROPGUN"
- int attachIndex = marvin.LookupAttachment( attachment )
- vector attachOrigin = marvin.GetAttachmentOrigin( attachIndex )
-
- // Make sure the barrel is close when it's time to parent the barrel
- if ( Distance( attachOrigin, job.barrel.GetOrigin() ) > 25 )
- {
- marvin.Anim_Stop()
- return
- }
-
- // Marvin picks up the barrel and carries it
- thread MarvinCarryBarrel( marvin, job.barrel )
-
- marvin.WaitSignal( "OnAnimationDone" )
-}
-
-void function MarvinCarryBarrel( entity marvin, entity barrel )
-{
- marvin.EndSignal( "OnDeath" )
- marvin.EndSignal( "OnDamaged" )
- marvin.EndSignal( "putdown_barrel" )
-
- OnThreadEnd(
- function () : ( marvin, barrel )
- {
- if ( IsValid( barrel ) )
- {
- barrel.kv.solid = SOLID_VPHYSICS
- barrel.ClearParent()
- barrel.SetOwner( null )
- EntFireByHandle( barrel, "wake", "", 0, null, null )
- EntFireByHandle( barrel, "enablemotion", "", 0, null, null )
- }
-
- if ( IsAlive( marvin ) )
- {
- MarvinDefaultMoveAnim( marvin )
- marvin.ClearIdleAnim()
- marvin.ai.carryBarrel = null
- }
- }
- )
-
- string attachment = "PROPGUN"
- marvin.SetMoveAnim( "mv_carry_barrel_walk" )
- marvin.SetIdleAnim( "mv_carry_barrel_idle" )
- barrel.SetParent( marvin, attachment, false, 0.5 )
- barrel.SetOwner( marvin )
-
- barrel.kv.solid = 0 // not solid
-
- marvin.ai.carryBarrel = barrel
-
- WaitSignal( marvin, "OnDestroy" )
-}
-
-void function MarvinPutsDownBarrel( entity marvin, MarvinJob job )
-{
- Assert( IsValid( marvin.ai.carryBarrel ) )
-
- // Don't place a barrel here if there is already one
- if ( IsValid( job.barrel ) )
- {
- if ( Distance( job.node.GetOrigin(), job.barrel.GetOrigin() ) <= 25 )
- return
- }
-
- EndSignal( marvin.ai.carryBarrel, "OnDestroy" )
-
- marvin.SetMoveAnim( "mv_carry_barrel_walk" )
- marvin.SetIdleAnim( "mv_carry_barrel_idle" )
-
- // Walk to the put down spot
- MarvinRunToAnimStart( marvin, "mv_carry_barrel_putdown", job.node )
-
- // Put down the barrel
- thread PlayAnim( marvin, "mv_carry_barrel_putdown", job.node, null, 0.6 )
-
- // Wait for release
- marvin.WaitSignal( "putdown_barrel" )
-
- marvin.WaitSignal( "OnAnimationDone" )
-}
-
-
-
-
-// ██╗ ██╗████████╗██╗██╗ ██╗████████╗██╗ ██╗
-// ██║ ██║╚══██╔══╝██║██║ ██║╚══██╔══╝╚██╗ ██╔╝
-// ██║ ██║ ██║ ██║██║ ██║ ██║ ╚████╔╝
-// ██║ ██║ ██║ ██║██║ ██║ ██║ ╚██╔╝
-// ╚██████╔╝ ██║ ██║███████╗██║ ██║ ██║
-// ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝
-
-bool function IsMarvinWalker( entity marvin )
-{
- return GetMarvinType( marvin ) == "marvin_type_walker"
-}
-
-bool function IsMarvinDrone( entity marvin )
-{
- return GetMarvinType( marvin ) == "marvin_type_drone"
-}
-
-string function GetMarvinType( entity npc )
-{
- var marvinType = npc.Dev_GetAISettingByKeyField( "marvin_type" )
- if ( marvinType == null )
- return "not_marvin"
-
- return expect string( marvinType )
-}
-
-bool function IsJobNode( entity node )
-{
- if ( node.GetClassName() == "script_marvin_job" )
- return true
- if ( GetEditorClass( node ) == "script_marvin_drone_job" )
- return true
- return false
-}
-
-void function MarvinDefaultMoveAnim( entity marvin )
-{
- if ( IsMarvinWalker( marvin ) )
- {
- marvin.SetNPCMoveSpeedScale( 1.0 )
- marvin.SetMoveAnim( "walk_all" )
- }
-}
-
-array<MarvinJob> function GetJobsForMarvin( entity marvin )
-{
- string marvinType = GetMarvinType( marvin )
-
- // Get jobs this marvin links to, if any, and randomize
- array<MarvinJob> linkedJobs
- array<entity> linkedEnts = marvin.GetLinkEntArray()
- foreach ( entity ent in linkedEnts )
- {
- if ( IsJobNode( ent ) )
- {
- MarvinJob linkedJob = GetMarvinJobForNode( ent )
- Assert( IsValid( linkedJob.node ) )
-
- // Error if we are linking to the wrong type of job node
- Assert( marvinType == linkedJob.validMarvinType, "npc_marvin at " + marvin.GetOrigin() + " links to a marvin job of the wrong marvin_type" )
-
- linkedJobs.append( linkedJob )
- }
- }
- linkedJobs.randomize()
-
- // If marvin was linked to jobs we only consider those
- if ( marvin.HasKey( "LinkedJobsOnly" ) && marvin.kv.LinkedJobsOnly == "1" )
- {
- Assert( linkedJobs.len() > 0, "marvin at " + marvin.GetOrigin() + " has LinkedJobsOnly marked but does not link to any job nodes" )
- return linkedJobs
- }
-
- // Add all jobs within valid distance and randomize
- array<MarvinJob> jobs
- foreach ( MarvinJob marvinJob in file.marvinJobs )
- {
- if ( marvinType != marvinJob.validMarvinType )
- continue
-
- // Don't re-add a job that was linked to
- if ( linkedJobs.contains( marvinJob ) )
- continue
-
- // Teleport nodes are for special case jobs with no nav mesh do son't consider them automatically
- if ( marvinJob.node.HasKey( "teleport" ) && marvinJob.node.kv.teleport == "1" )
- continue
-
- // Only search for jobs within a max distance
- if ( DistanceSqr( marvinJob.node.GetOrigin(), marvin.GetOrigin() ) <= MAX_JOB_SEARCH_DIST_SQR )
- jobs.append( marvinJob )
- }
-
- // Randomize the order so the marvin does them out of order
- jobs.randomize()
-
- // Add the linked jobs to the list, and put them at the beginning of the priority
- foreach ( MarvinJob linkedJob in linkedJobs )
- jobs.insert( 0, linkedJob )
-
- // Debug draw jobs this marvin can take
- if ( DEBUG_MARVIN_JOBS )
- {
- foreach ( MarvinJob job in jobs )
- {
- if ( linkedJobs.contains( job ) )
- DebugDrawLine( marvin.GetOrigin(), job.node.GetOrigin(), 255, 255, 0, true, 10.0 )
- else
- DebugDrawLine( marvin.GetOrigin(), job.node.GetOrigin(), 200, 200, 200, true, 10.0 )
- }
- }
-
- return jobs
-}
-
-void function DebugMarvinJobs()
-{
- while ( true )
- {
- foreach ( MarvinJob marvinJob in file.marvinJobs )
- {
- string appendText = "AVAILABLE"
- float timeTillNextUse = marvinJob.nextUsableTime - Time()
- if ( IsValid( marvinJob.user ) )
- appendText = "RESERVED"
- else if ( timeTillNextUse > 0 )
- appendText = format( "%.1f", timeTillNextUse )
- DebugDrawText( marvinJob.node.GetOrigin(), marvinJob.jobType + " (" + appendText + ")", true, 0.1 )
- }
- wait 0.05
- }
-}
-
-MarvinJob function GetMarvinJobForNode( entity node )
-{
- MarvinJob marvinJob
- foreach ( MarvinJob marvinJob in file.marvinJobs )
- {
- if ( marvinJob.node == node )
- return marvinJob
- }
- return marvinJob
-}
-
-entity function CreateBarrel( entity node )
-{
- return CreatePropPhysics( node.GetModelName(), node.GetOrigin(), node.GetAngles() )
-}
-
-void function MarvinRunToAnimStart( entity marvin, string anim, entity jobNode )
-{
- if ( jobNode.HasKey( "teleport" ) && jobNode.kv.teleport == "1" )
- wait 0.1
- else
- RunToAnimStartPos( marvin, anim, jobNode )
-}
-
-void function MarvinFlyToAnimStart( entity marvin, string anim, entity jobNode )
-{
- if ( jobNode.HasKey( "teleport" ) && jobNode.kv.teleport == "1" )
- {
- wait 0.1
- return
- }
-
- AnimRefPoint animStartInfo = marvin.Anim_GetStartForRefPoint( anim, jobNode.GetOrigin(), jobNode.GetAngles() )
-
- marvin.AssaultPoint( animStartInfo.origin )
- marvin.AssaultSetAngles( animStartInfo.angles, true )
- marvin.AssaultSetArrivalTolerance( 16 )
- marvin.WaitSignal( "OnFinishedAssault" )
-} \ No newline at end of file