215 lines
6.3 KiB
Ucode
215 lines
6.3 KiB
Ucode
|
/**
|
||
|
*
|
||
|
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* Where crowd agent is going. Destinations can kill agents that reach them or route them to another destination
|
||
|
*
|
||
|
*/
|
||
|
class GameCrowdDestinationQueuePoint extends GameCrowdInteractionPoint
|
||
|
native;
|
||
|
|
||
|
/** Position behind this one in line */
|
||
|
var() GameCrowdDestinationQueuePoint NextQueuePosition;
|
||
|
|
||
|
/** Position before this one in line */
|
||
|
var GameCrowdInteractionPoint PreviousQueuePosition;
|
||
|
|
||
|
/** Agent currently occupying this queue position */
|
||
|
var GameCrowdAgent QueuedAgent;
|
||
|
|
||
|
/** Which destination this queue is part of the line for. Used only for queue validation during error checking. */
|
||
|
var transient GameCrowdDestination QueueDestination;
|
||
|
|
||
|
/** Prevent ClearQueue() reentry */
|
||
|
var bool bClearingQueue;
|
||
|
|
||
|
/** Average pause time before agent reacts to queue movement */
|
||
|
var() float AverageReactionTime;
|
||
|
|
||
|
/** True if queued agent is still at this position, but about to advance */
|
||
|
var bool bPendingAdvance;
|
||
|
|
||
|
/** Queue behavior used by this queue point */
|
||
|
var class<GameCrowdBehavior_WaitInQueue> QueueBehaviorClass;
|
||
|
|
||
|
/**
|
||
|
* Returns true if agent at TestPosition is considered to have reached this queue point
|
||
|
*/
|
||
|
native function bool QueueReachedBy(GameCrowdAgent Agent, vector TestPosition);
|
||
|
|
||
|
/**
|
||
|
* Returns true if this queue has space
|
||
|
*/
|
||
|
simulated function bool HasSpace()
|
||
|
{
|
||
|
// If I don't have a queued agent, and there's not one about to advance to me, then I have space
|
||
|
if ( (QueuedAgent == None) && ((NextQueuePosition == None) || !NextQueuePosition.bPendingAdvance || (NextQueuePosition.QueuedAgent == None)) )
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if ( NextQueuePosition == None )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return NextQueuePosition.HasSpace();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called after Agent reaches this queue position
|
||
|
*
|
||
|
* @PARAM Agent is the crowd agent that just reached this queue position
|
||
|
*/
|
||
|
simulated event ReachedDestination(GameCrowdAgent Agent)
|
||
|
{
|
||
|
local GameCrowdDestinationQueuePoint QueuePoint;
|
||
|
|
||
|
// if agent in front of me hasn't reached yet and is further than me from the front, switch positions with him
|
||
|
// FIXMESTEVE - doesn't address the case where the GameCrowdDestination itself appears empty - may not need to be handled
|
||
|
for ( QueuePoint = Agent.CurrentDestination.QueueHead; QueuePoint!=None; QueuePoint= QueuePoint.NextQueuePosition)
|
||
|
{
|
||
|
if ( QueuePoint.NextQueuePosition == self )
|
||
|
{
|
||
|
if ( QueuePoint.QueuedAgent == None )
|
||
|
{
|
||
|
`warn(agent$"in queue behind empty spot at "$self);
|
||
|
}
|
||
|
else if ( !QueuePoint.QueueReachedBy(QueuePoint.QueuedAgent, QueuePoint.QueuedAgent.Location) && (VSizeSq(QueuePoint.Location - Agent.Location) < VSizeSq(QueuePoint.Location - QueuePoint.QueuedAgent.Location)) )
|
||
|
{
|
||
|
// switch places for agents
|
||
|
QueuedAgent = QueuePoint.QueuedAgent;
|
||
|
QueuePoint.QueuedAgent = Agent;
|
||
|
GameCrowdBehavior_WaitInQueue(QueuedAgent.CurrentBehavior).QueuePosition = self;
|
||
|
GameCrowdBehavior_WaitInQueue(QueuePoint.QueuedAgent.CurrentBehavior).QueuePosition = QueuePoint;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// note - idle time will increase until next position opens up
|
||
|
GameCrowdBehavior_WaitInQueue(QueuedAgent.CurrentBehavior).bIdleBehavior = true;
|
||
|
QueuedAgent.PlayIdleAnimation();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Advance customer to next position in line, with a reaction time delay
|
||
|
*/
|
||
|
simulated function AdvanceCustomerTo(GameCrowdInteractionPoint FrontPosition)
|
||
|
{
|
||
|
PreviousQueuePosition = FrontPosition;
|
||
|
bPendingAdvance = true;
|
||
|
SetTimer(AverageReactionTime, false, 'ActuallyAdvance');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Actually advance the customer now
|
||
|
*/
|
||
|
private simulated function ActuallyAdvance()
|
||
|
{
|
||
|
local GameCrowdDestinationQueuePoint FrontQueuePosition;
|
||
|
local GameCrowdDestination QueueFront;
|
||
|
local GameCrowdAgent TempAgent;
|
||
|
|
||
|
bPendingAdvance = false;
|
||
|
if ( QueuedAgent != None )
|
||
|
{
|
||
|
TempAgent = QueuedAgent;
|
||
|
|
||
|
// FIXMESTEVE - creates queue behavior for every spot in line - should re-use
|
||
|
bClearingQueue = true;
|
||
|
QueuedAgent.StopBehavior();
|
||
|
bClearingQueue = false;
|
||
|
QueuedAgent = None;
|
||
|
FrontQueuePosition = GameCrowdDestinationQueuePoint(PreviousQueuePosition);
|
||
|
if ( FrontQueuePosition != None )
|
||
|
{
|
||
|
FrontQueuePosition.AddCustomer(TempAgent, None);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
QueueFront = GameCrowdDestination(PreviousQueuePosition);
|
||
|
if ( QueueFront == None )
|
||
|
{
|
||
|
`warn("Illegal front position for queue "$self);
|
||
|
return;
|
||
|
}
|
||
|
QueueFront.IncrementCustomerCount(TempAgent);
|
||
|
}
|
||
|
if ( QueuedAgent != None )
|
||
|
{
|
||
|
`warn(self$" GOT QUEUED AGENT BACK - Head "$PreviousQueuePosition$" Tail "$NextQueuePosition);
|
||
|
}
|
||
|
else if ( NextQueuePosition != None )
|
||
|
{
|
||
|
NextQueuePosition.AdvanceCustomerTo(self);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add customer to queue
|
||
|
*/
|
||
|
simulated function AddCustomer(GameCrowdAgent NewCustomer, GameCrowdInteractionPoint PreviousPosition)
|
||
|
{
|
||
|
if ( PreviousPosition != None )
|
||
|
{
|
||
|
PreviousQueuePosition = PreviousPosition;
|
||
|
}
|
||
|
if ( QueuedAgent == None )
|
||
|
{
|
||
|
QueuedAgent = NewCustomer;
|
||
|
NewCustomer.ActivateInstancedBehavior(new(NewCustomer) QueueBehaviorClass);
|
||
|
GameCrowdBehavior_WaitInQueue(NewCustomer.CurrentBehavior).QueuePosition = self;
|
||
|
GameCrowdBehavior_WaitInQueue(NewCustomer.CurrentBehavior).ActionTarget = PreviousQueuePosition;
|
||
|
}
|
||
|
else if ( NextQueuePosition != None )
|
||
|
{
|
||
|
NextQueuePosition.AddCustomer(NewCustomer, self);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
`warn(self$" Attempted to add customer "$NewCustomer$" beyond end of queue");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clear OldCustomer from this queue position
|
||
|
* Advance any customers in line
|
||
|
*/
|
||
|
simulated function ClearQueue(GameCrowdAgent OldCustomer)
|
||
|
{
|
||
|
if ( !bClearingQueue )
|
||
|
{
|
||
|
bClearingQueue = true;
|
||
|
if ( OldCustomer == QueuedAgent )
|
||
|
{
|
||
|
QueuedAgent.StopBehavior();
|
||
|
QueuedAgent = None;
|
||
|
if ( NextQueuePosition != None )
|
||
|
{
|
||
|
NextQueuePosition.AdvanceCustomerTo(self);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
`warn("Attempted to clear "$OldCustomer$" from queue position with customer "$QueuedAgent);
|
||
|
}
|
||
|
bClearingQueue = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
simulated function bool HasCustomer()
|
||
|
{
|
||
|
return (QueuedAgent != None);
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
Begin Object NAME=CollisionCylinder
|
||
|
CollisionRadius=+0100.000000
|
||
|
CollisionHeight=+0040.000000
|
||
|
End Object
|
||
|
|
||
|
AverageReactionTime=0.7
|
||
|
|
||
|
QueueBehaviorClass=class'GameCrowdBehavior_WaitInQueue')
|
||
|
}
|