/* -------------------------------------------------------------- Condition_Use -------------------------------------------------------------- This Condition is marked complete when a player presses the 'Use' key while in range of its owning actor. Author : Alex Quick -------------------------------------------------------------- */ class ObjCondition_Use extends KF_ObjectiveCondition editinlinenew; /* requires that line of sight be maintained with the objective during the use process. Only really relevant if HoldUseSeconds is something > 0 */ var () bool bMaintainUseLOS; /* Min View angle cosine required to perform a 'use' action */ var () float MinUseViewAngle; /* Number of seconds a player must hold the use key for before the objective completes. Releasing the key will abort any progress. */ var () float HoldUseSeconds; /* if true, any progress made 'Using' this objective will be kept if the player stops holding the use key. only relevant if HoldUseSeconds is > 0 */ var () bool bKeepUseProgress; var () name UsePawn_Tag; var float FinishedUseSeconds; var float LastUseTime; var bool bAcquiredPawn; var bool bWasUsed; var const name UseActorName,InitialUseActorName,CurrentUserName,ControlledMoverName; var () edfindable private Actor UseActor; // this exists only for level designers. function Reset() { Super.Reset(); FinishedUseSeconds = 0.f; bWasUsed = false; } function PostBeginPlay(KF_StoryObjective MyOwner) { Super.PostBeginPlay(MyOwner); // Ditch any reference to this actor ASAP. if(UseActor != none) { SetTargetActor(InitialUseActorName,UseActor); SetTargetActor(UseActorName,UseActor); UseActor = none; } } function SetObjOwner(KF_StoryObjective NewOwner) { local Actor MyUseActor; MyUseActor = GetTargetActor(UseActorName); if(MyUseActor == none || (NewOwner != MyUseActor && GetObjOwner() == MyUseActor)) { SetTargetActor(UseActorName,NewOwner); } Super.SetObjOwner(NewOwner); } function ConditionActivated(pawn ActivatingPlayer) { local Actor InitialUseActor,MyUseActor; local KF_UseableMover ControlledMover; Super.ConditionActivated(ActivatingPlayer); InitialUseActor = GetTargetActor(InitialUseActorName); MyUseActor = GetTargetActor(UseActorName); if(InitialuseActor != none && !InitialuseActor.bPendingDelete) { SetTargetActor('UseActorName',InitialUseActor); if(KF_UseableMover(MyUseActor) != none) { SetTargetActor(ControlledMoverName,KF_UseableMover(MyUseActor)); ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName)); if(ControlledMover != none) { ControlledMover.Notify_Controlled(self); } } } } function ConditionTick(float DeltaTime) { local float RemainingHoldUseTime; local Actor MyUseActor; local Pawn CurrentUser; UpdateUseablePawnList(); MyUseActor = GetTargetActor(UseActorName); CurrentUser = Pawn(GetTargetActor(CurrentUserName)); /* Important we call this before the Range checks or it won't register completion */ Super.ConditionTick(DeltaTime); if(CurrentUser != none && CurrentUser.Controller != none) { RemainingHoldUseTime = GetRemainingUseTime() ; if(!InRangeAndView() || RemainingHoldUseTime <= 0) { StopUsingObj(CurrentUser); } } } function UpdateUseablePawnList() { local Controller C; local Actor MyUseActor; MyUseActor = GetTargetActor(UseActorName); if(UsePawn_Tag == '' || (MyUseActor != none && MyUseActor.Tag == UsePawn_Tag)) { return; } for ( C= GetObjOwner().Level.ControllerList; C!=None; C=C.NextController ) { if(C.Pawn != none && !C.Pawn.bDeleteMe && !C.Pawn.bPendingDelete && C.Pawn.Health > 0 && C.Pawn.Tag == UsePawn_Tag) { SetTargetActor(UseActorName,C.Pawn); break; } } } function bool InRangeAndView() { local bool bhasLOS; local bool bInRange; local Pawn CurrentUser; CurrentUser = Pawn(GetTargetActor(CurrentUserName)); if(CurrentUser == none) { return false; } bHasLOS = (!bMaintainUseLOS || KFPlayerController_Story(CurrentUser.Controller) != none && KFPlayerController_Story(CurrentUser.Controller).IsLookingAtLocation(GetLocation(),MinUseViewAngle)); bInRange = IsTouchingUseActor(CurrentUser) ; return bInRange && bHasLOS; } 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; } } if(MyUseActor.bBlockActors) { 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; ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName)); CurrentUser = Pawn(GetTargetActor(CurrentUserName)); if(CurrentUser == none && IsTouchingUseActor(User)) { SetTargetActor(InstigatorName,User); SetTargetActor(CurrentUserName,User); LastUseTime = User.Level.TimeSeconds; if(AllowCompletion()) { bWasUsed = true; } if(ControlledMover != none) { ControlledMover.StartedUsing(); } } } function StoppedUsing(pawn User) { local KF_UseableMover ControlledMover; ControlledMover = KF_USeableMover(GetTargetActor(ControlledMoverName)); StopusingObj(User); if(ControlledMover != none) { ControlledMover.StoppedUsing(); } } function StopUsingObj(pawn User) { local Pawn CurrentUser; CurrentUser = Pawn(GetTargetActor(CurrentUserName)); if(CurrentUser != none && User == CurrentUser) { /* Cache the amount of time we have been holding use for */ if( bKeepUseProgress) { FinishedUseSeconds += (User.Level.TimeSeconds - LastUseTime) ; } SetTargetActor(CurrentUserName,none); } } function vector GetLocation(optional out actor LocActor) { local Actor MyUseActor; if(ConditionIsActive()) { MyUseActor = GetTargetActor(UseActorName); if(MyUseActor != none && !MyUseActor.bPendingDelete) { LocActor = MyUseActor; return MyUseActor.Location; } return Super.GetLocation(LocActor); } } /* returns the percentage of completion for this condition */ function float GetCompletionPct() { if(HoldUseSeconds > 0) { return 1.f - (GetRemainingUseTime() / HoldUseSeconds); } else { return float(bWasUsed); } } /* Wrapper for finding the amount of time a player needs to hold down the USE key to complete this condition */ function float GetRemainingUseTime() { local Pawn CurrentUser; CurrentUser = Pawn(GetTargetActor(CurrentUserName)); if(CurrentUser != none) { return FMax(HoldUseSeconds - ((GetObjOwner().Level.TimeSeconds - LastUseTime) + FinishedUseSeconds), 0.f) ; } return (HoldUseSeconds - FinishedUseSeconds); } function string GetDataString() { if(HoldUseSeconds > 0) { return Round((1.f-(GetRemainingUseTime() / HoldUseSeconds))*100.f)$"%" ; } return "" ; } DefaultProperties { UseActorName = "UseActor" InitialUseActorName = "InitialUseActor" CurrentUserName = "CurrentUser" ControlledMoverName = "ControlledMover" }