using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# See https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse for how to create a verse device.
# A Verse-authored creative device that can be placed in a level
voting_ui_device := class(creative_device):
# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void=[]
# TODO: Replace this with your code
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /Verse.org/Assets }
using { /Verse.org/Colors }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
(Widget:widget).Refresh():void=
Widget.SetVisibility(widget_visibility.Hidden)
Widget.SetVisibility(widget_visibility.Visible)
<#> BEGIN STUFF YOU NEED TO CHANGE IN VERSE
#Things you are voting on
candidate_enum:=enum:
cosyvillage
floatingblock
beachresort
(CE:candidate_enum).ToTexture():texture= #FolderName.TextureName
case(CE):
candidate_enum.cosyvillage=>Textures.cosyvillageVote
candidate_enum.floatingblock=>Textures.floatingblockVote
candidate_enum.beachresort=>Textures.beachresortVote
<#> END STUFF YOU NEED TO CHANGE IN VERSE
# A Verse-authored creative device that can be placed in a level
voting_ui_device := class(creative_device):
#The candidates
@editable Candidates : []voting_candidate = array{}
#These start/end the voting
@editable StartVotingTrigger : trigger_device = trigger_device{}
@editable EndVotingTrigger : trigger_device = trigger_device{}
#If false, just waits for the end voting trigger
#If there's a value, it will end after that duration
@editable Duration : ?float = false
#The number of voting candidates to pick when voting
@editable NumToPick : int = 3
@editable Randomize : logic = false
#UI Settings
@editable ShowVoteCount : logic = false #If true, shows the vote count in the UI
var PlayerUIMap : [player]voting_ui = map{}
var PlayerChoiceMap : [player]candidate_enum = map{}
var ActiveCandidates : []candidate_enum = array{}
# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void=
StartVotingTrigger.TriggeredEvent.Subscribe(StartVoting)
StartVoting(mAgent:?agent):void=
DoneVoting.Signal() #ERROR, kill any current voting systems
spawn. HandleStart()
HandleStart()<suspends>:void=
AllCandidates : []candidate_enum = for(C:Candidates). C.Candidate
#ERROR: Slice Already does EndIndex-1
if:
Randomize?
NewCandidates:=Shuffle(AllCandidates).Slice[0,NumToPick]
then. set ActiveCandidates = NewCandidates
else if:
NewCandidates:=AllCandidates.Slice[0,NumToPick]
then. set ActiveCandidates = NewCandidates
else:
Print("ERROR: Failed to generate candidates")
return
var ClassArray : []voting_candidate = array{}
for(AC:ActiveCandidates):
for(C:Candidates). if(C.Candidate=AC). set ClassArray += array. C
#Add UIs to Players
for(Player:GetPlayspace().GetPlayers()):
NewVotingUI:=MakeVotingUI(ClassArray)
if:
set PlayerUIMap[Player] = NewVotingUI
PlayerUI:=GetPlayerUI[Player]
then:
PlayerUI.AddWidget(NewVotingUI.Widget,player_ui_slot{InputMode:=ui_input_mode.All})
#ERROR
NewVotingUI.Widget.Refresh()
spawn. HandleUI(Player,NewVotingUI)
spawn. HandleVoteChange()
#Wait for duration or for the trigger
if(TrueDuration:=Duration?):
race:
Sleep(TrueDuration)
EndVotingTrigger.TriggeredEvent.Await()
else. EndVotingTrigger.TriggeredEvent.Await()
#End Voting
EndVoting()
HandleDuration(VoteUI:voting_ui)<suspends>:void=
if(TrueDuration:=Duration?):
StartTime:=GetSimulationElapsedTime()
loop:
Sleep(1.0)
PassedTime:=GetSimulationElapsedTime()-StartTime
if(PassedTime>=TrueDuration). return
else. VoteUI.PromptTextBlock.SetText(S2M("Vote: {Ceil[TrueDuration-PassedTime] or -1}"))
HandleVoteChange()<suspends>:void=
if(ShowVoteCount?):
race:
DoneVoting.Await()
loop:
var CurrVotes : [candidate_enum]int = map{}
#ERROR: Initialize first
for(AC:ActiveCandidates). if. set CurrVotes[AC] = 0
for(Choice:PlayerChoiceMap):
if. set CurrVotes[Choice] += 1
#Get Current Votes
#Set on each ui
for(UI:PlayerUIMap):
UI.UpdateVotes(CurrVotes)
PlayerChoiceChangedEvent.Await()
HandleUI(Player:player,VoteUI:voting_ui)<suspends>:void=
spawn. HandleDuration(VoteUI)
race:
DoneVoting.Await()
loop:
ChosenCandidate:=VoteUI.CandidateSelectionEvent.Await()
if. set PlayerChoiceMap[Player] = ChosenCandidate
PlayerChoiceChangedEvent.Signal()
VoteUI.SubmitButton.OnClick().Await()
if. PlayerUI:=GetPlayerUI[Player]
then. PlayerUI.RemoveWidget(VoteUI.Widget)
VoteUI.Widget.Refresh() #ERROR
VoteUI.KillEvent.Await() #ERROR 1: KILL AFTERWARDS
DoneVoting : event() = event(){}
PlayerChoiceChangedEvent : event() = event(){}
EndVoting():void=
DoneVoting.Signal() #Kills handleUI, removes player uis
set PlayerUIMap = map{}
TallyVotes()
#Clear data for future use
set PlayerChoiceMap = map{}
TallyVotes():void=
#The key is the candidate, int is num votes
var Ballot : [candidate_enum]int = map{}
for(AC:ActiveCandidates). if. set Ballot[AC] = 0
for(Candidate:PlayerChoiceMap):
if. set Ballot[Candidate] += 1
var HighestVotes : int = -1
var Winners : []candidate_enum = array{}
for(Candidate->NumVotes:Ballot):
if(NumVotes>HighestVotes): #New Winner
set HighestVotes = NumVotes
set Winners = array. Candidate
else if(NumVotes=HighestVotes): #Tie
set Winners += array. Candidate
var Winner : ?candidate_enum = false
#What about when no votes have been submitted?
if(Winners.Length<=0):
Print("No votes found, picking random")
if. FoundWinner:=Shuffle(ActiveCandidates)[0]
then. set Winner = option{FoundWinner}
else:
Print("Picking from {Winners.Length} Tied Winners ")
if. FoundWinner:=Shuffle(Winners)[0]
then. set Winner = option{FoundWinner}
if(TrueWinner:=Winner?):
for(CandidateClass:Candidates):
if(CandidateClass.Candidate = TrueWinner):
CandidateClass.CompletedEvent.Trigger()
return
else. Print("ERROR: Failed to select winner")
voting_candidate := class<concrete>:
@editable Candidate : candidate_enum = candidate_enum.Oranges
@editable Title : string = ""
@editable Description : string = ""
@editable CompletedEvent : trigger_device = trigger_device{}
MakeVotingUI(ActiveCandidates:[]voting_candidate):voting_ui=
KillEvent : event() = event(){}
SelectionEvent : event(candidate_enum) = event(candidate_enum){}
NewVotingUI:=voting_ui:
PromptTextBlock:=text_block{DefaultText:=S2M("VOTE"),DefaultTextColor:=color{R:=1.0,G:=1.0,B:=1.0}}
CandidateWidgets:=for(AC:ActiveCandidates). MakeCandidateWidget(KillEvent,SelectionEvent,AC)
SubmitButton:=button_loud{DefaultText:=S2M("Submit")}
KillEvent:=KillEvent
CandidateSelectionEvent:=SelectionEvent
NewVotingUI.Init()
return NewVotingUI
#This handles the entire UI menu
voting_ui:=class:
var Widget : widget = color_block{}
PromptTextBlock : text_block
CandidateWidgets : []candidate_widget
SubmitButton : button_loud
KillEvent : event()
CandidateSelectionEvent : event(candidate_enum)
Init():void=
set Widget = canvas:
Slots:=array:
canvas_slot:
Widget:=PromptTextBlock
Alignment:=vector2{X:=0.5,Y:=0.5}
Anchors:=anchors{Minimum:=vector2{X:=0.5,Y:=0.1},Maximum:=vector2{X:=0.5,Y:=0.1}}
SizeToContent:=true
canvas_slot:
Alignment:=vector2{X:=0.5,Y:=0.5}
Anchors:=anchors{Minimum:=vector2{X:=0.5,Y:=0.5},Maximum:=vector2{X:=0.5,Y:=0.5}}
SizeToContent:=true
Widget:=stack_box:
Orientation:=orientation.Horizontal #ERROR should be horizontal
Slots:=for(CW:CandidateWidgets). stack_box_slot:
Widget:=CW.Widget
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
Padding:=margin{Left:=50.0,Right:=50.0}
canvas_slot:
Widget:=SubmitButton
Alignment:=vector2{X:=0.5,Y:=0.5}
Anchors:=anchors{Minimum:=vector2{X:=0.5,Y:=0.9},Maximum:=vector2{X:=0.5,Y:=0.9}}
SizeToContent:=true
spawn. HandleSelectionEvent() #ERROR: Forgot
HandleSelectionEvent()<suspends>:void=
race:
KillEvent.Await()
loop:
Candidate:=CandidateSelectionEvent.Await()
for(CW:CandidateWidgets):
if(CW.ActiveCandidate=Candidate): #Currently Selected
CW.BorderColorBlock.SetColor(SelectedColor)
else. CW.BorderColorBlock.SetColor(UnselectedColor)
UpdateVotes(CurrVotes:[candidate_enum]int):void=
for(CW:CandidateWidgets):
CW.VoteButton.SetText(S2M("Vote: {CurrVotes[CW.ActiveCandidate] or 0}"))
#Black
UnselectedColor : color = color{}
SelectedColor : color = color{R:=1.0,G:=1.0}
S2M<localizes>(S:string):message="{S}"
MakeCandidateWidget(KillEvent:event(),CSE:event(candidate_enum),Candidate:voting_candidate):candidate_widget=
NewCandidateWidget:=candidate_widget:
ActiveCandidate:=Candidate.Candidate
KillEvent:=KillEvent
CandidateSelectionEvent:=CSE
BorderColorBlock:=color_block{DefaultColor:=UnselectedColor,DefaultDesiredSize:=vector2{X:=250.0,Y:=300.0}} #ERROR: Predefined Size
InnerColorBlock:=color_block{DefaultColor:=color{B:=0.7}}
TextureBlock:=texture_block{DefaultImage:=Candidate.Candidate.ToTexture(),DefaultDesiredSize:=vector2{X:=150.0,Y:=150.0}}
TitleBlock:=text_block{DefaultText:=S2M(Candidate.Title),DefaultTextColor:=color{R:=1.0,G:=1.0,B:=1.0}}
DescBlock:=text_block{DefaultText:=S2M(Candidate.Description),DefaultTextColor:=color{R:=1.0,G:=1.0,B:=1.0}}
VoteButton:=button_loud{DefaultText:=S2M("VOTE")}
NewCandidateWidget.Init()
return NewCandidateWidget
#Handles individual candidates
candidate_widget:=class:
ActiveCandidate : candidate_enum
InnerPadding : float = 20.0
CenterPadding : float = 25.0
#This kills the event when its no longer needed
KillEvent : event()
CandidateSelectionEvent : event(candidate_enum)
var Widget : widget = color_block{}
#Widgets
BorderColorBlock : color_block
InnerColorBlock : color_block
TextureBlock : texture_block
TitleBlock : text_block
DescBlock : text_block
VoteButton : button_loud
Init():void=
set Widget = overlay:
Slots:=array:
overlay_slot:
Widget:=BorderColorBlock
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
overlay_slot:
Widget:=InnerColorBlock
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Padding:=margin{Top:=InnerPadding,Bottom:=InnerPadding,Left:=InnerPadding,Right:=InnerPadding}
overlay_slot:
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Padding:=margin{Top:=CenterPadding,Bottom:=CenterPadding,Left:=CenterPadding,Right:=CenterPadding}
Widget:=stack_box:
Orientation:=orientation.Vertical
Slots:=array:
stack_box_slot:
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
Widget:=TextureBlock
stack_box_slot:
Padding:=margin{Top:=5.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
Widget:=TitleBlock
stack_box_slot:
Padding:=margin{Top:=5.0}
HorizontalAlignment:=horizontal_alignment.Center
VerticalAlignment:=vertical_alignment.Center
Widget:=DescBlock
stack_box_slot:
Padding:=margin{Top:=10.0}
HorizontalAlignment:=horizontal_alignment.Fill
VerticalAlignment:=vertical_alignment.Fill
Widget:=VoteButton
spawn. HandleButton()
HandleButton()<suspends>:void=
race:
KillEvent.Await()
loop:
VoteButton.OnClick().Await()
CandidateSelectionEvent.Signal(ActiveCandidate)
````Preformatted text`
(I have no idea how verse works) so please if you could explain as if I’m 5 any help is much appreciated thank you for your time)