//============================================================================= // KFReplicatedShowPathActor //============================================================================= // Low-impact replicated actor that creates a trail path to any actor. //============================================================================= // Killing Floor 2 // Copyright (C) 2016 Tripwire Interactive LLC //============================================================================= class KFReplicatedShowPathActor extends Actor dependsOn(KFSeqAct_ShowPath); /** Team number to check against */ var byte PathTeamNum; /** Volume to check against, if any, for displaying the path to players */ var Volume CheckVolume; /** Volume check type for path displaying */ var byte VolumeCheckType; /** Target actor, set once and replicated at spawn */ var repnotify Actor Target; /** The Template to use for this emitter */ var ParticleSystem EmitterTemplate; replication { if( bNetInitial ) CheckVolume, VolumeCheckType, PathTeamNum, Target; } simulated event ReplicatedEvent( name VarName ) { if( VarName == nameOf(Target) ) { InitPath(); } else { super.ReplicatedEvent( VarName ); } } function SetPathTarget( Actor NewTarget, optional Volume NewVolume, optional eVolumeCheckType NewVolumeCheckType=VCT_None, optional byte NewPathTeamNum=0 ) { Target = NewTarget; CheckVolume = NewVolume; VolumeCheckType = NewVolumeCheckType; PathTeamNum = NewPathTeamNum; if( WorldInfo.NetMode != NM_DedicatedServer ) { InitPath(); } } simulated function InitPath() { if (Target != none) { ShowPath(); SetTimer( 2.f, true, nameOf(Timer_ShowPath) ); } else { ClearTimer(nameof(Timer_ShowPath)); } } simulated function Timer_ShowPath() { if( !bDeleteMe && Target != none ) { ShowPath(); } } simulated function ShowPath() { local PlayerController PC; local bool bInsideVolume; local EPathSearchType OldSearchType; local KFEmit_ScriptedPath Path; local Actor nodePathRoot; local bool bPathFound; foreach Target.WorldInfo.LocalPlayerControllers( class'PlayerController', PC ) { if( PC.Pawn == none || PC.GetTeamNum() != PathTeamNum || !PC.Pawn.IsAliveAndWell() ) { continue; } if( VolumeCheckType != VCT_None && CheckVolume != none ) { bInsideVolume = class'KFSeqAct_SetTraderVolumeIgnore'.static.IsActorInVolume( PC.Pawn, CheckVolume ); if( VolumeCheckType == VCT_InVolume ) { if( !bInsideVolume ) { continue; } } else if( VolumeCheckType == VCT_NotInVolume ) { if( bInsideVolume ) { continue; } } } OldSearchType = PC.Pawn.PathSearchType; PC.Pawn.PathSearchType = PST_Constraint; class'Path_ToTrader'.static.ToTrader( PC.Pawn ); class'Goal_AtActor'.static.AtActor( PC.Pawn, Target,, false ); nodePathRoot = PC.FindPathToward( Target ); if( nodePathRoot != none ) { bPathFound = true; } else { bPathFound = false; } if( bPathFound ) { Path = Target.Spawn(class'KFGame.KFEmit_ScriptedPath', PC,, PC.Pawn.Location); Path.SetTemplate(EmitterTemplate, true); if (Path != none) { // instead of using the routecache for the last waypoint, use the trader pod mesh Path.SetDestination(Target.Location + vect(0, 0, 50)); } } else { `log( "[KFReplicatedShowPathActor] ShowScriptedPath - No Path Found" ); } PC.Pawn.ClearConstraints(); PC.Pawn.PathSearchType = OldSearchType; } } simulated function SetEmitterTemplate(ParticleSystem NewTemplate) { EmitterTemplate = NewTemplate; } DefaultProperties { // Actor bGameRelevant=true bNoDelete=false bIgnoreEncroachers=true bPushedByEncroachers=false // Network RemoteRole=ROLE_SimulatedProxy NetUpdateFrequency=0.1f bAlwaysRelevant=true bOnlyDirtyReplication=true bReplicateMovement=false bSkipActorPropertyReplication=true bIgnoreNetRelevancyCollision=true // KFReplicatedShowPathActor VolumeCheckType=0 PathTeamNum=0 EmitterTemplate=ParticleSystem'FX_Gameplay_EMIT.FX_Trader_Trail' }