[GIINK] Zdolność skradania polepsza się wraz ze zręcznością 695 3

O temacie

Autor Czudak

Zaczęty 25.10.2018 roku

Wyświetleń 695

Odpowiedzi 3

Czudak

Czudak

Użytkownicy
posty20
Propsy9
Profesjabrak
  • Użytkownicy

Dla niektórych wszechpotężne orcze/jaszczurzoczłecze percypowanie wszystkiego z odległości 300 kroków jest zaletą, która podkreśla ich potworzy rodowód. Dla innych, w tym mnie, trąci lenistwem albo brakiem pomysłów twórców gry.

Wykreowałem dosyć prosty system, który adresuje kwestię za pomocą atrybutu zręczności postaci (zarówno wobec wymienionych humanoidów, jak i kilkunastu innych paskud). Im większa wartość tego atrybutu, tym mniejszy zasięg wykrywania bohatera którymkolwiek ze zmysłów (w grze są tylko wzrok, słuch i węch); ale tylko podczas skradania, naturalnie.

Nie jest to system doskonały i "realistyczny" (w grze gdzie można wyleczyć wszystkie rany zjadając wagon żółtego sera), ale przynajmniej próbuje odnieść się do wątpliwej jakości umiejętności skradania się w organiczny dla niej sposób. Jeśli kiedykolwiek ulepszę całość metody (bo na bank można ją poprawić), to opublikuję go w tym samym temacie, zmieniając jego nazwę.



Założenia wstępne:
- im większa wartość zręczności, tym gorzej monstrom idzie wykrywanie skradającego się bohatera
- system wymaga, aby postać miała wyuczoną zdolność ukradkowości (skradania się) i aktywnie jej używała
- może dojść do sytuacji, gdzie odpowiednio zręczna postać może przejść cieniostworowi przed nosem na odległość miecza; coś takiego przydałoby się fabularnie uzasadnić (np. u nauczyciela podczas nauki talentu, że skradanie się to nie tylko dźwięk, ale i elementy wizualne [oblepienie się błotem lub odpowiednią do otoczenia farba, ubranie płaszcza, nałożenie kamuflażu z liści i gałązek, używanie osłon w otoczeniu] oraz powonienia [podchodzenie od zawiewnej, noszenie szali, masek i rękawic, natarcie się ziemią, igliwiem itp.]), bowiem z oczywistych względów nie będzie to zrozumiała sytuacja, kiedy już nastąpi; osobiście nigdzie tego nie tłumaczyłem, gdyż ten system zainstalowałem w modzie, który właściwie robię tylko dla siebie
- zaaplikowano absolutne minimum, z którego nawet najbardziej otępiały krwiopijca wyczuje przez egzoszkielet zbliżającą się katastrofę (dokładnie 50, co odpowiada zasięgowi sztyletu w grze), a jest ono osiągane przy 150 punktach zręczności dla wszystkich pokrak objętych systemem
- brak zmian w zasadach skradania się/wykrywania u ludzi
- nie włączono pewnych grup potworów (jak konstrukty, czy nieumarli, lub smoki, Poszukiwacze, rodzinka psowatych [wraz z orkowymi psami, czyli wargami], szczury [wszystkie], trolle, harpie)
- całość zagadnienia dotyczy tylko Bezimiennego, bowiem NPC nigdy nie skradają (choć raz widziałem wilka podkradającego się do ścierwojada)
- po wykonaniu jakiejkolwiek innej czynności (atak, chód, bieg, wspinaczka, czasem skok), ciągłość skradania się zostaje przerwana, a potwory które powinny percypować postać w zasięgu zrobią to natychmiastowo (tak jak w przypadku ludzi), co może skończyć się niezbyt miło
- po zaimplementowaniu procedury, może nastąpić epizod gdzie jakaś poczwara nie zaatakuje NPCa człowieka, który jest na wyciągnięcie ręki, gdyż system działa zawsze gdy bohater się skrada, a dane postacie zmaterializowały się w zasięgu widzenia (choć może być tak, że ich nie widać); jednakoż na palcach jednej ręki można policzyć sytuacje, gdzie stwór aktywnie atakujący postać tła jest przewodnim wątkiem fabularnym w Nocy Kruka; w 99% przypadków to gracz/NPC decyduje o podjęciu walki
- najlepiej powiązać to wraz z jakimś dodatkowym systemem nawiązującym do podchodzenia ukradkiem, np. ciosów w plecy/podstępnego ataku (dla którego samouczek też mam i który przedstawię później)



