• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Code [Help] SetViewTraget

forrestmark9

Grizzled Veteran
Nov 29, 2011
1,110
42
I need help with SetViewTraget, so far no matter what I try nothing works I've tried replicated the function from the Client to Server like said but nothing works

Here is the code, PossesZed is on the server and is called by the client I'm unsure but I think here SpectatePlayer needs to be from the server to client
Code:
state PreySpec extends BaseSpectating
{
ignores SwitchWeapon, RestartLevel, ClientRestart, Suicide, ThrowWeapon, NotifyPhysicsVolumeChange, NotifyHeadVolumeChange;

    function SpectatePlayer(Pawn Target)
    {
        local bool bWasSpec;
        
        bWasSpec = !bBehindView && ViewTarget != Pawn && ViewTarget != self;
        
        if( Target != none  )
        {
            SetViewTarget(Target);
            ClientSetViewTarget(Target);
            if ( ViewTarget == self || bWasSpec )
                bBehindView = false;
            else
                bBehindView = true;
            ClientSetBehindView(bBehindView);
        }
    }

    function PossessZed()
    {
        local vector HitLocation, HitNormal, TraceEnd, TraceStart;
        local rotator R;
        local Actor A;
        local KFMonster M;

        if( NextPossessTimer>Level.TimeSeconds )
            return;
        NextPossessTimer = Level.TimeSeconds+0.4f;
        
        PlayerCalcView(A, TraceStart, R);
        TraceEnd = TraceStart + 1000 * Vector(R);
        A = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, true);
        if ( KFHumanPawn(A) != none)
        {
            SpectatePlayer(KFHumanPawn(A));
            return;
        }
        else if ( KFMonster(A) != none)
        {
            M = KFMonster(A);
            if( M!=None && M.Health>0 )
            {
                if( ( M.IsA('ZombieBoss') || M.IsA('ZombieFleshpound') || M.IsA('FemaleFP') || M.IsA('ZombieScrake') || M.IsA('ZombieJason') ) && !ForrestPRI(PlayerReplicationInfo).IsVIP )
                {
                    if( M.IsA('ZombieBoss') && bDisallowPatPossession )
                    {
                        ClientMessage("Can't possess: You suicided.");
                        return;
                    }
                    ClientMessage("Can't possess: You must be a VIP to possess this ZED.");
                    return;
                }
                VSGame(Level.Game).PlayerPossess(Self,M);
                return;
            }
        }
        ClientMessage("Can't possess: You must aim at the specimen to possess.");
    }
    
    exec function Fire( optional float F )
    {   
        if( NextPossessTimer<Level.TimeSeconds )
        {
            PossessZed();
            NextPossessTimer = Level.TimeSeconds+0.5f;
        }
    }
    
    exec function AltFire( optional float F )
    {
        if( ViewTarget != self )
            ServerViewSelf();
    }

    function Timer()
    {
        bFrozen = false;
    }

    function BeginState()
    {
        if ( Pawn != None )
        {
            SetLocation(Pawn.Location);
            UnPossess();
        }
        bCollideWorld = true;
        CameraDist = Default.CameraDist;
    }

    function EndState()
    {
        PlayerReplicationInfo.bIsSpectator = false;
        bCollideWorld = false;
    }
    
    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
        bBehindView = false;
        if( ViewTarget!=Self )
            SetViewTarget(Self);
        Acceleration = NewAccel;
        MoveSmooth(SpectateSpeed * Normal(Acceleration) * DeltaTime);
    }
}
 
There is no need of using "simulated" function inside PlayerController, because its role is ROLE_AutonomousProxy, i.e. it can execute non-simulated functions on client side.

Does this includes going to non-simulated states?

Here is the code, PossesZed is on the server and is called by the client I'm unsure but I think here SpectatePlayer needs to be from the server to client
Need more information about how it works. Which way you call it from client?
 
Last edited:
Upvote 0
Does this includes going to non-simulated states?


Need more information about how it works. Which way you call it from client?

The client goes into this state when he dies

