197 lines
5.0 KiB
Ucode
197 lines
5.0 KiB
Ucode
//=============================================================================
|
|
// KFScriptedPawnSpawner
|
|
//=============================================================================
|
|
// Placeable actor that contains information about a scripted pawn
|
|
//=============================================================================
|
|
// Killing Floor 2
|
|
// Copyright (C) 2018 Tripwire Interactive LLC
|
|
//=============================================================================
|
|
class KFScriptedPawnSpawner extends Actor
|
|
placeable;
|
|
|
|
// Class of scripted pawn to spawn
|
|
var(PawnInfo) class<KFPawn_Scripted> PawnClass;
|
|
// Character archetype for the pawn
|
|
var(PawnInfo) KFCharacterInfo_ScriptedPawn PawnCharacterInfo;
|
|
|
|
var float PawnHealth, PawnHealthMax;
|
|
var transient KFPawn_Scripted Pawn, ReferencePawn;
|
|
var bool bUseReferencePawnHealth, bUseReferencePawnHealthMax;
|
|
|
|
// SplineActor where the pawn spawns. Pawn has no collision / can't be targeted until it reaches PathStart
|
|
var(PathInfo) SplineActor PathSpawn;
|
|
// SplineActor where the pawn is considered to have officially started its route
|
|
var(PathInfo) SplineActor PathStart;
|
|
// Possible SplineActors where the pawn's scripted movement is considered complete for gameplay purposes
|
|
var(PathInfo) array<SplineActor> PathGoals;
|
|
var transient SplineActor PathGoal;
|
|
// How many subsegments the pawn will move through along the spline between two SplineActors (i.e. the higher the granularity, the more closely the pawn follows the curve of the spline)
|
|
var(PathInfo) int SegmentGranularity<ClampMin=0>;
|
|
|
|
var transient bool bReachedStart, bReachedGoal;
|
|
var transient float RouteDist, RouteDistTraversed;
|
|
|
|
delegate Delegate_OnPawnStartedRoute(KFPawn_Scripted StartedPawn);
|
|
delegate Delegate_OnPawnReachedRouteMarker(int MarkerIdx, SplineActor Marker, int SubIdx);
|
|
delegate Delegate_OnPawnReachedGoal();
|
|
delegate Delegate_OnPawnEndedRoute(bool bSuccess);
|
|
|
|
event PostBeginPlay()
|
|
{
|
|
super.PostBeginPlay();
|
|
SetupProgress();
|
|
}
|
|
|
|
function StartPawn(bool bSpawnInactive, optional KFPawn_Scripted NewPawn)
|
|
{
|
|
if (PathSpawn == none)
|
|
{
|
|
`warn(self$"::SpawnPawn - PathSpawn is NONE");
|
|
return;
|
|
}
|
|
|
|
if (PathStart == none)
|
|
{
|
|
`warn(self$"::SpawnPawn - PathStart is NONE");
|
|
return;
|
|
}
|
|
|
|
if (PathGoals.Length == 0)
|
|
{
|
|
`warn(self$"::SpawnPawn - PathGoals is EMPTY");
|
|
return;
|
|
}
|
|
|
|
if (PawnClass == none)
|
|
{
|
|
`warn(self$"::SpawnPawn - PawnClass is none!");
|
|
return;
|
|
}
|
|
|
|
if (NewPawn != none)
|
|
{
|
|
Pawn = NewPawn;
|
|
}
|
|
else
|
|
{
|
|
Pawn = Spawn(PawnClass, self, , PathSpawn.Location, PathSpawn.Rotation, , true);
|
|
}
|
|
|
|
if (Pawn == none)
|
|
{
|
|
`warn(self$"::SpawnPawn - cannot spawn "$PawnClass$"!");
|
|
return;
|
|
}
|
|
|
|
SetupPawn();
|
|
|
|
Pawn.bStartInactive = bSpawnInactive;
|
|
|
|
// The pawn needs to find a route from its spawn point to its goal
|
|
Pawn.StartRoute(PathSpawn, PathGoal, SegmentGranularity);
|
|
}
|
|
|
|
function SetupProgress()
|
|
{
|
|
local array<SplineActor> Route;
|
|
local int i;
|
|
|
|
// @TODO: don't just pick a random goal?
|
|
PathGoal = PathGoals[Rand(PathGoals.Length)];
|
|
PathStart.FindSplinePathTo(PathGoal, Route);
|
|
for (i = 0; i < Route.Length - 1; ++i)
|
|
{
|
|
RouteDist += Route[i].FindSplineComponentTo(Route[i+1]).GetSplineLength();
|
|
}
|
|
}
|
|
|
|
simulated function float GetProgress()
|
|
{
|
|
return RouteDistTraversed / RouteDist;
|
|
}
|
|
|
|
function SetupPawn()
|
|
{
|
|
if (ReferencePawn != none)
|
|
{
|
|
if (bUseReferencePawnHealth)
|
|
{
|
|
PawnHealth = ReferencePawn.Health;
|
|
}
|
|
|
|
if (bUseReferencePawnHealthMax)
|
|
{
|
|
PawnHealthMax = ReferencePawn.HealthMax;
|
|
}
|
|
// can set other stuff here, like maybe reusing the controller
|
|
}
|
|
|
|
Pawn.Initialize(PawnCharacterInfo, PawnHealth, PawnHealthMax);
|
|
Pawn.UpdatePawnSpeed();
|
|
|
|
if (Pawn.Controller == none)
|
|
{
|
|
Pawn.SpawnDefaultController();
|
|
}
|
|
|
|
Pawn.Delegate_OnReachedRouteMarker = OnPawnReachedRouteMarker;
|
|
Pawn.Delegate_OnEndedRoute = OnPawnEndedRoute;
|
|
}
|
|
|
|
function OnPawnReachedRouteMarker(int MarkerIdx, SplineActor Marker, int SubIdx, float DistSinceLastMarker)
|
|
{
|
|
if (bReachedStart && !bReachedGoal)
|
|
{
|
|
RouteDistTraversed += DistSinceLastMarker;
|
|
|
|
if (Delegate_OnPawnReachedRouteMarker != none)
|
|
{
|
|
Delegate_OnPawnReachedRouteMarker(MarkerIdx, Marker, SubIdx);
|
|
}
|
|
}
|
|
|
|
if (Marker == PathStart)
|
|
{
|
|
bReachedStart = true;
|
|
Pawn.Start();
|
|
|
|
if (Delegate_OnPawnStartedRoute != none)
|
|
{
|
|
Delegate_OnPawnStartedRoute(Pawn);
|
|
}
|
|
}
|
|
else if (Marker == PathGoal)
|
|
{
|
|
bReachedGoal = true;
|
|
Pawn.ReachedGoal();
|
|
|
|
if (Delegate_OnPawnReachedGoal != none)
|
|
{
|
|
Delegate_OnPawnReachedGoal();
|
|
}
|
|
}
|
|
}
|
|
|
|
function OnPawnEndedRoute(bool bSuccess)
|
|
{
|
|
if (Delegate_OnPawnEndedRoute != none && !bReachedGoal)
|
|
{
|
|
Delegate_OnPawnEndedRoute(bSuccess);
|
|
}
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
PawnClass=class'KFGame.KFPawn_Scripted'
|
|
PawnHealth=100
|
|
|
|
Begin Object Class=SpriteComponent Name=Sprite
|
|
Sprite=Texture2D'EditorResources.Crowd.T_Crowd_Spline'
|
|
Scale=0.5
|
|
HiddenGame=True
|
|
AlwaysLoadOnClient=False
|
|
AlwaysLoadOnServer=False
|
|
SpriteCategoryName="Splines"
|
|
End Object
|
|
Components.Add(Sprite)
|
|
}
|