850 lines
24 KiB
Ucode
850 lines
24 KiB
Ucode
/*
|
|
--------------------------------------------------------------
|
|
KF_ObjectiveCondition
|
|
--------------------------------------------------------------
|
|
|
|
Object used to store gameplay conditions for KF_StoryObjectives
|
|
Configured by level designers.
|
|
|
|
Author : Alex Quick
|
|
|
|
--------------------------------------------------------------
|
|
*/
|
|
|
|
#exec OBJ LOAD FILE=KFStoryGame_Tex.utx
|
|
|
|
class KF_ObjectiveCondition extends Object
|
|
abstract
|
|
dependson(KFStoryGameInfo)
|
|
hidecategories(Object);
|
|
|
|
|
|
const HintCharLimit = 35;
|
|
|
|
|
|
/* Pawn responsible for Activating and / or completing this condition. */
|
|
var const name InstigatorName;
|
|
|
|
var bool bComplete,SavedbComplete;
|
|
|
|
var float LastActivatedTime;
|
|
|
|
var float LastRepTime;
|
|
|
|
/* Minimum time between client updates of condition data */
|
|
var (Network) float ConditionRepInterval;
|
|
|
|
/* HUD properties ======================================================================
|
|
=======================================================================================*/
|
|
|
|
/* HUD Properties that pertain to the world (Wisp trail, projected icons, etc.) */
|
|
var (HUD) KFStoryGameInfo.SConditionHintInfoWorld HUD_World;
|
|
|
|
/* HUD Properties that pertain to the player's On-screen display */
|
|
var (HUD) KFStoryGameInfo.SConditionHintInfoHUD HUD_Screen;
|
|
|
|
var float OldCompletionPct,NewCompletionPct;
|
|
|
|
var bool OldComplete,NewComplete;
|
|
|
|
var string OldDataString,NewDataString;
|
|
|
|
var vector OldWorldLoc,NewLocation;
|
|
|
|
|
|
/* =====================================================================================
|
|
=======================================================================================*/
|
|
|
|
var bool bActive,SavedbActive;
|
|
|
|
var bool bWasTriggered,SavedbWasTriggered;
|
|
|
|
var byte ConditionType; // 0 = failure, 1 = success , 2 = optional
|
|
|
|
|
|
|
|
/* An array that stores Condition dependencies.
|
|
ie. We only want this condition to be considered for completion if the
|
|
conditions in this list are already completed and share the same instigator as us.
|
|
|
|
an example of this would be a Key locked door */
|
|
|
|
var() array <KF_ObjectiveCondition> DependentConditions;
|
|
|
|
/* If true this objective cannot be 'uncompleted' once it is complete, without being reset */
|
|
var() bool bCompleteOnce;
|
|
|
|
var bool bLockCompletion;
|
|
|
|
var bool bForceReliableUpdate;
|
|
|
|
/* Difficulty Modifiers ============================================================*/
|
|
|
|
enum EKFGameDifficulty
|
|
{
|
|
All,
|
|
Beginner,
|
|
Normal,
|
|
Hard,
|
|
Suicidal,
|
|
HellOnEarth,
|
|
};
|
|
|
|
/* Only use this condition above MinDifficulty and below MaxDifficulty */
|
|
var(Difficulty) EKFGameDifficulty Difficulty_Min,Difficulty_Max;
|
|
|
|
|
|
var(Difficulty) int PlayerCount_Min,PlayerCount_Max;
|
|
|
|
/* Scales the Condition's requirements based on the server's difficulty setting */
|
|
var(Difficulty) KFStoryGameInfo.SConditionDifficultyScale Scale_GameDifficulty;
|
|
|
|
/* Scales the Condition's requirements based on the number of players on the server */
|
|
var(Difficulty) float Scale_PlayerCount;
|
|
|
|
var private transient KF_StoryObjective ObjOwner;
|
|
|
|
/* =====================================================================================
|
|
=======================================================================================*/
|
|
|
|
var(Events) array<KFStoryGameInfo.SObjectiveProgressEvent> ProgressEvents;
|
|
|
|
/* =====================================================================================
|
|
=======================================================================================*/
|
|
|
|
var private KF_Objective_EventListener Eventlistener;
|
|
|
|
var(Events) name Tag;
|
|
|
|
var() KFStoryGameInfo.EConditionInitialState InitialState;
|
|
|
|
var() KFStoryGameInfo.EConditionActivationMethod ActivationMethod;
|
|
|
|
var() KFStoryGameInfo.EProgressImportance ProgressImportance;
|
|
|
|
var const name InitialWorldLocActorName, WorldLocActorName;
|
|
|
|
|
|
/*========== AUDIO =====================================================================*/
|
|
|
|
var(Audio) sound Sound_Completion;
|
|
|
|
|
|
function StoppedUsing(pawn User){}
|
|
function StartedUsing(pawn User){}
|
|
|
|
function PostBeginPlay(KF_StoryObjective MyOwner)
|
|
{
|
|
SpawnEventListener(MyOwner);
|
|
|
|
// cache and clear.
|
|
if(HUD_World.World_Location != none)
|
|
{
|
|
SetTargetActor(InitialWorldLocActorName,HUD_World.World_Location);
|
|
SetTargetActor(WorldLocActorName,HUD_World.World_Location);
|
|
HUD_World.World_Location = none;
|
|
}
|
|
}
|
|
|
|
function SaveState()
|
|
{
|
|
SavedbComplete = bComplete;
|
|
SavedbActive = bActive;
|
|
SavedbWasTriggered = bWasTriggered;
|
|
}
|
|
|
|
function Actor GetTargetActor(name TargetName)
|
|
{
|
|
local Actor TargetActor;
|
|
|
|
EventListener.FindAssociatedActor(TargetName,TargetActor);
|
|
return TargetActor;
|
|
}
|
|
|
|
|
|
function SetTargetActor(name NewTargetName, Actor NewValue)
|
|
{
|
|
Eventlistener.AddAssociatedActor(NewTargetName,NewValue);
|
|
}
|
|
|
|
function ReleaseTargetActor(name ReleaseTargetName)
|
|
{
|
|
EventListener.RemoveAssociatedActor(ReleaseTargetname);
|
|
}
|
|
|
|
function Reset()
|
|
{
|
|
local int i;
|
|
|
|
if(GetObjOwner().ActiveCheckPoint == none)
|
|
{
|
|
bWasTriggered = false;
|
|
bActive = false;
|
|
bComplete = false;
|
|
|
|
}
|
|
else
|
|
{
|
|
bWasTriggered = SavedbWasTriggered;
|
|
bActive = SavedbActive;
|
|
bComplete = SavedbComplete;
|
|
}
|
|
|
|
for(i = 0 ; i < ProgressEvents.Length ; i ++)
|
|
{
|
|
ProgressEvents[i].bWasTriggered = false;
|
|
}
|
|
|
|
OldDataString = "";
|
|
OldCompletionPct = 0.f;
|
|
OldWorldLoc = vect(0,0,0);
|
|
NewLocation = vect(0,0,0);
|
|
bLockCompletion = false;
|
|
}
|
|
|
|
function Trigger(actor Other, pawn EventInstigator)
|
|
{
|
|
if(ConditionIsValid())
|
|
{
|
|
SetTargetActor(InstigatorName,EventInstigator);
|
|
|
|
switch(ActivationMethod)
|
|
{
|
|
case TriggerToggled :
|
|
if(!bActive)
|
|
{
|
|
// log("**********************************************");
|
|
// log("Activating Condition By Trigger - :"@name);
|
|
GetObjOwner().ActivateCondition(self);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// log("**********************************************");
|
|
// log("Deactivating Condition By Trigger - :"@name);
|
|
GetObjOwner().DeActivateCondition(self);
|
|
return;
|
|
}
|
|
break;
|
|
case TriggerActivates :
|
|
if(!bActive)
|
|
{
|
|
GetObjOwner().ActivateCondition(self);
|
|
return;
|
|
}
|
|
break;
|
|
case TriggerDeActivates :
|
|
if(bActive)
|
|
{
|
|
GetObjOwner().DeActivateCondition(self);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bActive)
|
|
{
|
|
bWasTriggered = true;
|
|
}
|
|
|
|
}
|
|
|
|
function bool ConditionIsRelevant()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
function bool ConditionIsActive()
|
|
{
|
|
// log(self@"Owner : "@GetObjOwner().ObjectiveName@" Complete ? : "@bComplete@" Active ? : "@bActive,'Story_Debug');
|
|
return GetObjOwner() != none && bActive && (!bCompleteOnce || !bComplete);
|
|
}
|
|
|
|
/* Returns true if this condition should initialize automatically when its owning objective becomes active
|
|
In most cases this will be true ... except for complex conditions which the LD intentionally wants to activate
|
|
manually (after certain events in the mission , etc.)
|
|
*/
|
|
|
|
function bool ShouldInitOnActivation()
|
|
{
|
|
local bool Result;
|
|
|
|
if(InitialState == Active ||
|
|
(ActivationMethod == RandomlyActivate &&
|
|
FRand() > 0.5)) // condition is valid for activation
|
|
{
|
|
Result = true;
|
|
}
|
|
|
|
return Result && ConditionIsValid();
|
|
}
|
|
|
|
/* Only returns true if this condition is valid for activation - based on various factors like Game Difficulty, Player Count, etc.
|
|
*/
|
|
|
|
function bool ConditionIsValid()
|
|
{
|
|
local int NumPlayers;
|
|
local float CurrentDifficulty,MaxDifficulty,MinDifficulty;
|
|
local bool Result;
|
|
|
|
Result = true;
|
|
|
|
/* =============== Check Difficulty & Player Count validitiy ======*/
|
|
|
|
/* Make sure the values are in range first .. */
|
|
PlayerCount_Min = Min(PlayerCount_Min,PlayerCount_Max);
|
|
PlayerCount_Max = Max(PlayerCount_Max,PlayerCount_Min);
|
|
|
|
|
|
if(GetObjOwner() != none)
|
|
{
|
|
NumPlayers = KFStoryGameInfo(GetObjOwner().Level.Game).GetTotalActivePlayers();
|
|
CurrentDifficulty = GetObjOwner().Level.Game.GameDifficulty;
|
|
}
|
|
|
|
if((PlayerCount_Max > 0 && NumPlayers > PlayerCount_Max) ||
|
|
(PlayerCount_Min > 0 && NumPlayers < PlayerCount_Min))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(Difficulty_Max > 0)
|
|
{
|
|
switch(Difficulty_Max)
|
|
{
|
|
case Beginner : MaxDifficulty = 1.f ; break;
|
|
case Normal : MaxDifficulty = 2.f ; break;
|
|
case Hard : MaxDifficulty = 4.f ; break;
|
|
case Suicidal : MaxDifficulty = 5.f ; break;
|
|
case HellOnEarth : MaxDifficulty = 7.f ; break;
|
|
}
|
|
|
|
Result = CurrentDifficulty <= MaxDifficulty ;
|
|
}
|
|
if(Difficulty_Min > 0)
|
|
{
|
|
switch(Difficulty_Min)
|
|
{
|
|
case Beginner : MinDifficulty = 1.f ; break;
|
|
case Normal : MinDifficulty = 2.f ; break;
|
|
case Hard : MinDifficulty = 4.f ; break;
|
|
case Suicidal : MinDifficulty = 5.f ; break;
|
|
case HellOnEarth : MinDifficulty = 7.f ; break;
|
|
}
|
|
|
|
return Result && CurrentDifficulty >= MinDifficulty ;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/* Returns a value that scales this condition's requirements based on the Game Difficulty setting of the server */
|
|
function float GetGameDifficultyModifier()
|
|
{
|
|
local float CurrentDifficulty,DiffModifier;
|
|
|
|
CurrentDifficulty = GetObjOwner().Level.Game.GameDifficulty;
|
|
DiffModifier = 1.f;
|
|
|
|
switch(CurrentDifficulty)
|
|
{
|
|
case 1 : DiffModifier = Scale_GameDifficulty.Scale_Beginner; break; // Beginner.
|
|
case 3 : DiffModifier = Scale_GameDifficulty.Scale_Hard; break; // Hard.
|
|
case 5 : DiffModifier = Scale_GameDifficulty.Scale_Suicidal; break; // Suicidal.
|
|
case 7 : DiffModifier = Scale_GameDifficulty.Scale_HellOnEarth; break; // Hell On Earth.
|
|
}
|
|
|
|
return DiffModifier;
|
|
}
|
|
|
|
/* Returns a value that scales this condition's requirements based on the number of players on the server */
|
|
function float GetPlayerCountModifier()
|
|
{
|
|
local int NumPlayers;
|
|
|
|
NumPlayers = KFStoryGameInfo(GetObjOwner().Level.Game).GetTotalActivePlayers();
|
|
|
|
if(NumPlayers <= 1)
|
|
{
|
|
return 1.f;
|
|
}
|
|
|
|
return FMax(NumPlayers * Scale_PlayerCount, 1.f);
|
|
}
|
|
|
|
function float GetTotalDifficultyModifier()
|
|
{
|
|
return GetGameDifficultyModifier() * GetPlayerCountModifier();
|
|
}
|
|
|
|
function ConditionActivated(pawn ActivatingPlayer)
|
|
{
|
|
SetTargetActor(InstigatorName,ActivatingPlayer);
|
|
|
|
LastActivatedTime = GetObjOwner().Level.TimeSeconds;
|
|
bActive = true;
|
|
|
|
if(GetTargetActor(InitialWorldLocActorName) != none)
|
|
{
|
|
SetTargetActor(WorldLocActorName,GetTargetActor(InitialWorldLocActorName));
|
|
}
|
|
|
|
ReliableConditionUpdate();
|
|
}
|
|
|
|
function ConditionDeActivated()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
function bool IsOptionalCondition()
|
|
{
|
|
return ConditionType == 2;
|
|
}
|
|
|
|
|
|
function SpawnEventListener(KF_StoryObjective MyOwner)
|
|
{
|
|
if(Eventlistener == none )
|
|
{
|
|
EventListener = MyOwner.Spawn(class 'KF_Objective_EventListener');
|
|
EventListener.SetConditionOwner(self);
|
|
}
|
|
}
|
|
|
|
/* Allow Completion of this Condition
|
|
always true unless there is an outstanding dependency */
|
|
function bool AllowCompletion()
|
|
{
|
|
local int i;
|
|
local bool Result;
|
|
|
|
Result = true;
|
|
|
|
for(i = 0 ; i < DependentConditions.length ; i ++)
|
|
{
|
|
if(!DependentConditions[i].bComplete ||
|
|
!DependentConditions[i].FindInstigator(GetInstigatorList()))
|
|
{
|
|
Result = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
/* Some conditions may have multiple instigators */
|
|
function bool FindInstigator(array<Pawn> TestInstigators)
|
|
{
|
|
local int i,idx;
|
|
local array<Pawn> MyInstigatorList;
|
|
|
|
MyInstigatorList = GetInstigatorList();
|
|
|
|
for(i = 0 ; i < TestInstigators.length ; i ++)
|
|
{
|
|
for(idx = 0 ; idx < MyInstigatorList.length ; idx ++)
|
|
{
|
|
if(TestInstigators[i] == MyInstigatorList[idx])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function array<Pawn> GetInstigatorList()
|
|
{
|
|
local array<Pawn> Instigators;
|
|
|
|
Instigators[Instigators.length] = Pawn(GetTargetActor(InstigatorName));
|
|
return Instigators;
|
|
}
|
|
|
|
function ConditionTick(float DeltaTime)
|
|
{
|
|
local float PctComplete;
|
|
|
|
PctComplete = GetCompletionPct();
|
|
TriggerProgressEvents(PctComplete);
|
|
|
|
if(!bComplete)
|
|
{
|
|
if(PctComplete >= 1.f &&
|
|
AllowCompletion())
|
|
{
|
|
ConditionCompleted();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!bLockCompletion &&
|
|
!bCompleteOnce &&
|
|
PctComplete < 1.f)
|
|
{
|
|
bComplete = false;
|
|
}
|
|
}
|
|
|
|
/* Timed HUD Update - replicated , so do it only when the values actually change.*/
|
|
ConditionTickHUDUpdate();
|
|
}
|
|
|
|
/* Progress Event updates - Fired off at different stages in the condition's completion */
|
|
function TriggerProgressEvents(float PctComplete)
|
|
{
|
|
local int EventIdx;
|
|
|
|
for(EventIdx = 0 ; EventIdx < ProgressEvents.length ; EventIdx ++)
|
|
{
|
|
if(PctComplete >= ProgressEvents[EventIdx].ProgressPct &&
|
|
(!ProgressEvents[EventIdx].bWasTriggered ||
|
|
(ProgressEvents[EventIdx].bReTriggerable &&
|
|
PctComplete != ProgressEvents[EventIdx].LastTriggeredPct ) ) )
|
|
{
|
|
ProgressEvents[EventIdx].bWasTriggered = true;
|
|
GetObjOwner().TriggerEvent( ProgressEvents[EventIdx].EventName,GetObjOwner(),Pawn(GetTargetActor(InstigatorName)));
|
|
}
|
|
|
|
ProgressEvents[EventIdx].LastTriggeredPct = PctComplete;
|
|
}
|
|
}
|
|
|
|
function bool AllowConditionRepUpdate()
|
|
{
|
|
if( GetObjOwner().Level.TimeSeconds - LastRepTime < ConditionRepInterval ||
|
|
(HUD_World.bHide && HUD_Screen.Screen_ProgressStyle == 0 ))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Reliable HUD Update - Sends condition information to clients. Only used when a player
|
|
absolutely MUST get accurate data from this condition.
|
|
*/
|
|
function ReliableConditionUpdate(optional KFPlayerController_Story TargetPlayer)
|
|
{
|
|
local KFPlayerController_Story StoryPC;
|
|
local Controller C;
|
|
local float CompletionPct;
|
|
local string HUDHint;
|
|
local Actor NewLocActor;
|
|
|
|
GetLocation(NewLocActor);
|
|
CompletionPct = GetCompletionPct();
|
|
|
|
if(HUD_Screen.Screen_CountStyle != Hide_Counter)
|
|
{
|
|
HUDHint = GetDataString();
|
|
}
|
|
|
|
/* We want to update a specific Client's HUD */
|
|
if(TargetPlayer != none)
|
|
{
|
|
TargetPlayer.ReliableConditionUpdate(self,
|
|
GetObjOwner(),
|
|
CompletionPct,
|
|
NewLocActor,
|
|
HUDHint,
|
|
bComplete);
|
|
}
|
|
else // update everyone at once
|
|
{
|
|
For( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
|
{
|
|
StoryPC = KFPlayerController_Story(C);
|
|
if(StoryPC != none)
|
|
{
|
|
StoryPC.ReliableConditionUpdate(self,
|
|
GetObjOwner(),
|
|
CompletionPct,
|
|
NewLocActor,
|
|
HUDHint,
|
|
bComplete);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Replicates relevant info for this condition to clients
|
|
VERY expensive - for this reason it is throttled and only
|
|
set to replicate dirty values
|
|
|
|
@Todo - is there a more efficient way to do this ?
|
|
|
|
*/
|
|
|
|
function ConditionTickHUDUpdate()
|
|
{
|
|
local KFPlayerController_Story StoryPC;
|
|
local Controller C;
|
|
local bool bUpdateHUD;
|
|
local Actor NewLocActor;
|
|
|
|
if((GetObjOwner().AllowConditionRepUpdate() && AllowConditionRepUpdate()) )
|
|
{
|
|
GetLocation(NewLocActor);
|
|
|
|
OldComplete = NewComplete;
|
|
NewComplete = bComplete || !bActive;
|
|
|
|
OldDataString = NewDataString;
|
|
|
|
if(HUD_Screen.Screen_CountStyle != Hide_Counter)
|
|
{
|
|
NewDataString = GetDataString();
|
|
}
|
|
|
|
OldCompletionPct = NewCompletionPct;
|
|
NewCompletionPct = GetCompletionPct();
|
|
|
|
bUpdateHUD = NewCompletionPct != OldCompletionPct ||
|
|
NewComplete != OldComplete ||
|
|
NewDataString != OldDataString;
|
|
|
|
if(bUpdateHUD)
|
|
{
|
|
LastRepTime = GetObjOwner().Level.TimeSeconds;
|
|
GetObjOwner().CurrentRepUpdates ++ ;
|
|
|
|
For( C=GetObjOwner().Level.ControllerList; C!=None; C=C.NextController )
|
|
{
|
|
StoryPC = KFPlayerController_Story(C);
|
|
if(StoryPC != none)
|
|
{
|
|
if( bForceReliableUpdate )
|
|
{
|
|
StoryPC.ReliableConditionUpdate(self,
|
|
GetObjOwner(),
|
|
NewCompletionPct,
|
|
NewLocActor,
|
|
NewDataString,
|
|
bComplete);
|
|
}
|
|
else
|
|
{
|
|
StoryPC.UnreliableConditionUpdate(self,
|
|
GetObjOwner(),
|
|
NewCompletionPct,
|
|
NewLocActor,
|
|
NewDataString,
|
|
NewComplete);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Set the 'bComplete' bool to notify the parent Objective that this Condition is complete */
|
|
function ConditionCompleted()
|
|
{
|
|
local actor SourceActor;
|
|
local Controller C;
|
|
|
|
/* NOTE - any completion event stuff should be done *Before* bComplete is marked true*/
|
|
|
|
if(Sound_Completion != none)
|
|
{
|
|
GetLocation(SourceActor);
|
|
if(SourceActor != none &&
|
|
SourceActor != GetObjOwner())
|
|
{
|
|
SourceActor.PlaySound(Sound_Completion,,SourceActor.SoundVolume,,SourceActor.SoundRadius,SourceActor.SoundPitch,true);
|
|
}
|
|
else
|
|
{
|
|
for (C = GetObjOwner().Level.ControllerList; C != None; C = C.NextController)
|
|
{
|
|
if(PlayerController(C) != none)
|
|
{
|
|
PlayerController(C).ClientPlaySound(Sound_Completion,true,2.f,SLOT_Talk);
|
|
}
|
|
}
|
|
// log("Warning - Attempted to play Completion sound for"@name@" with no Source Actor!",'Story_Debug');
|
|
}
|
|
}
|
|
|
|
|
|
bComplete = true;
|
|
log("==============================================================================================", 'Story_Debug');
|
|
log("============= "@self@" a condition of "@GetObjOwner().ObjectiveName@" was just marked complete. ", 'Story_Debug');
|
|
|
|
ReliableConditionUpdate();
|
|
|
|
}
|
|
|
|
/* Accessor functions ========================== */
|
|
|
|
function SetObjOwner(KF_StoryObjective NewOwner)
|
|
{
|
|
ObjOwner = NewOwner;
|
|
}
|
|
|
|
function KF_StoryObjective GetObjOwner()
|
|
{
|
|
return ObjOwner;
|
|
}
|
|
|
|
/* Returns a reference to the pawn which instigated this condition last */
|
|
function Pawn GetInstigator()
|
|
{
|
|
return Pawn(GetTargetActor(InstigatorName));
|
|
}
|
|
|
|
function int GetOwnerArrayIndex()
|
|
{
|
|
return GetObjOwner().FindIndexForCondition(self);
|
|
}
|
|
|
|
/* returns the percentage of completion for this condition */
|
|
function float GetCompletionPct()
|
|
{
|
|
return float(bComplete);
|
|
}
|
|
|
|
function string GetDataString()
|
|
{
|
|
return "" ;
|
|
}
|
|
|
|
/* Hint to display over the world icon */
|
|
function string GetWorldHint()
|
|
{
|
|
return HUD_World.World_Hint ;
|
|
}
|
|
|
|
function string GetHUDHint()
|
|
{
|
|
return ClampHUDHint(HUD_Screen.Screen_Hint);
|
|
}
|
|
|
|
function string ClampHUDHint(string Hint)
|
|
{
|
|
if( Len(Hint) > HintCharLimit )
|
|
{
|
|
Hint = left(Hint,HintCharLimit);
|
|
Hint $= "..";
|
|
}
|
|
|
|
return Hint;
|
|
}
|
|
|
|
function vector GetLocation(optional out Actor LocActor)
|
|
{
|
|
if(ConditionIsActive())
|
|
{
|
|
if(GetWorldLocActor(LocActor))
|
|
{
|
|
return LocActor.Location ;
|
|
}
|
|
|
|
LocActor = GetObjOwner();
|
|
return GetObjOwner().Location;
|
|
}
|
|
}
|
|
|
|
function bool GetWorldLocActor(out Actor LocActor)
|
|
{
|
|
local Actor HUDWorldActor;
|
|
|
|
HUDWorldActor = GetTargetActor(WorldLocActorName);
|
|
|
|
if(ConditionIsActive() &&
|
|
HUDWorldActor != none &&
|
|
!HUDWorldActor.bPendingDelete &&
|
|
!HUDWorldActor.bDeleteMe)
|
|
{
|
|
LocActor = HUDWorldActor;
|
|
return true; ;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function vector GetWhispLocation(optional out Actor LocActor)
|
|
{
|
|
return GetNearestPathNodeTo(GetLocation(LocActor)).Location;
|
|
}
|
|
|
|
function bool ShouldShowWhispTrailFor(PlayerController C)
|
|
{
|
|
return HUD_World.bShowWhispTrail;
|
|
}
|
|
|
|
function NavigationPoint GetNearestPathNodeTo( vector DesiredLocation)
|
|
{
|
|
local navigationpoint N,Closest;
|
|
local float ClosestDistSq,DistSq;
|
|
|
|
for ( N=GetObjOwner().Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
|
|
{
|
|
DistSq = VSizeSquared(N.Location - DesiredLocation) ;
|
|
if(Closest == none || DistSq < ClosestDistSq)
|
|
{
|
|
Closest = N ;
|
|
ClosestDistSq = DistSq;
|
|
}
|
|
}
|
|
|
|
return Closest;
|
|
}
|
|
|
|
/* TimeFormatting string function Copied from Scoreboard.uc */
|
|
|
|
function String FormatTime( int Seconds )
|
|
{
|
|
local int Minutes, Hours;
|
|
local String Time;
|
|
|
|
if( Seconds > 3600 )
|
|
{
|
|
Hours = Seconds / 3600;
|
|
Seconds -= Hours * 3600;
|
|
|
|
Time = Hours$":";
|
|
}
|
|
Minutes = Seconds / 60;
|
|
Seconds -= Minutes * 60;
|
|
|
|
if( Minutes >= 10 )
|
|
Time = Time $ Minutes $ ":";
|
|
else
|
|
Time = Time $ "0" $ Minutes $ ":";
|
|
|
|
if( Seconds >= 10 )
|
|
Time = Time $ Seconds;
|
|
else
|
|
Time = Time $ "0" $ Seconds;
|
|
|
|
return Time;
|
|
}
|
|
|
|
defaultproperties
|
|
{
|
|
WorldLocActorName = "HUDWorldActor"
|
|
InitialWorldLocActorName = "InitialHUDWorldActor"
|
|
InstigatorName = "Instigator"
|
|
|
|
ConditionRepInterval = 0.5
|
|
InitialState = Active
|
|
|
|
Scale_GameDifficulty=(Scale_Beginner=1,Scale_Hard=1,Scale_Suicidal=1,Scale_HellOnEarth=1)
|
|
Scale_PlayerCount=1.f
|
|
|
|
HUD_World=(World_Clr=(R=255,G=50,B=50,A=255),Whisp_Clr=(R=255,G=50,B=50,A=255),World_Texture=none/*TexOscillator'KFStoryGame_Tex.HUD.ObjArrow_osc'*/,bHide=false,World_Texture_Scale=1.f)
|
|
HUD_Screen=(Screen_Clr=(R=255,G=50,B=50,A=255),Screen_ProgressStyle=HDS_Combination,bShowStrikethrough=true,FontScale=Font_Medium,Screen_ProgressBarBG=Texture'KFStoryGame_Tex.HUD.HUd_Rectangel_W_Stroke_Neutral',Screen_ProgressBarFill=Texture 'KFStoryGame_Tex.HUD.Hud_Rectangle_W_Stroke_Fill')
|
|
}
|
|
|
|
|