Code:
state Spectating
{
    function BeginState()
    {
        Super.BeginState();
        if( VSGame(Level.Game)!=None && VSGame(Level.Game).ShouldGoHunt() && !PlayerReplicationInfo.bOnlySpectator )
            GoToState('PreySpec');
    }
}
 
Upvote 0
Hmm I see, so that means like it does for PossessZed I have to move the code to the gametype?

This is one of the options. Maybe it has sense to make some "proxy" actor between clients and game type to handle such things.

There is no need to use "simulated" keyword inside PlayerController at all.
Thanks, did'nt know about that.
 
Last edited:
Upvote 0
I tried doing the code from the gametype and still no dice

Code:
state PreySpec extends BaseSpectating
{
ignores SwitchWeapon, RestartLevel, ClientRestart, Suicide, ThrowWeapon, NotifyPhysicsVolumeChange, NotifyHeadVolumeChange;

    function PossessZed()
    {
        local vector HitLocation, HitNormal, TraceEnd, TraceStart;
        local rotator R;
        local Actor A;
        local KFMonster M;

        if( NextPossessTimer>Level.TimeSeconds )
            return;
        NextPossessTimer = Level.TimeSeconds+0.4f;
        
        PlayerCalcView(A, TraceStart, R);
        TraceEnd = TraceStart + 1000 * Vector(R);
        A = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, true);
        if ( KFHumanPawn(A) != none)
        {
            VSGame(Level.Game).PlayerSpectate(Self,M);
            return;
        }
        else if ( KFMonster(A) != none)
        {
            M = KFMonster(A);
            if( M!=None && M.Health>0 )
            {
                VSGame(Level.Game).PlayerPossess(Self,M);
                return;
            }
        }
        ClientMessage("Can't possess: You must aim at the specimen to possess.");
    }
    
    exec function Fire( optional float F )
    {   
        if( NextPossessTimer<Level.TimeSeconds )
        {
            PossessZed();
            NextPossessTimer = Level.TimeSeconds+0.5f;
        }
    }
    
    exec function AltFire( optional float F )
    {
        if( ViewTarget != self )
            ServerViewSelf();
    }

    function Timer()
    {
        bFrozen = false;
    }

    function BeginState()
    {
        if ( Pawn != None )
        {
            SetLocation(Pawn.Location);
            UnPossess();
        }
        bCollideWorld = true;
        CameraDist = Default.CameraDist;
    }

    function EndState()
    {
        PlayerReplicationInfo.bIsSpectator = false;
        bCollideWorld = false;
    }
    
    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
        bBehindView = false;
        if( ViewTarget!=Self )
            SetViewTarget(Self);
        Acceleration = NewAccel;
        MoveSmooth(SpectateSpeed * Normal(Acceleration) * DeltaTime);
    }
}

Code:
final function PlayerSpectate( FMXVersusPlayerController P, Pawn Target )
{
    local bool bWasSpec;
        
    bWasSpec = !P.bBehindView && P.ViewTarget != P.Pawn && P.ViewTarget != P;
        
    if( Target != none  )
    {
        P.SetViewTarget(Target);
        P.ClientSetViewTarget(Target);
        if ( P.ViewTarget == P || bWasSpec )
            P.bBehindView = false;
        else
            P.bBehindView = true;
        P.ClientSetBehindView(P.bBehindView);
    }
}
 
Last edited:
Upvote 0
Pretty sure it isn't working because trace is hitting player bullet whiz, try to disable hitpoint tracing while doing trace:
bBlockHitPointTraces = false;
A = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, true);
bBlockHitPointTraces = true;

@Poosh, it doesn't matter if code is executed serverside only because ClientAdjustMove does move the client state to correct state.
 
Last edited:
Upvote 0
@Marco
What is ClientAdjustMove?

Anyway, as far as I see in the code, PossessZed() is called client-side. KFBulletWhipAttachment exists on server side only, so it isn't a case.