Całość krok po kroku:

1. Do (...)_WORK\DATA\SCRIPTS\CONTENT\STORY\STORY_GLOBALS.D dodajemy zmienną var int SNEAKER; (czy co tam chcesz, tylko żebyś spamiętał co).

2. W (...)_WORK\DATA\SCRIPTS\CONTENT\AI\HUMAN\C_HUMAN (może być gdzieś indziej, ale najlepiej w folderze AI) tworzymy plik C_SNEAKER.D (choć możesz ozwać go tym co ci przyjdzie do głowy, bez kitu), a w nim umieszczamy naszą podstawową funkcję:

Spoiler
func int C_Sneaker(var C_Npc hero)
{
if(C_BodyStateContains(hero,BS_SNEAK))
{
                return TRUE;
SNEAKER = TRUE;
}
else
{
                return FALSE;
SNEAKER = FALSE;
};
};

Pewnie można byłoby się obyć bez określania obu warunków TRUE/FALSE w tak bezpośredni sposób, ale wiedziony doświadczeniem, wiem że lepiej kiedy zEngine ma jasno przedstawione oba wybory w funkcjach, które mają zwrócić zerojedynkowe wartości.

3. Tak stworzoną funkcję, za pomocą AI\HUMAN\C_HUMAN\C_SNEAKER.D, dodajemy do pliku kompilacyjnego GOTHIC.SRC, który znajduje się zazwyczaj w (...)_WORK\DATA\SCRIPTS\CONTENT. Umieszczamy na pozycji po wszystkich ZS_MM_*****.D (u mnie w linii 1650); koniecznie tutaj, bowiem te skrypty regulują percepcję i nastawienie wobec innych NPCów w grze, w tym gracza.

4. Następnie, do wybranych (przez ciebie; nie będę dawał swojej listy, gdyż jest ona zbyt długa) skryptów potworów w (...)_WORK\DATA\SCRIPTS\CONTENT\STORY\NPC\MONSTER oraz \ORC dodajemy następującą treść, zamiast senses_range:

Spoiler
if(SNEAKER == TRUE)
{
senses_range = 1500 - (hero.attribute[ATR_DEXTERITY] * 10);
if(senses_range < 50)
{
senses_range = 50;
};
}
if(SNEAKER == FALSE)
{
senses_range = PERC_DIST_MONSTER_ACTIVE_MAX;
};

Musi się ona znaleźć zaraz po linii senses = ******** (od dwóch do trzech zmysłów); w danym skrypcie.

Należy zauważyć, iż PERC_DIST_MONSTER_ACTIVE_MAX są zastąpione u orków/jaszczuroludzi przez PERC_DIST_ORC_ACTIVE_MAX i mają różne wartości (1500 dla pierwszego, a 2500 dla drugiego), więc należy też kod powyżej odpowiednio zmienić, no chyba że ktoś chce zrównać pomiot Beliara z innymi zwierzętami.

Dodatkowo, 10 w równaniu można zastąpić inną liczbą (mniejszą dla łatwiejszego wykrywania w zależności od zręczności, a większą dla trudniejszego), więc samemu można sobie ustalić korelację, w zależności od preferencji. Nie polecam używania matematycznego dzielenia przez cokolwiek, bowiem nawet jeden punkt różnicy w zręczności może przełożyć się na dwa/trzy kroki odległości detekcji w świecie gry (a przynajmniej tak miałem podczas testowania).



