206 lines
4.9 KiB
Ucode
206 lines
4.9 KiB
Ucode
// a really creepy camera that is always looking in your direction.
|
|
// it can be destroyed if you shoot it
|
|
|
|
// Author: Alex Quick
|
|
|
|
class CreepyCamera extends Actor
|
|
placeable;
|
|
|
|
var () bool DebugCamera;
|
|
// the player this camera is focusing on.
|
|
var protected Pawn CameraTarget;
|
|
// the rotation of the camera at level startup
|
|
var protected Rotator InitialRotation;
|
|
// limits on the rotation of the camera
|
|
var () const float PitchLimit,YawLimit;
|
|
// effect to spawn when this camera is destroyed
|
|
var protected class<Emitter> DestructionEffect;
|
|
|
|
simulated function PostBeginPlay()
|
|
{
|
|
InitialRotation = Rotation;
|
|
DesiredRotation = InitialRotation;
|
|
}
|
|
|
|
simulated function Tick(float DeltaTime)
|
|
{
|
|
OrientCameraToLocalPlayer();
|
|
|
|
if(DebugCamera)
|
|
{
|
|
PrintDebugLogs();
|
|
}
|
|
}
|
|
|
|
simulated function PrintDebugLogs()
|
|
{
|
|
log("======= CAMERA DEBUG ================");
|
|
log(" -->"@Self@" TARGET : "@CameraTarget@"InitialRotation :"@InitialRotation@" DesiredRotation :"@DesiredRotation);
|
|
}
|
|
|
|
// turn the camera so its looking at the local player
|
|
simulated function OrientCameraToLocalPlayer()
|
|
{
|
|
local rotator NewRotation;
|
|
local byte LockYaw,LockPitch;
|
|
|
|
if(CameraTarget == none)
|
|
{
|
|
FindCameraTarget();
|
|
}
|
|
else
|
|
{
|
|
NewRotation = Rotator((CameraTarget.Location + (Vect(0,0,1)* CameraTarget.EyeHeight)) - Location) ;
|
|
|
|
// If the desired rotation goes beyond the camera's limit, stop turning it.
|
|
if(CameraTarget.Health <= 0 ||
|
|
CameraTarget.bDeleteMe)
|
|
{
|
|
StopTracking();
|
|
return;
|
|
}
|
|
|
|
if(IsOutSideViewFrustrum(CameraTarget,LockYaw,LockPitch))
|
|
{
|
|
StopTracking();
|
|
}
|
|
else
|
|
{
|
|
if(LockPitch == 0)
|
|
{
|
|
DesiredRotation.Pitch = NewRotation.Pitch;
|
|
}
|
|
|
|
if(LockYaw == 0)
|
|
{
|
|
DesiredRotation.Yaw = NewRotation.Yaw;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
simulated function StopTracking()
|
|
{
|
|
CameraTarget = none;
|
|
NetUpdateFrequency = 0.1; // camera isn't really do anything at the moment, so it doesn't need frequent replication updates.
|
|
}
|
|
|
|
simulated function bool IsOutsideViewFrustrum(Pawn TestTarget, optional out byte LockYaw, optional out byte LockPitch)
|
|
{
|
|
local Rotator RotExtent,IntendedRotation;
|
|
|
|
IntendedRotation = Rotator((TestTarget.Location + (Vect(0,0,1)* TestTarget.EyeHeight)) - Location) ;
|
|
RotExtent = IntendedRotation - InitialRotation;
|
|
|
|
RotExtent.Yaw = RotExtent.Yaw & 65535;
|
|
if( RotExtent.Yaw > YawLimit &&
|
|
RotExtent.Yaw < (65535+ (-YawLimit)) )
|
|
{
|
|
LockYaw = 1;
|
|
}
|
|
|
|
RotExtent.Pitch = RotExtent.Pitch & 65535;
|
|
if( RotExtent.Pitch > PitchLimit &&
|
|
RotExtent.Pitch < (65535+ (-PitchLimit)) )
|
|
{
|
|
LockPitch = 1;
|
|
}
|
|
|
|
return LockPitch == 1 && LockYaw == 1;
|
|
}
|
|
|
|
simulated function FindCameraTarget()
|
|
{
|
|
// do this separately on each client so the camera is looking at them.
|
|
if(Level.NetMode == NM_DedicatedServer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(Level.GetLocalPlayerController().Pawn != none &&
|
|
Level.GetLocalPlayerController().Pawn.Health > 0)
|
|
{
|
|
CameraTarget = Level.GetLocalPlayerController().Pawn;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
NetUpdateFrequency = default.NetUpdateFrequency;
|
|
}
|
|
}
|
|
|
|
|
|
simulated function TakeDamage(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional int HitIndex)
|
|
{
|
|
DestroyCamera(EventInstigator);
|
|
}
|
|
|
|
function DestroyCamera(Pawn Killer)
|
|
{
|
|
TriggerEvent(Event,self,Killer);
|
|
|
|
bHidden = true;
|
|
SetCollision(false,false);
|
|
|
|
bSkipActorPropertyReplication = false;
|
|
NetUpdateTime = Level.TimeSeconds - 1;
|
|
|
|
if(Level.NetMode != NM_DedicatedServer)
|
|
{
|
|
SpawnDestructionEffect();
|
|
}
|
|
}
|
|
|
|
simulated function SpawnDestructionEffect()
|
|
{
|
|
Spawn(DestructionEffect);
|
|
}
|
|
|
|
simulated event PostNetReceive()
|
|
{
|
|
if ( bHidden )
|
|
{
|
|
SpawnDestructionEffect();
|
|
bNetNotify = false; // finished
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
bDirectional = true
|
|
|
|
CollisionRadius = 15
|
|
Collisionheight = 15
|
|
|
|
bCollideActors = true
|
|
bBlockActors = true
|
|
bUseCylinderCollision=true
|
|
bBlockZeroExtentTraces=true
|
|
bCanBeDamaged=true
|
|
|
|
DestructionEffect = class 'Emitter_BreakerExplosion'
|
|
|
|
DrawType = DT_StaticMesh
|
|
StaticMesh = StaticMesh'FrightYard_SM.Camera.Trader_Security_Cam'
|
|
|
|
PitchLimit = 10000
|
|
YawLimit = 16000
|
|
|
|
RotationRate=(Pitch=10000,Yaw=10000,Roll=0)
|
|
bFixedRotationDir = false
|
|
bRotateToDesired = true
|
|
Physics = PHYS_Rotating
|
|
|
|
// network
|
|
bOnlyDirtyReplication=true
|
|
bNoDelete=true
|
|
bReplicateMovement=false
|
|
bAlwaysRelevant=true
|
|
bSkipActorPropertyReplication=true
|
|
bNetNotify=true
|
|
|
|
RemoteRole=Role_SimulatedProxy
|
|
NetUpdateFrequency=0.1
|
|
}
|
|
|
|
|
|
|
|
|