LEGO Quest System With NPC Behavior
Module — 6 files
These files compile together (same module folder).
file_1.verse
# This is the LEGO Quest Giver system built for the Action Adventure Template.
# In order to utilize this you'll need to create a Verse script for each snippet
# The LEGO Quest Giver Device
# Controls the quest system and is the central device that runs this system.
# The LEGO Quest Class
# Defines the quest object and is referenced in the Quest Array in the LEGO Quest
# Giver Device. This is currently dependent on the LEGO_Stud_Rewards module as the quest rewards players on
# Completion. If you are not using that module you'll need to comment out (#) The Using on Line 7, the
# LEGO_stud_Spawner reference and tooltip in the field definitions, as well as any call to that LEGO_Stud_Spawner
# called Reward
# The LEGO Quest Dialogue
# Creates and populates the quest UI window with information sent in from the LEGO
# Quest Device
# Line 138/139 define a texture block that requires a DefaultImage. Currently the
# code references 'T_LEGO_Quests_Dialog_Divider' which is provided in the Action #
# Adventure Template. You can copy the UAsset from the project into the same
# directory as your Quest_Dialogue class, or create your own divider image.
# The LEGO Persistent Quest Log
# Enables the quests to be saved. This persistency is on a per-player basis
# the initiating player will be the one that the data is associated with).
# The Quest Giver NPC Behavior
# is the custom behaviour you will assign in your NPC spawner. This will put the NPC # into stasis, so that it will stand still to interact with your player.
# Full setup guide can be found here:
# https://www.youtube.com/live/VyaB47DHt4gsi=rWqu22dLykl_WVAl&t=1409
lego_quest_giver_device.verse
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# ====================================================================================================================================
# LEGO quest giver device that manages a linear quest system
# ====================================================================================================================================
lego_quest_giver_device_log<public> := class(log_channel) {}
lego_quest_giver_device := class(creative_device):
@editable:
ToolTip := Tooltip_QuestGiver_Name
QuestGiverName<public> : string = "Quest Giver"
@editable:
ToolTip := Tooltip_Button_Interact
Button_Interact : button_device = button_device{}
@editable:
Categories := array{Category_FinishedGuidance}
ToolTip := Tooltip_QuestGiver_Tracker
TrackerDevice<public> : tracker_device = tracker_device{}
@editable:
Categories := array{Category_FinishedGuidance}
ToolTip := Tooltip_BeaconReturn
ReturnBeacon<public> : beacon_device = beacon_device{}
@editable:
ToolTip := Tooltip_AutoProgressDialog
Categories := array{Category_Settings}
AutoProgressDialog<public> : logic = true
@editable:
ToolTip := Tooltip_ResetProgress
Categories := array{Category_Settings}
Trigger_ResetProgress : ?trigger_device = false
@editable:
ToolTip := Tooltip_Quests
Quests : []lego_quest = array{}
Logger<protected>: log = log{Channel := lego_quest_giver_device_log, DefaultLevel:= log_level.Normal}
OnBegin<override>()<suspends>:void=
# Bind to button interaction event
Button_Interact.InteractedWithEvent.Subscribe(OnRequestInteraction)
Button_Interact.SetInteractionText(ToMessage("Talk to {QuestGiverName}"))
# Bind to Reset request trigger
if (ValidTrigger := Trigger_ResetProgress?):
ValidTrigger.TriggeredEvent.Subscribe(OnResetProgress)
# Setup Tracker Device (Return to QuestGiver message)
TrackerDevice.SetTitleText(ToMessage("Completed Quest"))
TrackerDevice.SetDescriptionText(ToMessage("Return to {QuestGiverName}"))
# Setup Event subscribes for all quests
for (Quest : Quests):
Quest.Setup(Self, TrackerDevice, ReturnBeacon)
# ---------------------------------------------------------------------------------------------------------------------------------
# Player Interaction with QuestGiver
# 1) Show Dialog UI
# 2) Wait for player interaction that closes the UI
# 3) Process and apply Response from Dialog UI (Start / Complete / Abort quest / Close)
# ---------------------------------------------------------------------------------------------------------------------------------
OnRequestInteraction<public>(InAgent : agent): void=
if (Quests.Length = 0):
Logger.Print("OnRequestInteraction failed - no quests found.", ?Level := log_level.Error)
return
TrackerDevice.Complete(InAgent)
spawn{InteractWithQuestGiver(InAgent)}
InteractWithQuestGiver<private>(InAgent : agent)<suspends>: void=
TrackerDevice.Complete(InAgent)
QuestProgressData := GetQuestLineProgression(InAgent)
# Create UI to be shown to the player
DialogUI := lego_quest_dialog{}
# Configure UI based on QuestLine progression
# iE. what button text to display and what Dialog option to show
Title := if(ValidQuest := QuestProgressData(1)?) {ToMessage(ValidQuest.Name)} else {ToMessage("")}
Dialog_Start := if(ValidQuest := QuestProgressData(1)?) {ToMessage(ValidQuest.DisplayText.DialogText_Start)} else {ToMessage("I don`t have any quests for you right now.")}
Dialog_Complete := if(ValidQuest := QuestProgressData(1)?) {ToMessage(ValidQuest.DisplayText.DialogText_Complete)} else {ToMessage("")}
var Text : ?message = false
var Button_1_Text : string = ""
var Button_2_Text : string = ""
case (QuestProgressData(0)):
en_lego_quest_progress.NotStarted =>
set Button_1_Text = "Accept Quest "
set Button_2_Text = "Decline Quest"
set Text = option{Dialog_Start}
en_lego_quest_progress.IsActive =>
set Button_2_Text = "Abort Quest"
set Text = option{Dialog_Start}
en_lego_quest_progress.CanBeCompleted =>
set Button_1_Text = "Finish Quest"
set Button_2_Text = "Abort Quest"
set Text = option{Dialog_Complete}
en_lego_quest_progress.None =>
set Text = option{Dialog_Start}
_=>
Button_1_Message : message = ToMessage(Button_1_Text)
Button_2_Message : message = ToMessage(Button_2_Text)
# Data to be passed to the UI class, the LEGO_quest_dialog will then process and display it
DialogConfig := lego_dialog_config:
Title := option{Title},
Text := Text,
Button_1_Text := if(Button_1_Text.Length > 0) {option{Button_1_Message}} else {false},
Button_2_Text := if(Button_2_Text.Length > 0) {option{Button_2_Message}} else {false}
# 1) Show UI
DialogUI.ShowDialog(InAgent, DialogConfig)
# 2) Wait for player interaction
DialogResponse := DialogUI.OnDialogCompleted.Await()
# 3) Process Response from the UI
# Which Button did the player press? Start / Complete / Abort / Close
if (DialogResponse = en_lego_quest_dialog_response.Close) {return}
# Process Response based on the players progress through the questline
if (ValidQuest := QuestProgressData(1)?):
case (QuestProgressData(0)):
# Start new quest
en_lego_quest_progress.NotStarted =>
if (DialogResponse = en_lego_quest_dialog_response.Accept):
ValidQuest.StartQuest(InAgent)
# Complete active quest
en_lego_quest_progress.CanBeCompleted =>
if (DialogResponse = en_lego_quest_dialog_response.Accept):
ValidQuest.CompleteQuest(InAgent)
# Open next quest Dialog (if auto Dialog progression is enabled)
if (AutoProgressDialog?) {spawn{InteractWithQuestGiver(InAgent)}}
# Abort quest
if (DialogResponse = en_lego_quest_dialog_response.Decline):
ValidQuest.AbortQuest(InAgent)
# Abort quest
en_lego_quest_progress.IsActive =>
if (DialogResponse = en_lego_quest_dialog_response.Decline):
ValidQuest.AbortQuest(InAgent)
_=>
# No Response to process
else:
Logger.Print("InteractWithQuestGiver failed - no valid quest found.", ?Level := log_level.Error)
# ---------------------------------------------------------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------------------------------------------------------
# QuestLine Progression
# Loop over all the quests and return the first quest that can either be started, completed or is active
# ---------------------------------------------------------------------------------------------------------------------------------
GetQuestLineProgression<public>(InAgent : agent)<transacts>: tuple(en_lego_quest_progress, ?lego_quest)=
if (Quests.Length = 0):
Logger.Print("GetQuestLineProgression: QuestGiver has no quests.", ?Level := log_level.Warning)
for (Quest : Quests):
# Quest can be started
if (Quest.CanBeStarted[InAgent]):
return (en_lego_quest_progress.NotStarted, option{Quest})
# Quest is active and can be completed or aborted
if (Quest.IsActive[InAgent]):
if (Quest.CanBeCompleted[InAgent]):
return (en_lego_quest_progress.CanBeCompleted, option{Quest})
return (en_lego_quest_progress.IsActive, option{Quest})
# No available quests
return (en_lego_quest_progress.None, false)
# ---------------------------------------------------------------------------------------------------------------------------------
# This function is called when the Trigger_ResetProgress is activated and resets all quest progress for the activating player
OnResetProgress<public>(InAgent : ?agent): void=
if:
ValidAgent := InAgent?
ValidQuestLog := ValidAgent.LoadLegoQuestLog[]
then:
UpdatedQuestLog := LEGO_persistent_quest_log:
ActiveQuests := array{},
CompletedQuests := array{}
if (ValidAgent.SaveLegoQuestLog[UpdatedQuestLog]) {}
else:
Logger.Print("ResetPersistentData failed - no quest log found.", ?Level := log_level.Error)
Tooltip_QuestGiver_Name<public><localizes>:message = "The name of the quest giver as it will appear in the tracker UI and button interaction text."
Tooltip_Button_Interact<public><localizes>:message = "The button that the player must press to interact with the quest giver."
Tooltip_QuestGiver_Tracker<public><localizes>:message = "The tracker_device used to display the return to questgiver message."
Tooltip_BeaconReturn<public><localizes>:message = "This beacon can be used to guide the player back to the quest giver once a quest is completed."
Tooltip_AutoProgressDialog<public><localizes>:message = "If true, the quest giver will automatically show the next quest Dialog after the player has completed a quest."
Tooltip_ResetProgress<public><localizes>:message = "Trigger device that will reset the progress in all quests for the activating player."
Tooltip_Quests<public><localizes>:message = "The quests that the quest giver can give to the player."
Category_Settings<public><localizes>:message = "Settings"
Category_FinishedGuidance<public><localizes>:message = "Quest finished guidance"
file_3.verse
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { LEGOModule_StudRewards}
# ============================================================================================================================================
# Definition of a completable quest with dialog setup and reward
# ============================================================================================================================================
en_lego_quest_progress<public> := enum{ None, NotStarted, IsActive, CanBeCompleted, Completed }
lego_quest_log<public> := class(log_channel) {}
lego_quest_repeatable<public> := class<concrete><unique>(lego_quest) {}
lego_quest<public> := class<concrete><unique>():
@editable:
ToolTip := ToolTip_Quest_Name
Name<public> : string = "UNIQUE Quest Name"
@editable
DisplayText<public> : lego_quest_info = lego_quest_info{}
@editable:
ToolTip := ToolTip_EventBindings
EventBindings<public> : ?lego_quest_eventbindings = false
@editable:
ToolTip := Tooltip_Tracker
TrackerDevice<public> : tracker_device = tracker_device{}
@editable:
ToolTip := Tooltip_Beacon
GuidingBeacons<public> : []beacon_device = array{}
@editable:
ToolTip := ToolTip_Quest_Reward
Reward<public> : lego_stud_spawner = lego_stud_spawner{}
var CompletedObjectives : [agent]logic = map{}
var TrackerDeviceQuestGiver : tracker_device = tracker_device{}
var ReturnBeacon : beacon_device = beacon_device{}
Logger<protected>: log = log{Channel := lego_quest_log, DefaultLevel:= log_level.Normal}
# --------------------------------------------------------------------------------------------------------------------------------------------
# API
# --------------------------------------------------------------------------------------------------------------------------------------------
# This is called by the quest giver to setup the quest with the required devices
Setup<public>(InCreativeDevice : creative_device, InTrackerDeviceQuestGiver : tracker_device, InReturnBeacon : beacon_device): void=
set TrackerDeviceQuestGiver = InTrackerDeviceQuestGiver
set ReturnBeacon = InReturnBeacon
TrackerDevice.CompleteEvent.Subscribe(OnCompletedObjective)
TrackerDevice.SetTitleText(ToMessage(Name))
TrackerDevice.SetDescriptionText(ToMessage(DisplayText.Description))
Reward.Init(InCreativeDevice)
# Start the quest for a player, add it to the quest log and update the tracker device
StartQuest<public>(InAgent : agent): void=
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
TrackerDevice.Assign(InAgent)
for (Beacon : GuidingBeacons):
Beacon.AddToShowList(InAgent)
if (ValidTrigger := EventBindings?.Trigger_OnStartedQuest?):
ValidTrigger.Trigger(InAgent)
# Update persistent quest log
UpdatedQuestLog := LEGO_persistent_quest_log:
ActiveQuests := ValidQuestLog.ActiveQuests + array{Name},
CompletedQuests := ValidQuestLog.CompletedQuests
if (InAgent.SaveLegoQuestLog[UpdatedQuestLog]):
Logger.Print("Quest Log updated.")
else:
Logger.Print("StartQuest failed - no quest log found.", ?Level := log_level.Error)
# Abort the quest for a player, remove it from the quest log and update the tracker device
AbortQuest<public>(InAgent : agent): void=
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
TrackerDevice.Reset(InAgent)
for (Beacon : GuidingBeacons):
Beacon.RemoveFromShowList(InAgent)
if (ValidTrigger := EventBindings?.Trigger_OnAbortedQuest?):
ValidTrigger.Trigger(InAgent)
# Update persistent quest log
var UpdatedActiveQuests : []string = array{}
for (ActiveQuest : ValidQuestLog.ActiveQuests; ActiveQuest <> Name):
set UpdatedActiveQuests += array{ActiveQuest}
UpdatedQuestLog := LEGO_persistent_quest_log{
ActiveQuests := UpdatedActiveQuests,
CompletedQuests := ValidQuestLog.CompletedQuests}
if (InAgent.SaveLegoQuestLog[UpdatedQuestLog]) {}
else:
Logger.Print("AbortQuest failed - no quest log found.", ?Level := log_level.Error)
# Complete the quest for a player, remove it from the quest log and update the tracker device, handle rewards
CompleteQuest<public>(InAgent : agent): void=
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
TrackerDevice.Complete(InAgent)
ReturnBeacon.RemoveFromShowList(InAgent)
if (lego_quest_repeatable[Self]):
TrackerDevice.Reset(InAgent)
for (Beacon : GuidingBeacons):
Beacon.RemoveFromShowList(InAgent)
if (ValidCharacter := InAgent.GetFortCharacter[]):
Reward.SpawnStudsAtLocation(ValidCharacter.GetTransform().Translation)
else:
Print("CompleteQuest failed - no valid FortCharacter found.")
if (ValidTrigger := EventBindings?.Trigger_OnCompletedQuest?):
ValidTrigger.Trigger(InAgent)
# Update persistent quest log
var UpdatedActiveQuests : []string = array{}
for (ActiveQuest : ValidQuestLog.ActiveQuests; ActiveQuest <> Name):
set UpdatedActiveQuests += array{ActiveQuest}
UpdatedQuestLog := LEGO_persistent_quest_log{
ActiveQuests := UpdatedActiveQuests,
CompletedQuests := ValidQuestLog.CompletedQuests + array{Name}}
if (InAgent.SaveLegoQuestLog[UpdatedQuestLog]) {}
else:
Logger.Print("CompleteQuest failed - no quest log found.", ?Level := log_level.Error)
# --------------------------------------------------------------------------------------------------------------------------------------------
# Helper functions to determine the state of the quest
# --------------------------------------------------------------------------------------------------------------------------------------------
IsActive<public>(InAgent : agent)<transacts><decides>: void=
var Result : logic = false
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
if (ValidQuestLog.ActiveQuests.Find[Name]):
set Result = true
Result?
CanBeStarted<public>(InAgent : agent)<transacts><decides>: void=
var Result : logic = true
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
if (ValidQuestLog.ActiveQuests.Find[Name]):
set Result = false
if (ValidQuestLog.CompletedQuests.Find[Name]):
if (lego_quest_repeatable[Self]) {}
else:
set Result = false
else:
Logger.Print("No quest log found for agent.")
set Result = false
Result?
CanBeCompleted<public>(InAgent : agent)<transacts><decides>: void=
var Result : logic = false
if (CompletedObjectives[InAgent] = true):
set Result = true
Result?
HasBeenCompleted<public>(InAgent : agent)<transacts><decides>: void=
var Result : logic = false
if (ValidQuestLog := InAgent.LoadLegoQuestLog[]):
if (ValidQuestLog.CompletedQuests.Find[Name]):
set Result = true
Result?
OnCompletedObjective<public>(InAgent : agent): void=
if (set CompletedObjectives[InAgent] = true) {}
TrackerDeviceQuestGiver.Assign(InAgent)
ReturnBeacon.AddToShowList(InAgent)
# --------------------------------------------------------------------------------------------------------------------------------------------
# Quest Info class, used to pass the quest description and dialog texts to the dialog UI
# --------------------------------------------------------------------------------------------------------------------------------------------
lego_quest_info<public> := class<concrete>():
@editable:
ToolTip := Tooltip_ObjectiveDescription
Description<public> : string = "Quest description"
@editable_text_box:
ToolTip := Tooltip_DialogText_Start
MultiLine := true
DialogText_Start<public> : string = ""
@editable_text_box:
ToolTip := Tooltip_DialogText_Complete
MultiLine := true
DialogText_Complete<public> : string = ""
# ============================================================================================================================================
# Event binding interface
# ============================================================================================================================================
lego_quest_eventbindings<public> := class<concrete>():
@editable
Trigger_OnStartedQuest : ?trigger_device = false
@editable
Trigger_OnAbortedQuest : ?trigger_device = false
@editable
Trigger_OnCompletedQuest : ?trigger_device = false
ToolTip_Quest_Name<public><localizes>:message = "The name of the quest as it will appear in the tracker_device and dialog UI. MUST be unique!"
ToolTip_EventBindings<public><localizes>:message = "Trigger Devices for linking other Fortnite Creative devices to this quest."
Tooltip_Tracker<public><localizes>:message = "The tracker_device that is required to complete for finishing the quest."
Tooltip_Beacon<public><localizes>:message = "This beacon can be used to guide the player towards the objective of the quest."
ToolTip_Quest_Reward<public><localizes>:message = "The Stud reward that will be given to the player when the quest is completed."
Tooltip_ObjectiveDescription<public><localizes>:message = "The description as visible in the tracker_device UI."
Tooltip_DialogText_Start<public><localizes>:message = "The text that will be displayed in the dialog when the quest is started."
Tooltip_DialogText_Complete<public><localizes>:message = "The text that will be displayed in the dialog when the quest is completed."
lego_quest_dialog.verse
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Simulation }
using { /Fortnite.com/UI }
using { /Verse.org/Assets }
using { /Verse.org/Colors }
using { /Verse.org/Colors/NamedColors }
ButtonCloseText<localizes><public> : message = "Close"
ToMessage<public><localizes>(InString : string)<transacts>: message = "{InString}"
# =====================================================================================================================================
# Quest giver UI
# Dialog Box
# =====================================================================================================================================
en_lego_quest_dialog_response<public> := enum{ Accept, Decline, Close }
lego_dialog_config<public> := struct():
Title<public> : ?message = false
Text : ?message = false
Button_1_Text : ?message = false
Button_2_Text : ?message = false
lego_quest_dialog := class():
var OwningPlayer : ?agent = false
var Canvas : ?widget = false
var Button_1 : text_button_base = button_loud{}
var Callback_ButtonClicked_1 : ?cancelable = false
var Button_2 : text_button_base = button_loud{}
var Callback_ButtonClicked_2 : ?cancelable = false
Button_Close : text_button_base = button_quiet{ DefaultText := ButtonCloseText}
var Callback_ButtonClicked_Close : ?cancelable = false
Logger<protected>: log = log{Channel := lego_quest_giver_device_log, DefaultLevel:= log_level.Normal}
# ---------------------------------------------------------------------------------------------------------------------------------
# Dialog UI Flow:
# 1) Open
# 2) Wait for player response
# 3) Close
# 4) Emit Dialog response as a command
# ---------------------------------------------------------------------------------------------------------------------------------
ShowDialog<public>(InAgent : agent, InDialogConfig : lego_dialog_config): void=
set OwningPlayer = option{InAgent}
# Setup Buttons
Callback_Close := Button_Close.OnClick().Subscribe(OnButtonClicked_Close)
set Callback_ButtonClicked_Close = option{Callback_Close}
if (ButtonText_1 := InDialogConfig.Button_1_Text?):
Button_1.SetText(ButtonText_1)
CallBack_Button1 := Button_1.OnClick().Subscribe(OnButtonClicked_1)
set Callback_ButtonClicked_1 = option{CallBack_Button1}
if (ButtonText_2 := InDialogConfig.Button_2_Text?):
Button_2.SetText(ButtonText_2)
CallBack_Button2 := Button_2.OnClick().Subscribe(OnButtonClicked_2)
set Callback_ButtonClicked_2 = option{CallBack_Button2}
# Create Canvas and add to Player Screen
set Canvas = option{MakeDialogCanvas(InDialogConfig)}
if:
PlayerUI := GetPlayerUI[player[OwningPlayer?]]
ValidCanvas := Canvas?
then:
PlayerUI.AddWidget(ValidCanvas, player_ui_slot{ZOrder := 3, InputMode := ui_input_mode.All})
else:
Logger.Print("Failed to show Dialog UI for player.", ?Level := log_level.Error)
# Accept / Complete Button
OnButtonClicked_1(Message : widget_message): void=
CompleteDialog(en_lego_quest_dialog_response.Accept)
# Decline / Abort Button
OnButtonClicked_2(Message : widget_message): void=
CompleteDialog(en_lego_quest_dialog_response.Decline)
# Close Button
OnButtonClicked_Close(Message : widget_message): void=
CompleteDialog(en_lego_quest_dialog_response.Close)
OnDialogCompleted<public> : event(agent; en_lego_quest_dialog_response) = event(agent; en_lego_quest_dialog_response){}
CompleteDialog<public>(InDialogCommand : en_lego_quest_dialog_response): void=
# Unsubscribe from Button clicks
if (ValidCallback := Callback_ButtonClicked_Close?):
ValidCallback.Cancel()
if (ValidCallback := Callback_ButtonClicked_1?):
ValidCallback.Cancel()
if (ValidCallback := Callback_ButtonClicked_2?):
ValidCallback.Cancel()
# Remove Canvas from Player Screen
if:
ValidOwningPlayer := OwningPlayer?
PlayerUI := GetPlayerUI[player[ValidOwningPlayer]]
ValidCanvas := Canvas?
then:
PlayerUI.RemoveWidget(ValidCanvas)
set Canvas = false
set OwningPlayer = false
OnDialogCompleted.Signal(ValidOwningPlayer; InDialogCommand)
# ---------------------------------------------------------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------------------------------------------------------
# VERSE UI creation
# Create a canvas with the Dialog UI
# ---------------------------------------------------------------------------------------------------------------------------------
MakeDialogCanvas<protected>(InDialogConfig : lego_dialog_config)<transacts>: canvas=
Anchor_Root := vector2{X := 0.5, Y := 0.6}
OutCanvas : canvas = canvas:
Slots := array:
# Background
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root, Maximum := Anchor_Root}
SizeToContent := true
Offsets := margin{Top := 0.0, Left := -765.0}
Widget := texture_block:
DefaultImage := T_LEGO_Quests_Dialog_Background
DefaultDesiredSize := vector2{X:= 1580.0, Y := 394.0}
# Divider
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root, Maximum := Anchor_Root}
SizeToContent := true
Offsets := margin{Top := 0.0, Left := -765.0}
Widget := texture_block:
DefaultImage := T_LEGO_Quests_Dialog_Divider
DefaultDesiredSize := vector2{X:= 1580.0, Y := 394.0}
# Text
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root + vector2{ X := -0.0, Y := 0.0}, Maximum := Anchor_Root + vector2{ X := -0.0, Y := 0.0}}
Widget := overlay:
Slots := array:
# Title
overlay_slot:
VerticalAlignment := vertical_alignment.Top
HorizontalAlignment := horizontal_alignment.Left
Padding := margin{Top := 80.0, Left := -600.0}
Widget := if (ValidContent := InDialogConfig.Title?)
{text_block:
DefaultText := ValidContent
DefaultTextColor := Orange
DefaultJustification := text_justification.Left
DefaultShadowColor:= MakeColorFromSRGB(0.05, 0.05, 0.05)
DefaultShadowOffset := option{vector2{X := 4.0, Y := 4.0}}
DefaultShadowOpacity := 1.0
}
else {text_block{}}
# Dialog Body
overlay_slot:
VerticalAlignment := vertical_alignment.Top
HorizontalAlignment := horizontal_alignment.Left
Padding := margin{Top := 135.0, Left := -600.0}
Widget := if (ValidContent := InDialogConfig.Text?)
{text_block:
DefaultText := ValidContent
DefaultTextColor := White
DefaultJustification := text_justification.Left
DefaultShadowColor:= MakeColorFromSRGB(0.05, 0.05, 0.05)
DefaultShadowOffset := option{vector2{X := 2.0, Y := 2.0}}
DefaultShadowOpacity := 1.0
}
else {text_block{}}
# Button 1
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root + vector2{ X := -0.18, Y := 0.25 }, Maximum := Anchor_Root + vector2{ X := -0.18, Y := 0.25 }}
Widget := if (ValidContent := InDialogConfig.Button_1_Text?) { Button_1 } else {text_block{}}
# Button 2
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root + vector2{ X := 0.0225, Y := 0.25 }, Maximum := Anchor_Root + vector2{ X := 0.0225, Y := 0.25 }}
Widget := if (ValidContent := InDialogConfig.Button_2_Text?) { Button_2 } else {text_block{}}
# Button Close
canvas_slot:
Anchors := anchors{ Minimum := Anchor_Root + vector2{ X := 0.275, Y := 0.05 }, Maximum := Anchor_Root + vector2{ X := 0.275, Y := 0.05 }}
Widget := Button_Close
npc_behavior_quest_giver.verse
using { /Fortnite.com/AI }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
# ============================================================================================================================================
# QuestGiver NPC Behavior
# -> This NPC just stands in place
# ============================================================================================================================================
npc_behavior_quest_giver := class(npc_behavior):
OnBegin<override>()<suspends>:void=
if:
NPCCharacter := GetAgent[].GetFortCharacter[]
then:
NPCCharacter.PutInStasis(stasis_args{AllowTurning := true, AllowFalling := false, AllowEmotes := false})
file_6.verse
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
# ====================================================================================================================================
# Stores the quest progress per-player - this is persistent data
# ====================================================================================================================================
var GlobalPersistentData_QuestLog : weak_map(player, LEGO_persistent_quest_log) = map{}
LEGO_persistent_quest_log<public> := class<persistable><final>:
CompletedQuests : []string = array{}
ActiveQuests : []string = array{}
(InAgent : agent).LoadLegoQuestLog()<decides><transacts>: LEGO_persistent_quest_log=
var Result : ?LEGO_persistent_quest_log = false
if(FoundData := GlobalPersistentData_QuestLog[player[InAgent]]):
set Result = option{FoundData}
else:
set Result = option{LEGO_persistent_quest_log{}}
if (InAgent.SaveLegoQuestLog[Result?]) {}
Result?
# Set the persistent data stored for this player.
(InAgent : agent).SaveLegoQuestLog<public>(InQuestLog : LEGO_persistent_quest_log)<decides><transacts>: void=
var Result : logic = false
if (set GlobalPersistentData_QuestLog[player[InAgent]] = InQuestLog):
set Result = true
else:
Logger: log = log{Channel:= lego_quest_log, DefaultLevel:= log_level.Normal}
Logger.Print("Failed to save LEGO_fortplayer_persistence_data.", ?Level:= log_level.Error)
Result?
Sign in to download module
Copy-paste each file above is always free.