I tyle. Teraz grając złodziejem, czy łucznikiem (bądź łucznikiem-złodziejem), o odpowiednio wysokiej zręczności, można przekraść się obok hordy orków w drodze do zamku (w rozdziale 2), czy kamiennego smoka (w rozdziale 4), zająć odpowiednią pozycję i ich wszystkich powystrzelać.

Tylko weź ze sobą odpowiednio dużo amunicji, OK?

Post połączony: 2018-10-25, 16:36
 

Bogdan Zwei

Bogdan Zwei

Użytkownicy
Wulgarny skurwiel pierdolony.
posty1861
Propsy532
Profesjabrak
  • Użytkownicy
  • Wulgarny skurwiel pierdolony.
Dlaczego funkcja jest typu "int" skoro nic nie zwraca? Jest to totalnie bez sensu. I tak i tak nie użyjesz "if (C_Sneeker() == true), bo funkcja nic nie zwróci, czyli będzie niespełniony warunek, no matter what.
 
:ok: zachęca do dalszej pomocy. Nie zapominaj o tym!

Prywatne wiadomości typu "Ej, pomocy" kasuję od razu. Od tego jest forum, a nie PW.

To me, defeat in anything is merely temporary, and its punishment is but an urge for me to greater effort to achieve my goal. Defeat simply tells me that something is wrong in my doing; it is a path leading to success and truth.

In order to realize our true self we must be willing to live without being dependent upon the opinion of others.

Czudak

Czudak

Użytkownicy
posty20
Propsy9
Profesjabrak
  • Użytkownicy
Dlaczego funkcja jest typu "int" skoro nic nie zwraca? Jest to totalnie bez sensu. I tak i tak nie użyjesz "if (C_Sneeker() == true), bo funkcja nic nie zwróci, czyli będzie niespełniony warunek, no matter what.

Hej! Dzięki za wkład. Już zacząłem kombinować z plikami percepcji, dzięki którym nie trzeba tyle kombinować, a sprawdza tylko jeden warunek. Powinienem to ogarnąć gdzieś do miesiąca.

PS. Nie wiem jakie są różnice w tych funkcjach, więc zgaduję, że int(eger) można zamienić na (float) void?

PSS. Czyli to wszystko było efektem placebo?
 

Cruc

Cruc

Użytkownicy
posty529
Propsy179
Profesjabrak
  • Użytkownicy
Ciekawy pomysł, podoba mi się. Ale mam jedną uwagę kosmetyczną.

Spoiler
senses_range = 1500 - (hero.attribute[ATR_DEXTERITY] * 10);
if(senses_range < 50)
{
   senses_range = 50;
};

Coś takiego nazywa się magiczną stałą. Jest to liczba w kodzie, która sama z siebie nie informuje co oznacza. Gdyby nie Twoje wyjaśnienie, w życiu bym się nie domyślił dlaczego tam jest akurat 1500, a nie np. 1234. To trochę tak, jakby ktoś Ci dał do analizy program, gdzie nagle w warunku masz liczbę 299 792 458. Wiesz co ona oznacza? A teraz wyobraź sobie, że w tym samym warunku masz zamiast tej liczby stałą SPEED_OF_LIGHT. Od razu lepiej, co? :F

Kod mógłby więc wyglądać mniej więcej tak:

Spoiler
senses_range = PERC_DIST_MONSTER_ACTIVE_MAX - (hero.attribute[ATR_DEXTERITY] * SENSE_DEBUFF_MULTIPLIER); //nie mam lepszego pomysłu na nazwę tak na szybko xd
if(senses_range < PERC_DIST_MONSTER_MIN)
{
   senses_range = PERC_DIST_MONSTER_MIN;
};

Ma to też tę zaletę, że chcąc dokonać zmian w balansie, zamiast szukać liczb w kodzie i zmieniać je pojedynczo, wystarczy jedynie zmodyfikować wartość stałej, nie zaglądając nawet do samego kodu.
 
Splash zajmuje się multiplayerami do Gothica. Nie przestawajcie zawracać mu tym głowy


0 użytkowników i 1 Gość przegląda ten wątek.
0 użytkowników
Do góry