Bu bölüm, oluşturduğun Verse dosyalarına eklenecek kodun tamamını içerir.
Tam Kod
Bu projede birden çok Verse dosyası bulunur.
-
heartbeat.verse: Dosyanın tam kodunu aşağıda görebilirsin.
-
base_team.verse: Dosyanın tam kodunu aşağıda görebilirsin.
-
hunter_team.verse: Dosyanın tam kodunu aşağıda görebilirsin.
-
prop_team.verse: Dosyanın tam kodunu aşağıda görebilirsin.
-
round_timer.verse: Dosyanın tam kodunu aşağıda görebilirsin.
-
waiting_for_more_players.verse: Dosyanın tam kodunu aşağıda görebilirsin.
heartbeat.verse
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_heart_beat := class(log_channel){}
# Bu mesajlar, bir nesne aracısını, nesne aracısının, kalp atışının görünür olmasını önlemek için hareket etmesi gerektiğinde bir mesajla bilgilendirmek (veya onu gizlemek) için kullanılır.
HeartBeatWarningMessage<localizes>(Time:int):message = "{Time} Saniye İçinde Kalp Atışı. Yürü!"
HeartBeatWarningClear<localizes>:message = ""
# Bu sınıf, kalp atışı için düzenlenebilir özellikleri prop_hunt cihazında kullanıma sundu.
heart_beat := class<concrete>():
Logger:log = log{Channel:=log_heart_beat}
@editable # Bir nesne aracısının, kalp atışı onun konumunu ortaya çıkarmadan önce hareket etmesi gereken saniye cinsinden süre.
MoveTime:float = 15.0
@editable # Kalp atışı uyarısı görünmeden önce kalan saniye. HeartBeatTimer’dan fazla olmamalıdır.
WarningTime:float = 5.0
@editable # Bir kalp atışı Görsel Efekt cihazları dizisi. Bunlardan oyuncu başına bir tane vardır.
AgentVFX:[]heartbeat_vfx = array{}
@editable # Kalp atışı ses efektlerini (SFX) çalmak için kullanılan ses çalar cihazı.
SFXPlayer:radio_device = radio_device{}
# Bu harita, kalp atışı uyarısının görüntülenmesine yönelik Kullanıcı Arayüzünü her bir nesne aracısıyla ilişkilendirir.
var WarningUI:[agent]heartbeat_warning_ui = map{}
# Ses Efekti cihazını yönetebilmemiz için kaç oyuncunun aktif bir kalp atışına sahip olduğunu takip eder.
var NumberOfHeartBeats:int = 0
# Aracı için kalp atışı Kullanıcı Arayüzünü ayarlar.
SetUpUI(PropAgent:agent):void =
if:
not WarningUI[PropAgent]
AsPlayer := player[PropAgent]
PlayerUI := GetPlayerUI[AsPlayer]
then:
UIData:heartbeat_warning_ui = heartbeat_warning_ui{}
UIData.CreateCanvas()
PlayerUI.AddWidget(UIData.Canvas, player_ui_slot{ZOrder := 1})
if (set WarningUI[PropAgent] = UIData) {}
# Belirtilen oyuncu için kalp atışı Görsel Efekti ve Ses Efektini etkinleştirir.
Enable(PropAgent:agent, HeartBeatVFXData:heartbeat_vfx):void =
if:
# Nesne aracısının sahnedeki konumunu bulmak için kullanılan karakteri al.
Character := PropAgent.GetFortCharacter[]
then:
# Kalp atışı Görsel Efektinin konumunu nesne aracısının konumuna ayarla.
HeartBeatVFXData.Activate(Character.GetTransform())
# Kalp atışı sayısını artır, ayrıca bu, çalan ilk kalp atışıysa onu başlatmak için sesi çalmamız gerekir.
set NumberOfHeartBeats += 1
if (NumberOfHeartBeats = 1) then SFXPlayer.Play()
# Nesne aracısını ses çalar cihazına kaydet, böylece kalp atışı sesi, o konumdan çalınabilecektir.
SFXPlayer.Register(PropAgent)
else:
Logger.Print("Karakter, Dizin veya HeartBeatVFXData bulunamadı. Kalp atışı başlatılamıyor")
# Belirtilen nesne aracısı için kalp atışı Görsel Efekti ve Ses Efektini temizler.
Disable(PropAgent:agent, HeartBeatVFXData:heartbeat_vfx):void =
Logger.Print("Kalp atışı devre dışı bırakılıyor.")
# Görsel Efekt görsellerini devre dışı bırak.
HeartBeatVFXData.Deactivate()
# Ses çalar cihazından nesne aracısının kaydını sil; bunun sonucunda kalp atışı sesi duracaktır.
SFXPlayer.Unregister(PropAgent)
# Kalp atışı sayacını azalt. Bu sayaç hiçbir zaman 0’ın altına düşmemelidir.
set NumberOfHeartBeats -= 1
if (NumberOfHeartBeats < 0) then set NumberOfHeartBeats = 0
# Tüm nesne aracıları için tüm kalp atışı Görsel Efektleri ve Ses Efektlerini temizler.
DisableAll():void =
Logger.Print("Tüm kalp atışları devre dışı bırakılıyor.")
# Tüm Görsel Efektlerin üzerinden geç ve bunları 0,0,0’a taşı.
for (HeartBeatVFXDevice : AgentVFX):
HeartBeatVFXDevice.Deactivate()
# Kalp atışı sesinden tüm oyuncuların kaydını sil.
SFXPlayer.UnregisterAll()
# Kalp atışı sayacını 0 olacak şekilde yeniden başlat
set NumberOfHeartBeats = 0
# heartbeat_warning_ui sınıfı, oyuncu başına Kullanıcı Arayüzü tuvali ve text_block’unun takip edilmesine yönelik bir veri yapısının yanı sıra yeni bir kalp atışı uyarısı Kullanıcı Arayüzü tuvali oluşturulmasına yönelik fonksiyonu içerir.
heartbeat_warning_ui := class:
var Canvas:canvas = canvas{}
var Text:text_block = text_block{}
# Uyarı mesajı için Kullanıcı Arayüzü tuvalini oluşturur.
CreateCanvas():void =
set Text = text_block{DefaultTextColor := NamedColors.White, DefaultShadowColor := NamedColors.Black}
set Canvas = canvas:
Slots := array:
canvas_slot:
Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.75}, Maximum := vector2{X := 0.5, Y := 0.75}}
Offsets := margin{Top := 0.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
Alignment := vector2{X := 0.5, Y := 1.0}
SizeToContent := true
Widget := Text
# heartbeat_vfx sınıfı, Görsel Efektin kökünün ve oyuncu başına vfx_spawner_device objelerinin takip edilmesine yönelik bir veri yapısının yanı sıra Görsel Efektin bir konuma ayarlanmasına veya sıfırlanmasına yönelik fonksiyonları içerir.
heartbeat_vfx := class<concrete>:
@editable # Her kalp atışı için Görsel Efekt cihazı.
VFXDevice:vfx_spawner_device = vfx_spawner_device{}
# Bu ofset, kalp atışını, bir nesne aracısının başının üzerine konumlandırmak için kullanılır.
HeartBeatVFXOffset:vector3 = vector3{X := 0.0, Y := 0.0, Z := 110.0}
# Kalp atışı Görsel Efektinin konumunu ayarlar ve ardından Görsel Efekti etkinleştirir.
Activate(Transform:transform):void =
VFXPosition := Transform.Translation + HeartBeatVFXOffset
if (VFXDevice.TeleportTo[VFXPosition, Transform.Rotation]):
VFXDevice.Enable()
# Görsel Efekti devre dışı bırakarak kalp atışı görsellerini gizler.
Deactivate():void =
VFXDevice.Disable()
base_team.verse
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_team := class(log_channel){}
# Bu sınıf, deneyimdeki farklı takımlar için gereken cihazları tanımlar.
# Bu sınıf soyut olduğundan tek başına kullanılamaz. Başka bir sınıf tarafından devralınması gerekir.
base_team := class<abstract>:
Logger:log = log{Channel:=log_team}
@editable # Takıma bir oyuncu ayarlamak için kullanılır.
ClassSelector:class_and_team_selector_device = class_and_team_selector_device{}
@editable # Takımdaki aracılara puan vermek için kullanılır.
ScoreManager:score_manager_device = score_manager_device{}
@editable # Takım görevi başlığını görüntülemek için kullanılır.
TeamTitle:hud_message_device = hud_message_device{}
@editable # Takım görevi açıklamasını görüntülemek için kullanılır.
TeamDescription:hud_message_device = hud_message_device{}
@editable # Takım üyesi (nesne takımı) veya düşman (avcı takımı) avlanma olaylarına bağlanmak için kullanılır.
TeamManager:team_settings_and_inventory_device = team_settings_and_inventory_device{}
# Bu, takımdaki aracıların bir dizisidir.
var TeamAgents<private>:[]agent = array{}
# Bu olayın işareti, TeamAgents dizisi boşaldığında verilir (raundun sonuna işaret eder).
TeamEmptyEvent:event() = event(){}
# Geçerli TeamAgents dizisini döndürür.
# Bu gereklidir, çünkü TeamAgents dizisi özel olduğundan diğer sınıflar ona doğrudan erişemez.
GetAgents()<decides><transacts>:[]agent =
TeamAgents
# TeamAgents dizisinin boyutunu döndür
# Bunun için bir fonksiyon gerekir, çünkü TeamAgents dizisi özel olduğundan diğer sınıflar ona doğrudan erişemez.
Count()<transacts>:int =
TeamAgents.Length
# Bir aracının TeamAgents dizisindeki bir dizini döndürür, aksi takdirde başarısız olur.
FindOnTeam(Agent:agent)<decides><transacts>: int =
Index := TeamAgents.Find[Agent]
# Aracıyı takıma ayarla ve oyuncuyu bilgilendir.
InitializeAgent(Agent:agent):void =
AddAgentToTeam(Agent)
ClassSelector.ChangeTeamAndClass(Agent)
DisplayTeamInformation(Agent)
# TeamAgents’a bir aracı ekle.
AddAgentToTeam(AgentToAdd:agent):void =
if (not FindOnTeam[AgentToAdd]):
Logger.Print("Aracı takıma ekleniyor.")
set TeamAgents += array{AgentToAdd}
# Oyuncuya hangi takımda olduğunu göstermek için Gösterge Paneli mesajı cihazlarını etkinleştirir.
DisplayTeamInformation(Agent:agent):void =
TeamTitle.Show(Agent)
TeamDescription.Show(Agent)
# Bir aracı maçtan ayrıldığında, onu TeamAgents dizisinden kaldır ve raundun sonunu kontrol et.
EliminateAgent(Agent:agent)<suspends>:void =
Sleep(0.0) # Devam etmeden önce oyuncunun yeniden çıkarılmasını sağlamak için 1 oyun tikini geciktirme.
RemoveAgentFromTeam(Agent)
# TeamAgents’tan bir aracıyı kaldır.
# Kaldırılan aracı sonuncuysa, TeamEmptyEvent’e sinyal ver.
RemoveAgentFromTeam(AgentToRemove:agent):void =
set TeamAgents = TeamAgents.RemoveAllElements(AgentToRemove)
Logger.Print("Takımda kalan aracıları {Count()}.")
if (Count() < 1):
Logger.Print("Takımda aracı kalmadı. Raunt sonlandırılıyor.")
TeamEmptyEvent.Signal()
hunter_team.verse
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Simulation }
# base_team sınıfından devralan hunter_team sınıfı, avcı takımı ve aracıları ile ilgili cihaz tanımları ve fonksiyonlarını içerir.
hunter_team := class<concrete>(base_team):
@editable # Her rauntta, her n adet oyuncu için bir avcı aracısı oluşturulur. Örnek: HunterTeamPerNumberOfPlayers = 5.0, 5 oyuncu başına 1 anlamına gelir. Oyuncu sayısı = 6 ise 2 avcı aracısı oluşturulur.
HunterAgentPerNumberOfPlayers:float = 5.0 # En az 1 nesne aracısının oluşturulmasını sağlamak için minimum 1,1 uygulanır.
@editable # Avcı aracıları çıkarılmadan önceki saniye sayısı. Bu sayede nesne aracılarının saklanmak için fazladan zamanı olur.
SpawnDelay:float = 15.0
@editable # Bir avcı aracısının, bir nesne aracısını avlama karşılığında alacağı maksimum taban puan. Bu puanlar kalan nesne aracıları sayısına bölünür.
MaxEliminationScore:int = 5000
@editable # Süreölçer cihazı, nesnelere saklanmaları için bir ek süre vermek amacıyla kullanılır.
WaitTimer:timer_device = timer_device{}
# Aracıyı, bir avcı aracısı olarak ayarla.
InitializeAgent<override>(NewHunterAgent:agent):void =
Logger.Print("Yeni bir avcı aracısı ayarlanıyor.")
(super:)InitializeAgent(NewHunterAgent)
# Bir avcı aracısı maçtan ayrıldığında, onu HunterAgents dizisinden kaldır ve raunt sonu olup olmadığını kontrol et.
# Bu fonksiyonu geçersiz kıldığımızı, çünkü burada nesne takımı için yaptığımız gibi ekstra veri aktarmamıza gerek olmadığını unutma.
EliminateAgent<override>(HunterAgent:agent)<suspends>:void =
Logger.Print("Avcı aracısı avlandı.")
(super:)EliminateAgent(HunterAgent)
prop_team.verse
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
# Bu mesaj, bir raunt sırasında tüm oyunculara kalan nesne sayısını yazdırmak için kullanılır.
PropAgentsRemainingMessage<localizes>(Count:int):message = "{Count} Prop(s) Remaining"
# base_team sınıfından devralan prop_team sınıfı, nesne takımı ve aracıları ile ilgili cihaz tanımları ve fonksiyonlarını içerir.
# Dikkat çekici bir şekilde, bir nesne aracısının kalp atışı davranışı bu sınıfta bulunabilir.
prop_team := class<concrete>(base_team):
@editable # Bir nesne aracısının saniye başına aldığı puan.
ScorePerSecond:int = 10
@editable # Bir nesne aracısının kalp atışı süreölçerini sıfırlamak için hareket etmesi gereken minimum mesafe.
MinimumMoveDistance:float = 100.0
@editable # Bir nesneye puan vermek için kullanılan süreölçer cihazı.
ScoreTimer:timer_device = timer_device{}
@editable # Bu takip cihazı kalan nesneleri ekranda görüntülemek için kullanılır.
PropsRemainingTracker:tracker_device = tracker_device{}
@editable # heart_beat sınıfından özellikleri al.
HeartBeat:heart_beat = heart_beat{}
# Aracıyı, bir nesne aracısı olarak ayarla ve kalp atışı uyarısı Kullanıcı Arayüzünü ata.
InitializeAgent<override>(NewPropAgent:agent):void =
Logger.Print("Yeni bir nesne aracısı ayarlanıyor.")
(super:)InitializeAgent(NewPropAgent)
# PropScoreTimer tamamlandığında tüm nesne aracılarına puan ver. PropInstigator, olay bağlanması için gereklidir, ancak kullanılmaz.
OnPropsScore(PropInstigator:?agent):void =
if (PropAgents := GetAgents[]):
for (PropAgent : PropAgents):
ScoreManager.Activate(PropAgent)
# Bir nesne aracısı avlandığında ve maçtan ayrıldığında, onu PropAgents dizisinden kaldır ve raunt sonu olup olmadığını kontrol et.
# Bunun geçersiz kılma olmadığını, çünkü tüm oyuncuları, nesnelerin kalan mesajını güncellemek için fonksiyona aktarıyor olduğumuzu unutma.
EliminateAgent<override>(PropAgent:agent)<suspends>:void =
Logger.Print("Nesne aracısı avlandı.")
(super:)EliminateAgent(PropAgent)
# # Nesnelerin kalan sayısını güncelle.
UpdatePropsRemainingTracker()
# Kalan nesne sayısını gösteren takip cihazının değerini günceller.
UpdatePropsRemainingTracker():void =
PropsRemainingTracker.SetValue(Count())
# Nesne aracısı hareket etmeyi durdurursa nesne aracısının MinimumMoveDistance’ı aştığını ve kalp atışı süreölçerinin tamamlandığını mı yoksa nesne aracısının avlandığını mı görmek için yarış.
RunPropGameLoop(PropAgent:agent)<suspends>:void =
Logger.Print("Nesne aracısı oyun döngüsü başlatılıyor.")
# Nesne aracısı avlanana veya oyuncu oturumdan ayrılana kadar nesne davranışı üzerinden sonsuza kadar döngü halinde çalıştır.
race:
PropAgent.AwaitNoLongerAProp()
loop:
# Nesne aracısı minimum mesafeden daha az hareket edene kadar bekle, ardından ilerle.
PropAgent.AwaitStopMoving(MinimumMoveDistance)
# Nesne aracısı minimum mesafenin ötesine geçene kadar kalp atışı için geri sayım yap ve ardından kalp atışını süresiz olarak çal.
race:
PropAgent.AwaitStartMoving(MinimumMoveDistance)
block:
CountdownTimer(PropAgent)
PropAgent.StartHeartbeat()
Sleep(0.0) # Yarış tamamlandığında (nesne aracısı hareket ettiğinde), döngüyü yeniden başlat.
# Nesne aracısı artık PropAgents dizisinin bir parçası olmayana kadar döngü halinde çalıştır. Kaldırma, nesne aracısının elenmesi ve avcıya dönüştürülmesi veya oyuncunun oturumdan ayrılması halinde gerçekleşir.
(PropAgent:agent).AwaitNoLongerAProp()<suspends>:void =
loop:
if (not FindOnTeam[PropAgent]):
Logger.Print("Nesne aracısı davranışı iptal ediliyor.")
break
Sleep(0.0) # Bir sonraki oyun tikine ilerle.
# Aracı, MinimumDistance’tan daha az hareket edene kadar döngü içinde olur.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void =
Logger.Print("Aracının minimum mesafeden daha az hareket edip etmediği kontrol ediliyor.")
# Aracının başlangıç konumunu, aracının sahnedeki karakterinden al.
if (Tracked := PropAgent.GetFortCharacter[]):
var StartPosition:vector3 = Tracked.GetTransform().Translation
loop:
Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al.
NewPosition := Tracked.GetTransform().Translation
# Yeni konumun başlangıç konumundan itibaren mesafesi MinimumDistance değerinden azsa, aracı hareket etmemiş demektir ve bu durumda döngüyü kırarız.
if (Distance(StartPosition, NewPosition) < MinimumDistance):
Logger.Print("Aracı minimum mesafeden daha az hareket etti.")
break
# Aksi takdirde, oyuncunun yeni konumdan hareket ettiğinden emin olmak için StartPosition’ı sıfırlarız.
else:
set StartPosition = NewPosition
# Aracı MinimumDistance’tan daha fazla hareket edene kadar döngü içinde olur.
(PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void =
Logger.Print("Aracının minimum mesafeden daha ileriye hareket edip etmediği kontrol ediliyor.")
# Aracının başlangıç konumunu, aracının sahnedeki karakterinden al.
if (Tracked := PropAgent.GetFortCharacter[]):
StartPosition:vector3 = Tracked.GetTransform().Translation
loop:
Sleep(0.0) # Bir sonraki oyun tikinde aracının konumunu al.
NewPosition := Tracked.GetTransform().Translation
# Yeni konumun başlangıç konumundan itibaren mesafesi MinimumDistance’tan büyük veya ona eşitse aracı hareket etmiş demektir ve bu sebeple döngüyü kırarız.
if (Distance(StartPosition, NewPosition) >= MinimumDistance):
Logger.Print("Aracı minimum mesafeden daha fazla veya ona eşit bir mesafe kadar hareket etti.")
break
# HeartBeatWarningTime’ın başlaması gereken zamana kadar gecikme yapar. Ardından, HeartBeatWarningTime’a göre geri sayım yapar ve geri sayım metnini ayarlar. Ertelendiğinde metni temizler.
CountdownTimer(PropAgent:agent)<suspends>:void =
Logger.Print("Kalp atışı geri sayımı başlatılıyor.")
if (UIData := HeartBeat.WarningUI[PropAgent]):
Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Uyarı görünmeden önceki süre boyunca uyu.
Logger.Print("Kalp atışı uyarısı başlatılıyor.")
var WarningTimeRemaining:int = 0
if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {}
# Erteleme, fonksiyon tamamlandığında veya iptal edilmesi halinde (örneğin bir yarışı kaybederse) gerçekleşir.
# Dolayısıyla bu durumda, geri sayım bittiğinde veya nesne aracısının geri sayım bitmeden hareket etmesi halinde uyarı metni temizlenir.
defer:
UIData.Text.SetText(HeartBeatWarningClear)
# Uyarı metnini kalan süreye ayarla, bir saniye bekle ve ardından kalan süreyi azalt. Geri sayım tamamlanırsa döngüyü kır.
loop:
Logger.Print("{WarningTimeRemaining} saniye içinde kalp atışı.")
UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining))
Sleep(1.0)
set WarningTimeRemaining -= 1
if (WarningTimeRemaining <= 0):
break
else:
Logger.Print("UIData bulunamadı.")
# Kalp atışı Görsel Efekti ile Ses Efektini açar. Ertelenene dek sonsuza kadar bekler, ardından kalp atışı Görsel Efekti ile Ses Efektini devre dışı bırakır.
(PropAgent:agent).StartHeartbeat()<suspends>:void =
Logger.Print("Kalp atışı çıkarılıyor.")
# Kalp atışı verilerini kaydet; böylece PropAgent yok edildikten veya oyundan ayrıldıktan sonra onları ertelemede aktarabiliriz.
var HeartBeatVFXData:heartbeat_vfx = heartbeat_vfx{}
if:
# PropAgents dizisindeki nesne aracısının dizinini alarak daha sonra ilgili kalp atışı Görsel Efekt aktörüne erişebilirsin.
Index := FindOnTeam[PropAgent]
set HeartBeatVFXData = HeartBeat.AgentVFX[Index]
then:
HeartBeat.Enable(PropAgent, HeartBeatVFXData)
# Bu fonksiyon, nesne aracısının hareket etmesi, avlanması veya oyuncunun oturumdan ayrılması nedeniyle iptal edildiğinde kalp atışını devre dışı bırak.
defer:
HeartBeat.Disable(PropAgent, HeartBeatVFXData)
Sleep(Inf) # Yarış tamamlanana kadar uyumayı bırakma.
round_timer.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_round_timer_device := class(log_channel){}
# Belirtilen aralıklar arasındaki değerlere izin veren bir tamsayı. Bu tür, player_ui_slot.ZOrder için gereklidir.
round_int_clamped := type{_X:int where 0 <= _X, _X <= 2147483647}
# Bu mesaj, bir raundun sona ermesi için kalan süreyi yazdırmak için kullanılır.
TimeRemainingMessage<localizes>(Minutes:string, Seconds:string):message = "{Minutes}:{Seconds}"
<#
Bu sınıf, raunt süresini yönetmek ve süreyi ekranda görüntülemek için gereken tüm mantığı içerir.
Raundu fiilen bitirmek için bir round_settings_device ile bu cihazı kullanabilirsin.
Bu cihaz, süreyi, süreölçer kullanmadan yönetir.
Bu sınıfı kullanmak için:
1) Dosyayı projene ekle.
2) Araç çubuğundaki Verse menüsünden Verse Kodunu derle.
3) Cihazı, adanın, İçerik Tarayıcısında yer alan İçerik/Kreatif Cihazları klasöründen adanın içine sürükle.
4) Waiting_for_more_players sınıfını, aşağıdakiyle başka bir Verse koduna ekle:
@editable
RoundTimer:round_timer = round_timer{}
5) Araç çubuğundaki Verse menüsünden Verse Kodunu derle.
6) 3. adımda yaptığın cihazı Verse cihazına bağla.
7) Raunt süreölçerini aşağıdaki Verse ile başlat:
RoundTimer.Start()
8) Süreölçeri eşdeğer fonksiyonlarla yeniden başlat veya durdur.
9) Süreölçerin şununla başlamasını bekle:
RoundTimer.AwaitStart()
10) Süreölçerin şununla bitmesini bekle:
RoundTimer.AwaitEnd()
Oyun raundunu fiilen sonlandırmak için bir round_settings_device cihazında EndRound fonksiyonunu çağır.
#>
round_timer := class(creative_device):
Logger:log = log{Channel:=log_prop_hunt_device}
@editable # Bir raundun dakika cinsinden aldığı zaman.
RoundTimeInMinutes:float = 5.0
@editable # Süreölçer Kullanıcı Arayüzünün ekrandaki yatay ve dikey konumu. X 0-1 sol-sağ ve Y 0-1 ise üst-alttır.
UIPosition:vector2 = vector2{X:= 0.98, Y:=0.13}
@editable # Süreölçer Kullanıcı Arayüzünün ekrandaki yatay ve dikey konumu. X 0-1 sol-sağ ve Y 0-1 ise üst-alttır.
UIAlignment:vector2 = vector2{X := 1.0, Y := 0.0}
@editable # Diğer Kullanıcı Arayüzü öğeleriyle karşılaştırıldığında Kullanıcı Arayüzünün ZOrder’ı.
UIZOrder:round_int_clamped = 4
# Raunt başlatıldığında işareti verilir.
RoundStarted:event() = event(){}
# Raunt sonlandırılmak üzere olduğunda işareti verilir.
RoundEndedEvent:event() = event(){}
# Bu harita, sürenin görüntülenmesine yönelik metin kutusunu her bir oyuncuyla ilişkilendirir.
var TimeRemainingTextBlocks:[player]text_block = map{}
# Raundun tamamlanması için kalan süre (tamsayı olarak).
var TimeRemainingInSeconds:int = 0
Raunt süreölçeri başlatılana kadar bekler.
AwaitStart()<suspends>:void =
RoundStarted.Await()
Logger.Print("Raunt süreölçeri başlatıldı.")
# Raunt süreölçerini başlatmak için kullanılır.
Start():void =
Logger.Print("Raunt süreölçeri başlatılıyor.")
RoundStarted.Signal()
set TimeRemainingInSeconds = GetRoundTimeInSeconds()
spawn{ Running() }
# Süreölçeri RoundTime’a sıfırlar
Restart():void =
Logger.Print("Raunt süreölçeri yeniden başlatılıyor.")
set TimeRemainingInSeconds = GetRoundTimeInSeconds()
# Süreölçer mantığını çalıştırır.
Running()<suspends>:void =
Logger.Print("Raunt süreölçeri çalışıyor.")
loop:
UpdateTimeUI()
Sleep(1.0)
# TimeRemaining’i 1 saniye azalt, ardından sürenin dolup dolmadığını kontrol et. Süre dolmuşsa raundu sonlandır.
set TimeRemainingInSeconds -= 1
if (TimeRemainingInSeconds < 0):
Stop()
break
# Süreölçeri durdurur ve raundu bitirir.
Stop():void =
Logger.Print("Raunt süreölçeri sonlandırılıyor.")
# Raundu sonlandırmak için sahnede kalan oyunculardan bir oyuncu alırız.
Players:[]player = GetPlayspace().GetPlayers()
if (Instigator := Players[0]):
RoundEndedEvent.Signal()
# Raunt süreölçeri sonlanmak üzere olana kadar bekler.
AwaitEnd()<suspends>:void =
RoundEndedEvent.Await()
Logger.Print("Raunt süreölçeri sonlandırıldı.")
# Dakika cinsinden bir zaman değeri kabul eder ve değeri saniye cinsinden döndürür.
GetRoundTimeInSeconds():int =
var InSeconds:int = 0
if (set InSeconds = Round[RoundTimeInMinutes * 60.0]) {}
InSeconds
# Süreölçer tamamlandığında kalan süreyi güncelle ve sürenin dolup dolmadığını kontrol et.
UpdateTimeUI():void =
# Dakikayı, kalan olmadan TimeRemainingInSeconds/60 olarak ayarla.
var Minutes:int = 0
if (set Minutes = Floor(TimeRemainingInSeconds / 60)) {}
# Saniyeyi TimeRemainingInSeconds/60’ın kalanı olarak ayarla.
var Seconds:int = 0
if (set Seconds = Mod[TimeRemainingInSeconds, 60]) {}
# Dakika ve Saniyeyi dizelere dönüştür.
MinutesAsString := string("{Minutes}")
# Saniye < 10 ise değerin önüne 0 eklememiz gerekir ki :# yerine :0# olarak görünsün
SecondsAsString := if (Seconds < 10) then Join(array{string("{0}"),string("{Seconds}")},string()) else string("{Seconds}")
# Tüm oyuncuların üzerinden geç, bunların bir TimeRemainingTextBlock içerip içermediğini kontrol et ve içermiyorlarsa onlara bir tane ver. Ardından metni güncelle.
Players:[]player = GetPlayspace().GetPlayers()
for (Player : Players):
var TextBlock:text_block = text_block{}
if (set TextBlock = TimeRemainingTextBlocks[Player]) {}
else:
set TextBlock = SetUpTimeRemainingUI(Player)
TextBlock.SetText(TimeRemainingMessage(MinutesAsString, SecondsAsString))
# Bir oyuncuyu kabul eder, ardından onun ekranına yuvarlak bir zaman Kullanıcı Arayüzü tuvali ekler ve TimeRemainingTextBlock’larını daha sonra güncellemek üzere saklar.
SetUpTimeRemainingUI(Player:player):text_block =
Logger.Print("Oyuncuya raunt süreölçeri Kullanıcı Arayüzü ekleniyor.")
# Bu, kalan süre metnini ekrana yazdıran text_block’tur.
TextBlock:text_block = text_block:
DefaultTextColor := NamedColors.White
DefaultShadowColor := NamedColors.Black
if (PlayerUI := GetPlayerUI[Player]):
if (set TimeRemainingTextBlocks[Player] = TextBlock) {}
# Bu, text_block’u tutan ve ekranda konumlandıran tuvaldir.
Canvas := canvas:
Slots := array:
canvas_slot:
Anchors := anchors{Minimum := UIPosition, Maximum := UIPosition}
Offsets := margin{Top := 0.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
Alignment := UIAlignment
SizeToContent := true
Widget := TextBlock
# Tuval oyuncuya atanır.
PlayerUI.AddWidget(Canvas, player_ui_slot{ZOrder := UIZOrder})
# text_block, haritaya kaydedilebilmesi ve daha sonra zaman geçtikçe güncellenebilmesi için döndürülür.
return TextBlock
waiting_for_more_players.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_waiting_for_more_players_device := class(log_channel){}
# Belirtilen aralıklar arasındaki değerlere izin veren bir tamsayı. Bu tür, player_ui_slot.ZOrder için gereklidir.
waiting_int_clamped := type{_X:int where 0 <= _X, _X <= 2147483647}
# Bu mesaj, bir raundun başlayabilmesi için gerekli olan oyuncu sayısını yazdırmak için kullanılır.
WaitingForMorePlayersMessage<localizes>(Count:int):message = "Waiting for {Count} more Player(s)"
# Bu sınıf, raundun başlatılabilmesi için kaç oyuncuya ihtiyaç duyulduğunu göstermek içindir.
waiting_for_more_players_ui := class:
var Canvas:canvas
var TextBlock:text_block
<#
Bu sınıf, minimum bir oyuncu sayısı belirlenmesi ve raundu başlatılması için yeterli oyuncu olup olmadığının kontrol edilmesine ilişkin mantığın tamamını içerir.
Bu sınıfı kullanmak için:
1) Dosyayı projene ekle.
2) Araç çubuğundaki Verse menüsünden Verse Kodunu derle.
3) Cihazı, adanın, İçerik Tarayıcısında yer alan İçerik/Kreatif Cihazları klasöründen adanın içine sürükle.
4) Bu cihazın “WaitingForMorePlayersTimer” özelliğine bir süreölçer cihazı bağla.
5) Waiting_for_more_players sınıfını, aşağıdakiyle başka bir Verse koduna dahil et:
@editable
WaitingForMorePlayers:waiting_for_more_players = waiting_for_more_players{}
6) Araç çubuğundaki Verse menüsünden Verse Kodunu derle.
7) 3. adımda yaptığın cihazı Verse cihazına ve 6. adımda kullanıma sunduğun özelliğe bağla.
8) Onu bir oyuncuya ileterek CheckForMinimumNumberOfPlayers fonksiyonlarını bekle. Örneğin:
Players = GetPlayspace().GetPlayers()
CheckForMinimumNumberOfPlayers(Players)
9) IslandSettings’de Oyun Başlangıcı Geri Sayımını 0,0’a ayarla.
#>
waiting_for_more_players := class(creative_device):
Logger:log = log{Channel:=log_waiting_for_more_players_device}
@editable # Bir raundun başlayabilmesi için maçta gerekli olan minimum oyuncu sayısı.
MinimumNumberOfPlayers:int = 2
@editable # Süreölçer Kullanıcı Arayüzünün ekrandaki yatay ve dikey konumu. X 0-1 sol-sağ ve Y 0-1 ise üst-alttır.
UIPosition:vector2 = vector2{X:= 0.5, Y:=0.4}
@editable # Süreölçer Kullanıcı Arayüzünün ekrandaki yatay ve dikey konumu. X 0-1 sol-sağ ve Y 0-1 ise üst-alttır.
UIAlignment:vector2 = vector2{X := 0.5, Y := 0.5}
@editable # Diğer Kullanıcı Arayüzü öğeleriyle karşılaştırıldığında Kullanıcı Arayüzünün ZOrder’ı.
UIZOrder:waiting_int_clamped = 3
@editable # Bu süreölçer, oyuncuların maça katılmasını bekledikten sonra raundun başlaması için geri sayım yapmak amacıyla kullanılır.
WaitingForMorePlayersTimer:timer_device = timer_device{}
# Bu harita, bir raundun başlatılması için gerekli olan oyuncu sayısının görüntülenmesine yönelik Kullanıcı Arayüzü tuvalini her bir oyuncuyla ilişkilendirir.
var WaitingForMorePlayersUI:[player]?waiting_for_more_players_ui = map{}
# Raundu başlatmak için, yeterli oyuncu olup olmadığını kontrol et. Yeterli oyuncu yoksa, oyuncu sayısı >= MinimumNumberOfPlayers olana kadar bekle.
WaitForMinimumNumberOfPlayers(Players:[]player)<suspends>:[]player =
Logger.Print(“Raundun başlaması için yeterli oyuncu olup olmadığı bekleniyor.")
# Daha fazla oyuncu katıldıkça değiştirebilmem için yeni bir değişken oluşturuyorum. Onu, fonksiyona aktarılan bir oyuncular dizisiyle başlatıyorum.
var PlayersWaiting:[]player = Players
# Oyuncu sayısı raundu başlatmak için gereken minimum sayıdan azsa...
if (PlayersWaiting.Length < MinimumNumberOfPlayers):
loop: # Oyuncu sayısı gereken minimum sayıya eşit veya ondan daha fazla olana kadar döngü halinde çalıştır.
Logger.Print(Raundun başlaması için "{PlayersWaiting.Length}/{MinimumNumberOfPlayers} oyuncuya ihtiyaç var.")
# Daha fazla oyuncu bekleniyor Kullanıcı Arayüzünü güncelle.
DisplayWaitingForMorePlayers(PlayersWaiting)
Sleep(2.0) # Maça daha fazla oyuncunun katılıp katılmadığını görmek için bekle, ardından raundu başlatmak için yeterli oyuncu olup olmadığını kontrol et.
set PlayersWaiting = GetPlayspace().GetPlayers()
if (PlayersWaiting.Length >= MinimumNumberOfPlayers):
# Artık yeterli oyuncu varsa daha fazla oyuncu bekleniyor Kullanıcı Arayüzünü temizle,
Logger.Print(Rauntta "{PlayersWaiting.Length}/{MinimumNumberOfPlayers} oyuncu var, raundun başlamasına hazırlanılıyor.")
ClearWaitingForMorePlayers()
# Ardından döngüden çık.
break
# raunt başlama geri sayımını başlat ve geri sayım tamamlanana kadar bekle.
WaitingForMorePlayersTimer.Start()
WaitingForMorePlayersTimer.SuccessEvent.Await()
Logger.Print("Raunt başlatılıyor.")
# Oturumdaki oyuncuların listesini döndür.
return PlayersWaiting
# Her oyuncu için "Daha fazla oyuncu bekleniyor" Kullanıcı Arayüzü mesajını görüntüler (bu mesajın henüz görüntülenmediği oyuncular için). Tüm oyuncular için oyuncu sayacını günceller.
DisplayWaitingForMorePlayers(Players:[]player):void =
PlayersNeededCount := MinimumNumberOfPlayers - Players.Length
Logger.Print("Rauntta {Players.Length} oyuncu var, {PlayersNeededCount} oyuncunun daha katılması bekleniyor.")
for (Player : Players):
# Oyuncunun bir WaitingForMorePlayersUI’sı varsa TextBlock’u al ve metnin, raundun başlatılması için gereken doğru oyuncu sayısını göstermesi için metni yenile.
if (UIData := WaitingForMorePlayersUI[Player]?):
UIData.TextBlock.SetText(WaitingForMorePlayersMessage(PlayersNeededCount))
# Aksi halde, oyuncu için bir WaitingForMorePlayersUI oluştur.
else:
SetUpWaitingForMorePlayersUI(Player, PlayersNeededCount)
# Bir oyuncu ile player_ui’yi kabul eder ve onların ekranına bir daha fazla oyuncu bekleniyor kullanıcı arayüzü tuvali ekler.
SetUpWaitingForMorePlayersUI(Player:player, PlayersNeededCount:int):void =
Logger.Print("'Daha fazla oyuncu bekleniyor' Kullanıcı Arayüzü oluşturuluyor.")
if (PlayerUI := GetPlayerUI[Player]):
# Bu, daha fazla oyuncu bekleniyor metnini ekrana yazdıran text_block’tur.
TextBlock:text_block = text_block:
DefaultText := WaitingForMorePlayersMessage(PlayersNeededCount)
DefaultTextColor := NamedColors.White
DefaultShadowColor := NamedColors.Black
# Bu, text_block’u tutan ve ekranda konumlandıran tuvaldir.
Canvas := canvas:
Slots := array:
canvas_slot:
Anchors := anchors{Minimum := UIPosition, Maximum := UIPosition}
Offsets := margin{Top := 0.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
Alignment := UIAlignment
SizeToContent := true
Widget := TextBlock
# Tuval oyuncuya atanır.
PlayerUI.AddWidget(Canvas, player_ui_slot{ZOrder := UIZOrder})
# Text_block haritaya kaydedilir, böylece daha sonra oyuna daha fazla oyuncu katıldıkça metni güncelleyebiliriz.
if (set WaitingForMorePlayersUI[Player] = option{ waiting_for_more_players_ui{Canvas := Canvas, TextBlock := TextBlock} }) {}
# Her oyuncu için "Daha fazla oyuncu bekleniyor" Kullanıcı Arayüzü mesajını kaldırır (bu mesajın görüntülendiği oyuncular için).
ClearWaitingForMorePlayers():void =
Logger.Print("'Daha fazla oyuncu bekleniyor' Kullanıcı Arayüzü temizleniyor.")
for (Player -> UIData : WaitingForMorePlayersUI):
if:
PlayerUI := GetPlayerUI[Player]
Canvas := UIData?.Canvas
set WaitingForMorePlayersUI[Player] = false
then:
PlayerUI.RemoveWidget(Canvas)