Hammer'da input ve output: bir butonu kapıya bağlamak
Hammer'da input ve output'lar: Outputs sekmesinin alanları, buton ve kapı örneği, !activator, logic_relay ve ent_fire ile hata ayıklama.
Hammer'da entity'leri output'lar ve input'lar üzerinden birbirine bağlarsın: bir entity'nin output'u başka bir entity'nin input'unu tetikler ve hedef, adına (targetname) göre bulunur. Kapı açan bir buton için kapıya bir ad verirsin ve func_button entity'sine, kapının Open input'uyla birlikte OnPressed output'unu eklersin. Böyle bir bağlantı çoğunlukla yanlış yazılmış ya da iki kez kullanılmış bir ad, kaldırılmış bir hedef ya da aynı anda ulaşan iki output yüzünden bozulur.
Output'lar ve input'lar birlikte nasıl çalışır
Output, bir entity'nin bildirdiği bir olaydır: bir butona basıldı, bir kapı tamamen açıldı, biri bir trigger'a girdi. Input ise bir entity'nin kabul ettiği bir komuttur; örneğin Open, Close ya da Kill. Bir sınıfın hangi output'lara ve input'lara sahip olduğu FGD'de tanımlıdır.
Tetiklenen her output, motorun içindeki bir olay kuyruğuna yerleştirilir ve ayarladığın gecikmeden sonra teslim edilir. Motor hedefi ada göre ancak o anda arar. Yanında iki bilgi taşınır: activator, yani çoğunlukla zinciri başlatan entity (butonda oyuncu), ve caller, yani output'u tetiklenmekte olan entity.
Adı, Object Properties penceresindeki (Alt+Enter) Name alanında verirsin. Adı olmayan bir entity output gönderebilir, ama hedef olarak ona yalnızca classname'i ya da !activator gibi özel bir hedef üzerinden ulaşılabilir. Editörün temelleri Hammer Editor'e başlangıç yazısında anlatılıyor.
Outputs sekmesinin alanları
Object Properties penceresinin Outputs sekmesinde Add... ile bir bağlantı oluşturursun. GMod ile gelen Hammer'da düzenleme alanları ile listedeki sütunlar biraz farklı adlandırılmıştır:
| Alan | Sütun | Anlamı |
|---|---|---|
My output named | My Output | Bu entity'nin, bağlantıyı tetikleyen olayı |
Targets entities named | Target Entity | Hedefin adı; alternatif olarak classname, wildcard ya da özel hedef |
Via this input | Target Input | Hedefin yerine getirdiği komut |
With a parameter override of | Parameter | Input bir değer bekliyorsa o değer |
After a delay in seconds of | Delay | Olay ile teslim arasındaki bekleme süresi |
Fire once only | Once | Bağlantı bir kez tetiklendikten sonra silinir |
Hammer++, onay kutusunun yerine Limit to this many fires ( -1 = infinite ) alanını ve "Refires" sütununu koyar. Inputs sekmesi ters yönü, yani bu entity'yi gösteren tüm bağlantıları gösterir. Mark diğer uca atlar.
Örnek: bir buton kapıyı açar ve yeniden kapatır
- Kapıyı brush olarak yap,
Ctrl+Ttuşlarına bas vefunc_doorseç. Adınıdoor_1koy. Move Direction (Pitch Yaw Roll)değerini açılma yönüne,Delay Before Reset (-1 stay)değerini-1olarak ayarla. Kapı o zaman açık kalır.FlagssekmesindeTouch Opensişaretini kaldır. Varsayılan olarak işaretlidir ve kapıyı dokunulduğunda açardı.- Butonu brush olarak yap ve
func_buttonentity'sine çevir.Use Activatesflag'i zaten ayarlıdır.Delay Before Reset (-1 stay)değeri5olduğunda butona en az beş saniye boyunca yeniden basılamaz. - Butonun
Outputssekmesinde iki bağlantı ekle:
My Output Target Entity Target Input Parameter Delay
OnPressed door_1 Open 0.00
OnPressed door_1 Close 5.00
Kapı hemen açılır ve basıştan beş saniye sonra kapanır. İkinci bağlantı olmadan da olur: Delay Before Reset değeri 5 olan bir kapı kendiliğinden kapanır. Aynı düzenle bir asansörün nasıl çağrıldığı asansörler ve trenler yazısında anlatılıyor.
Özel hedefler ve mantık yapı taşları
Hedef alanında ad yerine özel bir hedef de bulunabilir:
| Hedef | Anlamı |
|---|---|
!activator | Zinciri başlatan entity, örneğin butondaki oyuncu |
!caller | Output'u tetiklenmekte olan entity |
!self | Hedef olarak !caller ile aynıdır, parametre olarak ise input'u alan entity'dir |
!player | Oyuncu; çok oyunculu modda sunucuya ilk katılan oyuncu |
!picker | Nişangâhın altındaki entity; hata ayıklama için düşünülmüştür |
Bu yüzden bir sunucuda !player neredeyse hiçbir zaman doğru değildir. Zinciri tetikleyen oyuncu için !activator, herkes için ise player classname'ini kullan. Wildcard'lar yalnızca sonda çalışır: door_*, door_ ile başlayan her adla eşleşir. *_door gibi bir kalıp çalışmaz, çünkü motor * işaretinden sonraki her şeyi yok sayar. func_door gibi bir classname de geçerli bir hedeftir; yeter ki tam olarak bu metni ad olarak taşıyan bir entity olmasın.
Birkaç mantık entity'si bunu daha büyük devrelere dönüştürür:
logic_relaybirden çok output'u tek bir ad altında toplar: inputTrigger, outputOnTrigger.Disablezinciri keser,CancelPendingrelay'in hâlâ bekleyen olaylarını iptal eder.Allow fast retriggerflag'i ayarlı değilse, gecikmeli output'lar beklerken yeniden tetiklenemez.logic_timer,Refire Intervaldeğerinin temposundaOnTimertetikler.math_counter,AddveSubtractile sayar ve bir sınıra ulaşıldığındaOnHitMaxya daOnHitMintetikler.trigger_multiple;OnStartTouch,OnEndTouchveOnTriggeriçeren bir hacimdir. Onu kimin tetikleyebileceğini flag'ler ve birfilter_activator_nameya dafilter_activator_classile birlikteFilter Namebelirler.
Oyunda hata ayıklama
Derlemeden önce Map > Check for Problems (Alt+P), geçersiz bağlantıları olan entity'leri listeler. Oyunda şu konsol komutları işe yarar:
developer 2
ent_messages_draw 1
ent_fire door_1 Open
ent_fire !picker Kill
developer 2, her output'u ve her input'u konsola yazar.dumpeventqueue, gecikmesinin dolmasını hâlâ bekleyen olayları listeler.ent_messages_draw 1, aynı mesajları 3D dünyada entity'lerin üzerinde gösterir.ent_fire <target> <input> [parameter] [delay], bir input'u elle tetikler. Böylece hedefi, onu tetikleyen şeyden bağımsız olarak test edebilirsin.
Tek oyunculu modda ya da host olarak test et, çünkü Valve wiki'sine göre bir sunucuya bağlı olan client ent_fire kullanamaz. Konsol cheat isterse önce sv_cheats 1 yaz. developer 2 ile konsol satırları aşağıdaki kalıbı izler. Blok, GMod'un server.dll dosyasındaki mesaj biçimlerinden, örnekteki adlarla ve uydurma bir zamanla bir araya getirilmiştir. Gerçek bir oturumun kaydı değildir:
(12.50) output: (func_button,button_1) -> (door_1,Open)()
(12.50) input button_1: door_1.Open()
unhandled input: (Open) -> (door_2), from (func_button,button_1); target entity not found
İlk satır tetiklenen output, ikincisi onun teslimidir. Asıl bakman gereken üçüncüsüdür: teslim anında hiçbir entity hedef adını taşımıyorsa görünür; bu örnekte hedef adı door_2.
Tipik hatalar
- Ad eksik ya da yanlış yazılmış: Hammer hedefi kırmızı gösterir ve "Check for Problems" bağlantıyı bildirir. Orada "Fix" seçeneğini körü körüne kullanma: hata metnine göre Hammer hatalı bağlantıları onarmak yerine siler. Wildcard'lar ve classname'ler de oyunda çalıştıkları hâlde kırmızı görünür.
- Ad iki kez kullanılmış: Hammer hedefi kalın gösterir. Input, bu ada sahip her entity'ye gider. Bu, iki kapı kanadı için istenen bir şeydir; yan odadaki kopyalanmış bir kapı için değil.
- Hedef kaldırılmış:
Kill, bir entity'yi parent hiyerarşisindeki çocuklarıyla birlikte siler. Sonrasında ulaşan gecikmeli output'lar boşa gider ve kaldırılan entity yeni output tetiklemez. Oyuncu sunucudan daha önce ayrılırsa aynısı!activatoriçin de olur. - Zamanlama yarışları: Aynı gecikmeye sahip iki output aynı tick'te ulaşır. Sıralarına güvenme. B, A'ya bağlıysa B'ye küçük bir gecikme ver. Valve wiki'si böyle bir durumda en az 0,02 saniye kullanır.
Output'lar bir lua_run entity'sini de tetikleyebilir; o da Lua kodu çalıştırır. Map Scanner, bir BSP'deki bu tür riskli entity'leri bulur. Başka kontroller yayın öncesi BSP kontrolü yazısında sıralanıyor.
Sık sorulan sorular
Bir output aynı anda birden çok entity'ye gidebilir mi?
Evet. Input, hedefin eşleştiği her entity'ye gider: ortak bir ad, door_* gibi bir wildcard ya da bir classname.
func_button'da OnPressed ile OnIn arasındaki fark nedir?
OnPressed, butona basılır basılmaz tetiklenir. OnIn ancak buton basılı son konumuna ulaştığında, OnOut ise başlangıç konumuna döndüğünde tetiklenir.
Oyun çalışırken output'ları değiştirebilir miyim?
Evet, AddOutput input'uyla. Biçimi şöyledir: <output> <target>:<input>:<parameter>:<delay>:<max times to fire>. FGD bunu "very dangerous, use with care" diye niteler ve oyun içinde kendi kendini yeniden bağlayan devreleri sonradan takip etmek zordur.