Jak z pewnością wiesz otwierane drzwi można zrobić przy użyciu func_door_rotating. Drzwi zrobione w ten sposób pozostawiają jednak wiele do życzenia -; same się zamykają, brakuje im oprawy dźwiękowej. Poniżej przedstawiam metodę, dzięki której będziesz mógł(a) umieścić na mapie drzwi, które zamykać i otwierać będzie się poprzez ich każdorazowe użycie, ba, okraszone będą efektami dźwiękowymi.
Na samym początku utwórz prostą mapę z dwiema szczelinami na drzwi. Może to wyglądać w ten sposób:
1) Tworzenie modelu drzwi.
Sam model drzwi tworzy się w ten sam sposób jak przy drzwiach robionych metodą func_door_rotating. Tak więc:
a) Stwórz brusha i pokryj go teksturą common\caulk (szerokość 48, wysokość 80, grubość 4). Następnie wszystkie możliwe do zauważenia face'y pokryj teksturą jakichś drzwi (tj. wszystkie prócz spodu). Przypominam, że aby zaznaczyć poszczególne face'y do teksturowania przytrzymaj [Ctrl] i [Shift], a następnie kliknij lewym przyciskiem myszy w podglądzie 3D. Rozciągnij teksturę na frontach (zaznacz je, uruchom Surface inspektora [S], kliknij na górny [Fit]). Na brzegach mogły być widoczne klamki lub inne elementy frontu drzwi. Anomalie te można poprawić za pomocą wspomnianego Surface inspektora (przesuwanie - Horizontal\Vertical shift, rozciąganie - Horizontal\Vertical stretch, obrót - Rotate). Tak więc mamy już same drzwi. Można opcjonalnie dorobić klamki.
b) Utwórz oś, po której drzwi będą się obracać. Wybierz teksturę common => origin. Narysuj brusha o wysokości tej samej co drzwi. Pamiętaj by umieścić go po stronie zawiasów. Grubość może być równa grubości drzwi. Szerokość - 1 cal. Środek tego brusha będzie początkiem układu współrzędnych dla drzwi przy ich obracaniu. Gdyby go nie było środkiem tym byłby środek mapy. W takim przypadku drzwi obracałyby się o 90* nie względem zawiasów, ale środka mapy - widzielibyśmy efekt raczej przesuwania niż obrotu.
c) Teraz zaznacz wszystkie brushy, które będą wchodziły w skład ruchomych elementów drzwi (drzwi, ewentualna klamka i co najważniejsze brush pokryty tekstura common\orgin). W podglądzie 2D kliknij prawym przyciskiem myszy i wybierz script => brushmodel (nie jak przy drzwiach robionym poprzez func_door_rotating - func => door_rotating). Utworzyliśmy w ten sposób model jak pojazd, czy drzewo tyle, że składający się z brushów. Jeżeli chcemy by coś się na naszej mapie poruszało musimy dokonać na tym obiekcie tej czynności. By zaznaczyć wszystkie elementy wchodzące w skład modelu przytrzymaj [Alt] + [Ctrl] + [Shift] i kliknij na niego.
d) Analogicznie stwórz drugie drzwi, dla drugiej szczeliny (najlepiej skopiuj już utworzony).
2) Triggery i inne ustawienia w edytorze.
Mamy już modele drzwi teraz należy stworzyć triggery, dzięki którym będziemy mogli je otwierać. Tak więc:
a>Stwórz brusha o rozmiarach frontu drzwi, jego grubość niech będzie trzy razy większa. Przesuń go w stronę, w którą drzwi będą się otwierać oraz, oczywiście, pokryj go teksturą common/trigger.
b) Mając zaznaczony ten obiekt kliknij prawym na podglądzie 2D i wybierz trigger => use. W ten sposób stworzyliśmy pole, na którym po najechaniu i byciu dostatecznie blisko pojawi się - łapka - i będziemy mogli coś zdziałać.
c) Analogicznie stwórz drugi taki dla drugich drzwi.
d) Teraz należy wszystko ponazywać. Zaznacz jeden z elementów wchodzących w skład pierwszych drzwi. Uruchom Enity [N]. W pole Key wpisz targetname, a w pole Value door1. naciśnij [Enter]. Dzięki temu ustalamy nazwę modelu na door1 (mimo, że zaznaczyłeś (aż) tylko jeden element, nazwa zostanie przyporządkowana wszystkim, a raczej całemu modelowi). Nazwanie modelu będzie potrzebne do późniejszego odnalezienia go przez skrypt. Podaj jeszcze klucz (Key) close o wartości (Value) 1. Będzie to informowało, czy drzwi są zamknięte, czy nie.
e) Zaznacz teraz odpowiadający drzwiom trigger i nazwij go door1handler (czyli nazwa drzwi + handler - dzięki temu odpowiedni trigger zostanie odnaleziony przez skrypt).
f) Operacje d) i e) wykonaj dla drugich drzwi. Nazwij je jednak door2, a odpowiadający im sensor door2handler.
3) Obskryptowywanie
Bez tworzenia skrypt się tutaj nie objedzie. Otwórz Notatnik i zapisz plik jako nazwa_twojej_misji.gsc. Umieść go w folderze gdzie znajduje się twoja mapa (np. \Main\maps\). Wklej do niego poniższy fragment kodu:
#using_animtree("generic_human");
main()
{
thread door("door1",1); //uruchomienie funkcji steruj?cej dla door1
thread door("door2",1); //uruchomienie funkcji steruj?cej dla door2
}
//funkcja sterująca drzwiami
//name - nazwa drzwi
//x - początkowy kierunek obrotu (1 - dodatni lub -1 - ujemny)
door(name,x)
{
door = getent (name, "targetname"); //odszukanie drzwi
trig = getent (name + "handler", "targetname"); //odszukanie odpowiedniego triggera
if (door.close == 1) //sprawdzanie stanu drzwi do
nadania im odpowiedniej podpowiedzi
trig setHintString ("Otwórz drzwi"); //ustawienie treści komunkatu do sensora
else
trig setHintString ("Zamknij drzwi"); //ustawienie treści komunkatu do sensora
while (1) //czuwanie nad stanem triggera …
{
trig waittill ("trigger"); //… czekanie, aż trigger nie zostanie użyty
trig setHintString (""); //na czas ruchu brak podpowiedzi do triggera
trig setCursorHint ("HINT_NOACTIVATE");//na czas ruchu brak obrazka do triggera
if (door.close == 1) //sprawdzanie stanu drzwi
{
//otwieranie
door rotateyaw(90 * x,1.45,0,0.3); //obrót
door playsound ("mdoor_open"); //odgrywanie dźwięku
door waittill ("rotatedone"); //czekanie na zakończenie obrotu
door playsound ("mdoor_openEnd"); //odgrywanie dźwięku
door.close = 0; //stan drzwi na otwarty
trig setHintString ("Zamknij drzwi"); //pokazanie treści podpowiedzi triggera
}
else
{
//zamykanie
door rotateyaw(90 * x,2,0,0.4); //obrót
door playsound ("mdoor_close"); //odgrywanie dźwięku
door waittill ("rotatedone"); //czekanie na zakończenie obrotu
door playsound ("mdoor_closeEnd"); //odgrywanie dźwięku
door.close = 1; //stan drzwi na zamknięty
trig setHintString ("Otwórz drzwi "); //pokazanie treści podpowiedzi triggera
}
trig setCursorHint ("HINT_ACTIVATE"); //pokazanie obrazka triggera po wykonaniu ruchu
x = x * -1; //zaktualizowanie kierunku obrotu
}
}
Nie mogę tutaj z oczywistych powodów dokładnie wytłumaczyć działania skryptu. Mogę za to w uogólnieniu przedstawić jego działanie.
1) Inicjowanie funkcji sterującej dla każdych z drzwi.
2) Odnajdywanie modelu drzwi i odpowiadającego triggera.
3) Oczekiwanie na użycie triggera.
4) Otwarcie lub zamknięcie drzwi (na dostawie wpisu close w modelu).
5) Punkty 3. i 4. są wykonywane cyklicznie, aż do zakończenia misji.
W razie jakichkolwiek problemów napisz o tym w komentarzu do artykułu.
4) Teksty i aliasy dźwięków
Tekst podpowiedzi możesz pobierać z plików z tekstami (te w localizedstrings\english w packach gry). Poniżej znajduje się przykład takiego pliku.
REFERENCE DOOR_OPEN
LANG_ENGLISH "Otwórz drzwi"
REFERENCE DOOR_CLOSE
LANG_ENGLISH "Zamknij drzwi"
ENDMARKER
Zapisz ten fragment do folderu /Main/localizedstrings/english jako nazwa_twojej_misji.str
Teraz zamiast "Otwórz drzwi" podamy &"NAZWAMISJI_ DOOR_OPEN".
Jeżeli nie stworzysz odpowiedniego pliku z aliasami do dźwięków nie będziesz w stanie słyszeć jakichkolwiek odgłosów oddawanych przez drzwi. Tak więc, znowu otwórz Notatnik i wklej tam poniższy fragment kodu:
name,sequence,file,vol_min,vol_max,pitch_min,
pitch_max,dist_min,dist_max,channel,type,
probability,loop,masterslave,loadspec,subtitle
mdoor_open,,doors\door_metal_open.wav ...[nazwa twojej misji],
mdoor_openEnd,,doors\door_metal_openEnd.wav ... [nazwa twojej misji],
mdoor_close,,doors\door_metal_close.wav ... [nazwa twojej misji],
mdoor_closeEnd,,doors\door_metal_closeEnd.wav ... [nazwa twojej misji],
Plik zapisz byle jak byle z rozszerzeniem *.csv do katalogu \Main\soundaliases.
5) Szybka inicjacja dla wielu drzwi
W przypadku występowania 20 drzwi na mapie musimy dla każdych dopisywać linijkę kodu, która zainicjuje czuwanie nad nimi (będzie ich wtedy 20). Nie bez powodu nazywaliśmy utworzone poprzednio modele door1 i door2. Możemy dostawiź jeszcze door3 i dooor4, aż do door20. Dzięki temu przy użyciu pętli for będziemy mogli dla każdych z nich zainicjować funkcje sterującą w tylko 2 linijkach kodu.
for (i=1; i<=20; i++)
thread door("door" + i, 1);