You are trying to execute this on client side, where Level.Game=none:
Code:
        if ( KFHumanPawn(A) != none)
        {
            [COLOR="Orange"]VSGame(Level.Game).PlayerSpectate(Self,M);[/COLOR]
            return;
        }
        else if ( KFMonster(A) != none)
        {
            M = KFMonster(A);
            if( M!=None && M.Health>0 )
            {
               [COLOR="orange"] VSGame(Level.Game).PlayerPossess(Self,M);[/COLOR]
                return;
            }
        }

Try something like this:
Code:
replication {
    reliable if ( Role < ROLE_Authority )
        ServerSpectateActor;
}

// server-side
function ServerSpectateActor(Actor A)
{
    if ( KFHumanPawn(A) != none)
    {
        VSGame(Level.Game).PlayerSpectate(Self,M);
        return;
    }
    else if ( KFMonster(A) != none)
    {
        M = KFMonster(A);
        if( M!=None && M.Health>0 )
        {
            VSGame(Level.Game).PlayerPossess(Self,M);
            return;
        }
    } 
    ClientMessage("Can't spectate this kind of actor: " $ A);
}

state PreySpec extends BaseSpectating
{
ignores SwitchWeapon, RestartLevel, ClientRestart, Suicide, ThrowWeapon, NotifyPhysicsVolumeChange, NotifyHeadVolumeChange;

    //client-side
    function PossessZed()
    {
        local vector HitLocation, HitNormal, TraceEnd, TraceStart;
        local rotator R;
        local Actor A;
        local KFMonster M;

        if( NextPossessTimer>Level.TimeSeconds )
            return;
        NextPossessTimer = Level.TimeSeconds+0.4f;
        
        PlayerCalcView(A, TraceStart, R);
        TraceEnd = TraceStart + 1000 * Vector(R);
        A = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, true);
        if ( A != none )
            ServerSpectateActor(A);
        else 
            ClientMessage("Can't possess: You must aim at the specimen to possess.");
    }
    
    exec function Fire( optional float F )
    {   
        if( NextPossessTimer<Level.TimeSeconds )
        {
            PossessZed();
            NextPossessTimer = Level.TimeSeconds+0.5f;
        }
    }
    
    exec function AltFire( optional float F )
    {
        if( ViewTarget != self )
            ServerViewSelf();
    }

    function Timer()
    {
        bFrozen = false;
    }

    function BeginState()
    {
        if ( Pawn != None )
        {
            SetLocation(Pawn.Location);
            UnPossess();
        }
        bCollideWorld = true;
        CameraDist = Default.CameraDist;
    }

    function EndState()
    {
        PlayerReplicationInfo.bIsSpectator = false;
        bCollideWorld = false;
    }
    
    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
        bBehindView = false;
        if( ViewTarget!=Self )
            SetViewTarget(Self);
        Acceleration = NewAccel;
        MoveSmooth(SpectateSpeed * Normal(Acceleration) * DeltaTime);
    }
}
 
Last edited:
Upvote 0
Indeed, it was called ClientAdjustPosition in UE2 and not ClientAdjustMove.

to be honest, you should had taken same approach as I did with VS game:
Code:
	function ServerPossessZed()
	{
		local Pawn M;
		local vector HL,HN;

		if( NextPossessTimer>Level.TimeSeconds )
			return;
		NextPossessTimer = Level.TimeSeconds+0.4f;

		foreach TraceActors(Class'Pawn',M,HL,HN,Location+vector(Rotation)*1000.f,Location)
		{
			if( M!=None && M.Health>0 )
			{
				if( Monster(M)!=None )
					VSGame(Level.Game).PlayerPossess(Self,Monster(M));
				else if( KFPawn(M)!=None )
					SpectatePlayer(M);
				return;
			}
		}
		ClientMessage("Can't possess: You must aim at the specimen to possess.");
	}
	exec function Fire( optional float F )
	{
		if( NextPossessTimer<Level.TimeSeconds )
		{
			ServerPossessZed();
			NextPossessTimer = Level.TimeSeconds+0.5f;
		}
	}
 
Upvote 0