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

234 lines
6.2 KiB
Ucode

class ObjCondition_Use_SE extends ObjCondition_Use
editinlinenew;
/*
--------------------------------------------------------------
ObjCondition_Use_SE
--------------------------------------------------------------
Enhanced version of ObjCondition_Use.
- Fixed a bug when GetCompletionPct() could return value > 1
- Added bCheckDependentsFirst
- ConditionTick() stops using if bCheckDependentsFirst and DependentConditions incomplete
- HoldUseSeconds use difficulty modifiers
- if Screen_CountStyle == Count_Down, then seconds left are displayed on the HUD
- If UseActor uses collision cylinder, it will be always taken
in place, not only when it is blocking actors
Author : PooSH
Original Author: Alex Quick
--------------------------------------------------------------
*/
// if true, DependentConditions the progression
var(KF_ObjectiveCondition) bool bCheckDependentsFirst;
// call DependentConditions[].FindInstigator()?
var(KF_ObjectiveCondition) bool bCheckDependentsInstigator;
var(Audio) sound UsingSound;
var protected sound OriginalUsingSound;
var protected transient float InitialHoldUseSeconds;
function Reset()
{
ResetSound();
Super.Reset();
SetTargetActor(CurrentUserName,none);
}
function ResetSound()
{
local Actor MyUseActor;
// restore original ambient sound (mostly - none)
if ( UsingSound != OriginalUsingSound ) {
MyUseActor = GetTargetActor(UseActorName);
if ( MyUseActor != none && MyUseActor.AmbientSound != OriginalUsingSound )
MyUseActor.AmbientSound = OriginalUsingSound;
}
}
function PostBeginPlay(KF_StoryObjective MyOwner)
{
local Actor MyUseActor;
Super.PostBeginPlay(MyOwner);
InitialHoldUseSeconds = HoldUseSeconds;
MyUseActor = GetTargetActor(UseActorName);
if ( MyUseActor != none )
OriginalUsingSound = MyUseActor.AmbientSound;
}
function SetObjOwner(KF_StoryObjective NewOwner)
{
ResetSound(); // just to be sure we won't leave ambient sound for old actor
super.SetObjOwner(NewOwner);
}
function ConditionActivated(pawn ActivatingPlayer)
{
if ( InitialHoldUseSeconds > 0 )
HoldUseSeconds = InitialHoldUseSeconds * GetTotalDifficultyModifier();
Super.ConditionActivated(ActivatingPlayer);
}
function ConditionTick(float DeltaTime)
{
Super.ConditionTick(DeltaTime);
// stop using objective, if we don't match condition
if ( bCheckDependentsFirst && GetTargetActor(CurrentUserName) != none && !AllowCompletion() )
StopUsingObj(Pawn(GetTargetActor(CurrentUserName)));
}
function bool IsTouchingUseActor(pawn Toucher)
{
local Actor A;
local float DistSq;
local Actor MyUseActor;
MyUseActor = GetTargetActor(UseActorName);
if(Toucher != none && MyUseActor != none)
{
foreach Toucher.TouchingActors(class 'Actor', A)
{
if(A == MyUseActor)
{
return true;
}
}
// added bUseCylinderCollision in cases use actor doesn't want block actors (e.g. use blocking volume)
// but just wants to collide with actors
// -- PooSH
if( MyUseActor.bBlockActors || MyUseActor.bUseCylinderCollision )
{
DistSq = VsizeSquared(MyUseActor.Location - Toucher.Location) ;
if(DistSq <= Square( (MyUseActor.CollisionRadius + (Toucher.CollisionRadius)) * 1.25 ) )
{
return true;
}
}
}
return false;
}
function Startedusing(pawn User)
{
local Pawn CurrentUser;
local KF_UseableMover ControlledMover;
local Actor MyUseActor;
local Pawn OriginalIntigator;
local bool bCantUse;
if ( bComplete )
return; // no point of using already completed objective
MyUseActor = GetTargetActor(UseActorName);
ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName));
CurrentUser = Pawn(GetTargetActor(CurrentUserName));
if(CurrentUser == none && IsTouchingUseActor(User))
{
OriginalIntigator = GetInstigator();
// Instigator must be set to check DependentConditions
if ( OriginalIntigator != User )
SetTargetActor(InstigatorName, User);
bCantUse = bCheckDependentsFirst && !AllowCompletion();
if ( bCantUse ) {
SetTargetActor(InstigatorName, OriginalIntigator); // restore original instigator
return;
}
SetTargetActor(InstigatorName,User);
SetTargetActor(CurrentUserName,User);
LastUseTime = User.Level.TimeSeconds;
if(AllowCompletion())
{
bWasUsed = true;
}
if(ControlledMover != none)
{
ControlledMover.StartedUsing();
}
if ( HoldUseSeconds > 0 && UsingSound != none ) {
MyUseActor.AmbientSound = UsingSound;
MyUseActor.NetUpdateTime = MyUseActor.Level.TimeSeconds - 1;
}
}
}
function StopUsingObj(pawn User)
{
ResetSound();
super.StopUsingObj(User);
// ensure that we are not going abouve 100%
if ( FinishedUseSeconds > HoldUseSeconds )
FinishedUseSeconds = HoldUseSeconds;
}
// fixed progress going above 100% -- PooSH
function float GetCompletionPct()
{
return fclamp(super.GetCompletionPct(), 0.f, 1.f);
}
// count down style shows remaining time -- PooSH
function string GetDataString()
{
if(HoldUseSeconds > 0)
{
if ( HUD_Screen.Screen_CountStyle == 0 ) {
return string( (1.f-(GetRemainingUseTime() / HoldUseSeconds))*100.f) $"%" ;
}
else {
return string(GetRemainingUseTime()) ;
}
}
return "" ;
}
/* Overriden to skip inactive dependencies -- PooSH */
function bool AllowCompletion()
{
local int i;
local array<Pawn> MyInstigators;
if ( DependentConditions.length > 0 ) {
MyInstigators = GetInstigatorList();
for(i = 0 ; i < DependentConditions.length ; i ++) {
if ( DependentConditions[i].ConditionIsActive() ) {
if( !DependentConditions[i].bComplete
|| (bCheckDependentsInstigator && !DependentConditions[i].FindInstigator(MyInstigators)) )
{
return false;
}
}
}
}
return true;
}
defaultproperties
{
bCheckDependentsInstigator=True
}