rott/kf_sources/KFStoryGame/Classes/ObjCondition_Area.uc
2026-07-14 20:27:09 +07:00

328 lines
8.8 KiB
Ucode

/*
--------------------------------------------------------------
Condition_Area
--------------------------------------------------------------
A Condition which is marked complete when a player either
(A) leaves a volume or (B) enters a volume
Can also be configured to check ZoneInfo regions.
Author : Alex Quick
--------------------------------------------------------------
*/
class ObjCondition_Area extends KF_ObjectiveCondition
editinlinenew;
var () private edfindable Volume AreaVolume;
var const Name AreaVolumeName,InitialAreaVolumeName;
var () string AreaZoneName;
var private Volume InitialVolume;
var () float Duration;
var () bool bRequiresWholeTeam;
var private ZoneInfo AssociatedZone; // Zones are NoDelete so having a reference in here should be O.K
enum EAreaConditionType
{
Method_LeaveArea,
Method_EnterArea,
};
var ()class<Actor> ProximityTriggerType;
var () name ProximityTag;
var ()EAreaConditionType CompletionMethod;
var () bool bKeepProgress;
var float LastInAreaTime;
var float TimeInArea;
var float TimeOutOfArea;
var float LastOutOfAreaTime;
var bool bTimingOut;
var int NumInVolume;
var private array<name> PawnInstigatorNames;
function PostBeginPlay(KF_StoryObjective MyOwner)
{
local ZoneInfo Zone;
Super.PostBeginPlay(MyOwner);
if(AreaVolume != none)
{
SetTargetActor(InitialAreaVolumeName,AreaVolume);
SetTargetActor(AreaVolumeName,AreaVolume);
AreaVolume = none;
}
else if(AreaZoneName != "")
{
foreach AllObjects(class 'ZoneInfo', Zone)
{
if(Zone.LocationName == AreaZoneName)
{
AssociatedZone = Zone;
break;
}
}
}
}
function array<Pawn> GetInstigatorList()
{
local array<Pawn> PawnInstigators;
local int i;
for(i = 0 ; i < PawnInstigatorNames.length ; i ++)
{
PawnInstigators[PawnInstigators.length] = Pawn(GetTargetActor(PawnInstigatorNames[i])) ;
}
return PawnInstigators;
}
function AdjustToDifficulty(float Difficulty)
{
Duration /= FMax(Difficulty-2,1);
}
function Reset()
{
Super.Reset();
bTimingOut = false;
TimeInArea = 0.f;
TimeOutOfArea = 0.f;
}
function ConditionActivated(pawn ActivatingPlayer)
{
Super.ConditionActivated(ActivatingPlayer);
Duration = FMax(Duration,0.1f);
if(GetTargetActor(InitialAreaVolumeName) != none)
{
SetTargetActor(AreaVolumeName,GetTargetActor(InitialAreaVolumeName));
}
}
function ConditionTick(Float DeltaTime)
{
local controller AController;
local Actor ProximityActor;
local Volume MyAreaVolume;
local int i;
NumInVolume = 0;
for(i = 0 ; i < PawnInstigatorNames.length ; i ++)
{
ReleaseTargetActor(PawnInstigatorNames[i]);
}
PawnInstigatorNames.length = 0;
MyAreaVolume = Volume(GetTargetActor(AreaVolumeName));
if(MyAreaVolume != none || AreaZoneName != "" )
{
if(MyAreaVolume != none)
{
if(ClassIsChildOf(ProximityTriggerType,class 'Controller'))
{
for ( AController=GetObjOwner().Level.ControllerList; AController!=None; AController=AController.NextController )
{
if(AController.Pawn != none &&
AController.Pawn.Health > 0 &&
MyAreaVolume.Encompasses(AController.Pawn))
{
if(ClassIsChildOf(AController.class,ProximityTriggerType))
{
PawnInstigatorNames[PawnInstigatorNames.length] = AController.Pawn.name;
SetTargetActor(AController.Pawn.name,AController.Pawn);
NumInVolume ++ ;
}
}
}
}
else
{
foreach MyAreaVolume.TouchingActors(class 'Actor', ProximityActor)
{
if(ProximityActor.IsA(ProximityTriggerType.name) &&
!ProximityActor.bPendingDelete && (ProximityTag == '' ||
ProximityActor.Tag == ProximityTag))
{
if(ProximityActor.Instigator != none)
{
PawnInstigatorNames[PawnInstigatorNames.length] = ProximityActor.Instigator.name;
SetTargetActor(ProximityActor.Instigator.name,ProximityActor.Instigator);
}
NumInVolume ++ ;
}
}
}
}
else if(AreaZoneName != "")
{
for ( AController=GetObjOwner().Level.ControllerList; AController!=None; AController=AController.NextController )
{
if(AController.Pawn != none &&
AController.Pawn.Health > 0 &&
(ClassIsChildOf(AController.Pawn.Class,ProximityTriggerType) ||
ClassIsChildOf(AController.Class,ProximityTriggerType)) &&
(ProximityTag == '' || AController.Pawn.Tag == ProximityTag))
{
if(AController.Pawn.Region.Zone.LocationName == AreaZoneName)
{
PawnInstigatorNames[PawnInstigatorNames.length] = AController.Pawn.name;
SetTargetActor(AController.Pawn.name,AController.Pawn);
NumInVolume ++ ;
}
}
}
}
if(NumInVolume == 0 ||
(bRequiresWholeTeam && NumInVolume < GetObjOwner().StoryGI.GetTotalActivePlayers()))
{
bTimingOut = true;
if(bKeepProgress)
{
TimeInArea = FMax( TimeInArea - DeltaTime, 0 );
}
else
{
TimeInArea = 0.f;
}
TimeOutOfArea = FMin( TimeOutOfArea + DeltaTime, Duration );
}
else
{
bTimingOut = false;
TimeInArea = FMin( TimeInArea + DeltaTime, Duration );
if(bKeepProgress)
{
TimeOutOfArea = FMax( TimeOutOfArea - DeltaTime, 0 );
}
else
{
TimeOutOfArea = 0.f;
}
}
}
Super.ConditionTick(DeltaTime);
}
/* returns the percentage of completion for this condition */
function float GetCompletionPct()
{
if(CompletionMethod == Method_LeaveArea)
{
return FClamp(TimeOutOfArea / Duration,0.f,1.f);
}
else
{
return FClamp(TimeInArea / Duration,0.f,1.f);
}
}
function string GetDataString()
{
local string DataString;
local int NumActivePlayers;
if(bRequiresWholeTeam )
{
NumActivePlayers = GetObjOwner().StoryGI.GetTotalActivePlayers() ;
if(NumActivePlayers > 1)
{
DataString@="["$NumInVolume$"/"$NumActivePlayers$"]" ;
}
}
return DataString ;
}
function string GetHUDHint()
{
local string HintString;
return Super.GetHUDHint();
if( (CompletionMethod == Method_LeaveArea && bTimingOut) ||
(CompletionMethod == Method_EnterArea && !bTimingOut) )
{
HintString = Super.GetHUDHint();
}
return HintString ;
}
function vector GetLocation(optional out Actor LocActor)
{
local Actor WorldLocActor;
local Vector WorldLocation;
local Volume MyAreaVolume;
if(ConditionIsActive())
{
MyAreaVolume = Volume(GetTargetActor(AreaVolumeName));
WorldLocation = Super.GetLocation(WorldLocActor);
if(WorldLocActor != none)
{
LocActor = WorldLocActor;
return WorldLocation;
}
if(MyAreaVolume != none)
{
LocActor = MyAreaVolume;
return LocActor.Location;
}
else
if(AreaZoneName != "" && AssociatedZone != none)
{
LocActor = AssociatedZone;
return LocActor.Location;
}
}
}
DefaultProperties
{
AreaVolumeName = "AreaVolume"
InitialAreaVolumeName = "InitialAreaVolume"
CompletionMethod = Method_EnterArea
ProximityTriggerType = class 'PlayerController'
HUD_World=(bIgnoreWorldLocHidden=true)
}