Documentation for the Unreal C++ Plugin
Loading...
Searching...
No Matches
StoryManager.cpp
Go to the documentation of this file.
1// Copyright(c) Pixo Group. All Rights Reserved.
2
4#include "Net/UnrealNetwork.h"
11
14
15DEFINE_LOG_CATEGORY(LogStoryManager);
16
17bool FStoryStep::operator==(const FStoryStep& Step) const
18{
19 return Step.StepName.EqualTo(StepName);
20}
21
26
27bool UStoryManager::InitNewStory(int newStoryIndex)
28{
29 if (StoryDataArray.Num() == 0)
30 {
31 UE_LOG(LogStoryManager, Warning, TEXT("AStoryManager::InitNewStory StoryDataArray is empty"));
32 //GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, "AStoryManager::InitNewStory StoryDataArray is empty");
33 return false;
34 }
35
36 if (!StoryDataArray.IsValidIndex(newStoryIndex))
37 {
38 UE_LOG(LogStoryManager, Warning, TEXT("AStoryManager::InitNewStory Index out of range"));
39 return false;
40 }
41 // rewrite StoryDataArray with updated StoryData when loading new story in one experience
42 if (StoryData)
43 {
45 }
46 StoryData = StoryDataArray[newStoryIndex];
48 StepIndex = 0;
49 SubStepIndex = 0;
50 if (!StepData.IsValidIndex(StepIndex))
51 {
52 return false;
53 }
54
56 if (StepData[StepIndex].SubStep.IsValidIndex(SubStepIndex))
57 {
59 }
60 else
61 {
62 CurrentSubStep.StepName = FText();
64 }
65 StoryIndex = newStoryIndex;
66 StoryFinished = false;
68 OnStoryLoaded.Broadcast();
69 StepStartingTime = FDateTime::Now();
70
71 return true;
72}
73
75{
76 if (!StepData.IsValidIndex(StepIndex))
77 {
78 return false;
79 }
80
81 if (!StepData.IsValidIndex(StepIndex + 1))
82 {
83 StoryFinished = true;
84 OnEndOfStory.Broadcast();
86
87 UE_LOG(LogStoryManager, Warning, TEXT("AStoryManager::GoToNextStep Index out of range"));
88 return false;
89 }
90
91 StepIndex++;
94 SubStepIndex = 0;
95 if (StepData[StepIndex].SubStep.IsValidIndex(SubStepIndex))
96 {
98 }
99 else
100 {
101 CurrentSubStep.StepName = FText();
103 }
104
105 OnNewStep.Broadcast(CurrentStep, true);
107 StepStartingTime = FDateTime::Now();
108 UE_LOG(LogStoryManager, Log, TEXT("AStoryManager::GoToNextStep Next Step %s"), *CurrentStep.StepName.ToString());
109
110 return true;
111}
112
114{
115 if (!StepData.IsValidIndex(StepIndex))
116 {
117 return false;
118 }
119
120 if (!StepData[StepIndex].SubStep.IsValidIndex(SubStepIndex + 1))
121 {
123 SubStepIndex = 0;
124 return false;
125 }
126
127 SubStepIndex++;
128 //PreviousStep = CurrentStep;
130
131 OnNewSubStep.Broadcast(CurrentSubStep);
133 UE_LOG(LogStoryManager, Log, TEXT("AStoryManager::GoToNextSubStep Next SubStep %s"),
134 *CurrentSubStep.StepName.ToString());
135
136 return true;
137}
138
140{
141 if (!StepData.IsValidIndex(StepIndex))
142 {
143 return;
144 }
145
146 for (int i = 0; i < StepData[StepIndex].SubStep.Num(); i++)
147 {
148 if (StepData[StepIndex].SubStep[i].StepName.EqualTo(completedStep.StepName))
149 {
150 StepData[StepIndex].SubStep[i].Completed = true;
151 }
152 }
154 {
156 SubStepIndex = 0;
157 }
158}
159
161{
162 if (!StepData.IsValidIndex(index))
163 {
164 UE_LOG(LogStoryManager, Warning, TEXT("AStoryManager::JumpToStepByIndex Couldn't find a step by index %d"),
165 index);
166 return false;
167 }
168
169 bool isForward;
170 if (index < StepIndex)
171 {
172 isForward = false;
173
174 for (int i = StepIndex - 1; i >= index; i--)
175 {
176 OnStepSkipped.Broadcast(StepData[i].Step, false);
177 }
178 }
179 else
180 {
181 isForward = true;
182
183 for (int i = StepIndex; i < index; i++)
184 {
185 OnStepSkipped.Broadcast(StepData[i].Step, true);
186 }
187 }
188
189 StepIndex = index;
192 SubStepIndex = 0;
193 if (StepData[StepIndex].SubStep.IsValidIndex(SubStepIndex))
194 {
196 }
197 else
198 {
199 CurrentSubStep.StepName = FText();
201 }
202
203 OnNewStep.Broadcast(CurrentStep, isForward);
205 UE_LOG(LogStoryManager, Log, TEXT("AStoryManager::JumpToStepByIndex Jump To Step %s"),
206 *CurrentStep.StepName.ToString());
207
208 return true;
209}
210
212{
213 bool found = false;
214 int index = 0;
215
216 for (int i = 0; i < StepData.Num(); i++)
217 {
218 if (stepId.EqualTo(StepData[i].Step.StepName))
219 {
220 index = i;
221 found = true;
222 break;
223 }
224 }
225
226 if (found == false)
227 {
228 UE_LOG(LogStoryManager, Warning, TEXT("AStoryManager::JumpToStepByName Couldn't find a step %s"),
229 *stepId.ToString());
230 return false;
231 }
232
233 bool isForward;
234 if (index < StepIndex)
235 {
236 isForward = false;
237
238 for (int i = StepIndex - 1; i >= index; i--)
239 {
240 OnStepSkipped.Broadcast(StepData[i].Step, false);
241 }
242 }
243 else
244 {
245 isForward = true;
246
247 for (int i = StepIndex; i < index; i++)
248 {
249 OnStepSkipped.Broadcast(StepData[i].Step, true);
250 }
251 }
252
253 StepIndex = index;
256 SubStepIndex = 0;
257 if (StepData[StepIndex].SubStep.IsValidIndex(SubStepIndex))
258 {
260 }
261 else
262 {
263 CurrentSubStep.StepName = FText();
265 }
266
267 OnNewStep.Broadcast(CurrentStep, isForward);
269 UE_LOG(LogStoryManager, Log, TEXT("AStoryManager::JumpToStepByName Jump To Step %s"),
270 *CurrentStep.StepName.ToString());
271
272 return true;
273}
274
275void UStoryManager::StepCompleted(FText stepToUpdate, bool goToNext)
276{
277 if (!StepData.IsValidIndex(StepIndex))
278 {
279 return;
280 }
281
282 if (BlockStory == false)
283 {
284 if (stepToUpdate.EqualTo(CurrentStep.StepName))
285 {
286 StepData[StepIndex].Step.Completed = true;
288 OnStepCompleted.Broadcast(CurrentStep);
290
291 if (goToNext)
292 {
293 GoToNextStep();
294 }
295 }
296 }
297}
298
300{
301 StoryComponents.AddUnique(storyComponent);
302}
303
304void UStoryManager::SetupNextStory(int newNextStoryIndex, TArray<FText> newStoryParameters)
305{
306 NextStoryIndex = newNextStoryIndex;
307 StoryParameters = newStoryParameters;
308}
309
310bool UStoryManager::IsSpecificParametersExist(TArray<FText> SpecificParameters)
311{
312 for (auto SpecificParameter : SpecificParameters)
313 {
314 bool SpecificParameterFounded = false;
315 for (auto Parameter : StoryParameters)
316 {
317 if (SpecificParameter.EqualTo(Parameter))
318 {
319 SpecificParameterFounded = true;
320 break;
321 }
322 }
323 if (!SpecificParameterFounded)
324 return false;
325 }
326 return true;
327}
328
330{
331 return (((FDateTime::Now().GetHour() - StepStartingTime.GetHour())*360)+((FDateTime::Now().GetMinute() - StepStartingTime.GetMinute())*60)+(FDateTime::Now().GetSecond() - StepStartingTime.GetSecond()));
332}
333
335{
336 if (!StepData.IsValidIndex(StepIndex))
337 {
338 return false;
339 }
340
341 bool isCompleted = true;
342 for (FStoryStep steps : StepData[StepIndex].SubStep)
343 {
344 if (!steps.Completed)
345 {
346 isCompleted = false;
347 }
348 }
349 return isCompleted;
350}
351
353{
354 bool StoryAlreadyInArray = false;
355 int32 FoundedStoryIndex = 0;
356 for (int i = 0; i <= (PassedExperiencesArray.Num() - 1); i++)
357 {
359 {
360 StoryAlreadyInArray = true;
361 FoundedStoryIndex = i;
362 }
363 }
364 if (StoryAlreadyInArray)
365 {
366 PassedExperiencesArray[FoundedStoryIndex].PassedStepData = StepData;
367 }
368 else
369 {
370 FPassedExperiences TempExp;
371 TempExp.PassedStepData = StepData;
372 TempExp.StoryIndex = StoryIndex;
373 PassedExperiencesArray.Add(TempExp);
374 }
375}
376
377void UStoryManager::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
378{
379 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
380
381 DOREPLIFETIME(UStoryManager, StoryData);
382 DOREPLIFETIME(UStoryManager, StepData);
383 DOREPLIFETIME(UStoryManager, CurrentStep);
384 DOREPLIFETIME(UStoryManager, StepIndex);
385 DOREPLIFETIME(UStoryManager, PreviousStep);
386 DOREPLIFETIME(UStoryManager, CurrentSubStep);
387 DOREPLIFETIME(UStoryManager, SubStepIndex);
388 DOREPLIFETIME(UStoryManager, StoryIndex);
389}
390
395{
396 if (!StoryData->IsValidLowLevel() || StoryData->StepData.Num() == 0)
397 {
399 {
400 UE_LOG(LogStoryManager, Error, TEXT("AStoryManager::UInitializationEvent StoryDataArray is empty"));
401 }
402 }
403}
#define DEFINE_EVENT_HANDLER(TEventType)
Definition BaseManager.h:13
DEFINE_LOG_CATEGORY(LogStoryManager)
static FUNCTION_NON_NULL_RETURN_START TEventType * NewEvent(APlayerController *Executor=nullptr) FUNCTION_NON_NULL_RETURN_END
Creates a new event of the specified type.
void HandleEvent_Impl(class UBaseEvent *Event)
Event called when we on init experience.
A component responsible for managing the story progression in story actors.
TArray< FStepData > StepData
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Manager that provides handling story-related operations and data.
int StoryIndex
UPROPERTY(BlueprintReadWrite, Replicated)
UStoryManager()
FOnStepSkipped OnStepSkipped
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
TArray< UStoryComponent * > StoryComponents
UPROPERTY()
FOnNewStep OnNewStep
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
FStoryStep PreviousStep
UPROPERTY(BlueprintReadWrite, Replicated)
bool JumpToStepByIndex(int index)
UFUNCTION(BlueprintCallable)
void RecordStoryStepData()
Records the data for a story step. It checks if the story is already present in the PassedExperiences...
bool JumpToStepByName(FText stepId)
UFUNCTION(BlueprintCallable)
UStoryData * StoryData
UPROPERTY(BlueprintReadWrite, Replicated)
TArray< FPassedExperiences > PassedExperiencesArray
UPROPERTY(BlueprintReadWrite)
FStoryStep CurrentSubStep
UPROPERTY(BlueprintReadWrite, Replicated)
int StepIndex
UPROPERTY(BlueprintReadWrite, Replicated)
FOnStoryLoaded OnStoryLoaded
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
int SubStepIndex
UPROPERTY(BlueprintReadWrite, Replicated)
void CompleteSubStep(FStoryStep completedStep)
UFUNCTION(BlueprintCallable)
static TArray< FText > StoryParameters
void AddStoryComponent(UStoryComponent *storyComponent)
bool InitNewStory(int newStoryIndex)
Choose one story from StoryDataArray.
bool BlockStory
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray< UStoryData * > StoryDataArray
UPROPERTY(EditAnywhere, BlueprintReadWrite)
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > &OutLifetimeProps) const override
bool GoToNextSubStep()
UFUNCTION(BlueprintCallable)
bool GoToNextStep()
UFUNCTION(BlueprintCallable)
static void SetupNextStory(int newNextStoryIndex, TArray< FText > newStoryParameters)
UFUNCTION(BlueprintCallable)
static bool IsSpecificParametersExist(TArray< FText > SpecificParameters)
UFUNCTION(BlueprintCallable)
TArray< FStepData > StepData
UPROPERTY(BlueprintReadWrite, Replicated)
FOnStepCompleted OnStepCompleted
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
void StepCompleted(FText stepToUpdate, bool goToNext=true)
UFUNCTION(BlueprintCallable)
bool StoryFinished
UPROPERTY(BlueprintReadOnly)
FOnNewSubStep OnNewSubStep
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
static int NextStoryIndex
Keeps track of which story should be loaded next by index, saved between levels.
bool IsAllSubStepsCompleted()
UFUNCTION()
FStoryStep CurrentStep
UPROPERTY(BlueprintReadWrite, Replicated)
float GetCurrentStepDuration() const
UFUNCTION(BlueprintCallable, Category = "StoryManager|Misc")
FOnEndOfStory OnEndOfStory
UPROPERTY(BlueprintAssignable, Category = "Story Delegate")
FDateTime StepStartingTime
USTRUCT(BlueprintType)
int32 StoryIndex
UPROPERTY(BlueprintReadWrite)
TArray< FStepData > PassedStepData
UPROPERTY(BlueprintReadWrite)
USTRUCT(BlueprintType)
bool operator==(const FStoryStep &Step) const
FText StepName
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool Completed
UPROPERTY(BlueprintReadWrite, EditAnywhere)