|
GOTHIC WEB SITE Forum o grach z serii Gothic
|
Zobacz poprzedni temat :: Zobacz następny temat |
Autor |
Wiadomość |
Artex
Wojownik
Dołączył: 06 Sie 2008
Posty: 1048
Przeczytał: 0 tematów
Pomógł: 29 razy Ostrzeżeń: 0/5
Płeć: Mężczyzna
|
Wysłany: Czw 14:19, 21 Maj 2009 Temat postu: Zbiór tutoriali. |
|
|
Ponieważ coraz więcej osób zadaje mi pytania na odpowiedzi które zostały udzielone, robię ten temat, jako zbiór wszystkich moich tutków, żebyście się nie mogli wykręcać że nie potraficie znaleźć.
W tym temacie nie odpisujemy, jest to miejsce wyłącznie na turtoriale związane z modowaniem. Jeżeli ktoś chce zamieścić tutaj swój tutek (powtarzam, swój, a nie kopię) to pisać do mnie na PW.
Cytat: | Modowanie od podstaw cz. 1.(tutek pod gothic 1).
No więc jak zacząć:
Musimy mieć parę programów/narzędzi żeby zacząć.
1. Gothic (najlepiej PL) chyba nie muszę wyjaśniać.
2. [link widoczny dla zalogowanych] (mogą być oryginalne, ale wasze mody będą, oprócz wprowadzonych przez was zmian będą po niemiecku).
3. [link widoczny dla zalogowanych] (żeby edytować world'a).
4. [link widoczny dla zalogowanych] (służy także do uruchamiania innych modów, ale swojego też musisz uruchomić, nie?)
5. I tak dosyć ogólnie [link widoczny dla zalogowanych], jest tam zawarta większość tego co wam podałem w poprzednich linkach i jeszcze trochę.
Wszystko to wypakowywujemy do swojego folderu z Gothiciem (do właściwych folderów), z uwagą na to że najpierw powinniśmy wgrać GMDK, a potem podmienić tamte narzędzia na te z linków podanych wcześniej.
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 2.(tutek pod gothic 1).
No więc:
Żeby wprowadzić zmiany w naszych skryptach musimy mieć własny plik .ini który będzie "tak jakby" naszym modem. Więc:
1. Tworzymy nowy plik .ini. Mój wygląda tak:
Kod: | [INFO]
title=MyMod
description=A po co?
authors=Ja!
version=Pre Alpha
webpage=Ni mom.
[FILES]
game=content\gothic
fightai=content\fight
menu=system\menu
camera=system\camera
music=system\music
soundeffects=system\sfx
particleseffects=system\particlefx
visualeffects=system\visualfx
outputunits=content\cutscene\ou
vdf=MyMod.mod
[SETTINGS]
world=WORLD.ZEN
player=PC_HERO
[OPTIONS]
force_parameters=1
force_subtitles=1
show_info=1 |
Title: Nazwa twojego modka
Description: Krótki opis, ale po co ci on narazie? : )
Authors: autorzy.
Version: Wersja moda. Na początek prealpha, ale możesz wpisać cokolwiek >.<
Webpage: noo.... webpage!
World: Definiuję w jakim świecie odbywa się gra, dajemy tam "world.zen"
player: Definiuje PC którym zaczniesz grę, najlepiej dać PC_HERO bo startujemy bezi, który jako jeden z niewielu PC potrafi w ogóle do kogoś zagadać, ale nic nie stoi na przeszkodzie żeby wklepać PC_THIEF albo PC_FIGHTER.
Resztę zostaw jak jest. Przy czym linijka "vdf=MyMod.mod" Może zawierać NARAZIE dowolną wartość, bo odnosi się ona do paczki z modem, której na razie nie mamy...
Teraz:
2. Wprowadzamy zmiany (heh, nowi NPC, dialogi, cokolwiek).
3. Uruchamiamy PlayerKita. I...
... mamy takie coś (cholera, mało widoczne... macie tu [link widoczny dla zalogowanych] do pobrania obrazka). Jest to okno naszego player kita, ale uwaga, player kita dla tych którzy "robią mody", a nie "grają w mody" . Różnica jest duża, bo ten dla grających nie zawiera parę potrzebnych nam opcji.
A. uruchamiamy wybraną modyfikację.
B. uruchamiamy Spacer.
1. Odznaczamy tą opcje jeżeli chcemy żeby nasze zmiany zostały wprowadzone do gry.
2. Gra zostanie uruchomiona w oknie.
3. Wyłącza muzykę w grze.
4. Wyłącza dźwięki w grze.
5. To jest ważne, uruchamia zSpy, programik służący do wynajdywania błędów w skryptach, przestawiamy suwak maksymalnie w prawo jeżeli spodziewamy się błędów (robimy repasację po wielu przeróbkach), dajemy na lewo jeżeli nie spodziewamy się takowych.
Teraz zaznaczamy w polu po lewej nasz mod i dajemy A, czyli startujemy grę. Jeżeli wszystko jest dobrze to gra się uruchomi, jeżeli nie... to pokaże nam się okienko w którym zostanie wypisany JEDEN (bo może być więcej) błędów które popełniliśmy w kodzie. Gra poda nam linijkę w której zrobiliśmy błąd (np. 47) i specyfikację błędu (brakuje średnika, niepotrzebne else, itd.), ale nie poda pliku. Poda nam go za to zSpy którego (być może...) uruchomiliśmy przed repasowaniem, za pomocą suwaka.
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 3.(tutek pod gothic 1).
No to dziś nauczymy się wprowadzać do gry "realne" zmiany , czyli naszą pierwszą broń.
Przedmioty znajdują się w ścieżce "X:\Folder z Gothicem\_Work\Data\Scripts\Content\Items" A dalej bronie, albo w "Melee_weapons", "Ranged_weapons", albo w "weapons"
oto przykładowy skrypt broni:
Kod: | INSTANCE Kill_Lame (C_Item)
{
name = "Zguba Lamera";
mainflag = ITEM_KAT_NF;
flags = ITEM_SWD;
material = MAT_METAL;
value = 2500;
damageTotal = 110;
damagetype = DAM_EDGE;
range = 130;
cond_atr[2] = ATR_STRENGTH;
cond_value[2] = 60;
owner = Non_2001_Artex;
visual = "ItMw_1H_Sword_Bastard_04.3DS";
description = name;
TEXT[2] = NAME_Damage; COUNT[2] = damageTotal;
TEXT[3] = NAME_Str_needed; COUNT[3] = cond_value[2];
TEXT[4] = NAME_OneHanded;
TEXT[5] = NAME_Value; COUNT[5] = value;
}; |
A teraz, co i jak:
Kod: | INSTANCE Kill_Lame (C_Item) |
Jest to definicja potrzebna na początku każdego przedmiotu NPC, potwora... itd. zaraz po słowie INSTANCE wpisujemy identyfikator naszego przedmiotu, gdy będziemy go przyzywać z konsoli, albo pisać skrypt że np: "Jeżeli masz przedmiot to:..." będziemy używać tego właśnie identyfikatora.
Dalej otwieramy nawias klamrowy "{" potrzebne, gdyż nasz przedmiot jest klasą (języka C... tym sobie głowy nie musicie zawracać )
I....
Kod: | name = "Zguba Lamera"; |
Określa jak będzie nazywał się nasz przedmiot (broń).
Kod: | mainflag = ITEM_KAT_NF;
flags = ITEM_SWD;
material = MAT_METAL; |
Średnio ważne, określa że nasz item jest bronią, mieczem i jest zrobiony z metalu (potrzebne gdy przedmiot upada i gra musi zdecydować jaki wywołać dźwięk).
Wartość, tak, ta zwykła sklepowa wartość przypisana do każdego przedmiotu.
Damagetotal - Obrażenia (po prostu )
Kod: | damagetype = DAM_EDGE; |
To jest ciekawe. Określa typ obrażeń jakie zadaje broń, prawie każda broń w grze ma EDGE (cięcie)
BLUNT (obuch, przydatne do określania dmg na golemy, nie można nią dobić ),
FIRE (ogień, patrz Uriziel)
MAGIC (patrz uriziel, zadaje dmg, jak czary, zabija od razu),
POINT (łuk, kusza, te sprawy)
BARRIER (serio... nie wiem, taki pół-lot zobaczcie sobie),
FLY (nie będę opisywał, sprawdźcie sobie, gwarantuje wrażenia śmiechowe)
INVAILD (dla mnie zagadka...)
Jeżeli chcemy aby broń używała paru typów, rozdzielamy je znakiem "|" o tak:
Określa długość broni, 0 - musimy uderzać z baaaardzo bliska, wyższe wartości (około 1000) dają ciekawy efekt.
Kod: | cond_atr[2] = ATR_STRENGTH;
cond_value[2] = 60; |
Określa jaki atrybut jest potrzebny żeby broń nosić (tu siła) i ile (tu 60).
Kod: | owner = Non_2001_Artex; |
Określa do jakiego NPC należy broń, w tym przypadku do mojego alter ego (NPC omówię w kolejnym tutku), jeżeli pokażesz (masz ja przy pasie/na plecach) się z bronią przy jego właścicielu to się na ciebie rzuci.
Kod: | visual = "ItMw_1H_Sword_Bastard_04.3DS"; |
Określa wygląd broni, w tym przypadku miecz blizny.
Kod: | description = name;
TEXT[2] = NAME_Damage; COUNT[2] = damageTotal;
TEXT[3] = NAME_Str_needed; COUNT[3] = cond_value[2];
TEXT[4] = NAME_OneHanded;
TEXT[5] = NAME_Value; COUNT[5] = value; |
Określa wygląd opisu broni, to co zawsze widać kiedy patrzycie na item w EQ, pokombinujcie sobie.
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 4.(tutek pod gothic 1).
Dziś nauczymy się jak wprowadzić trochę życia do naszego świata, dodamy NPC'ka.
Skrypty NPC znajdują się w folderze: "X:\Mój Folder z Gothiciem\_Work\Data\Scripts\Content\Story\NPC"
Oto skrypt typowego NPC (nie przerażać się!):
Kod: | instance Grd_200_Thorus (Npc_Default)
{
//-------- primary data --------
name = "Thorus";
npctype = NPCTYPE_FRIEND;
guild = GIL_GRD;
level = 50;
voice = 9;
id = 200;
flags = NPC_FLAG_IMMORTAL;
//-------- abilities --------
attribute[ATR_STRENGTH] = 100;
attribute[ATR_DEXTERITY] = 80;
attribute[ATR_MANA_MAX] = 0;
attribute[ATR_MANA] = 0;
attribute[ATR_HITPOINTS_MAX]= 280;
attribute[ATR_HITPOINTS] = 280;
//-------- visuals --------
// animations
Mdl_SetVisual (self,"HUMANS.MDS");
Mdl_ApplyOverlayMds (self,"Humans_Militia.mds");
// body mesh ,bdytex,skin,head mesh ,headtex,teethtex,ruestung
Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 3,"Hum_Head_Fighter", 12, 0, GRD_ARMOR_H);
B_Scale (self);
Mdl_SetModelFatness(self,0);
self.aivar[AIV_IMPORTANT] = TRUE;
fight_tactic = FAI_HUMAN_STRONG;
//-------- Talente --------
Npc_SetTalentSkill (self,NPC_TALENT_1H,2);
Npc_SetTalentSkill (self,NPC_TALENT_2H,2);
Npc_SetTalentSkill (self,NPC_TALENT_CROSSBOW,1);
//-------- inventory --------
EquipItem (self, Thorus_Schwert);
EquipItem (self, ItRw_Crossbow_01);
CreateInvItems (self, ItAmBolt, 30);
CreateInvItems (self, ItMiNugget,200);
CreateInvItem (self, ItFo_Potion_Health_02);
CreateInvItem (self, ItLsTorch);
//-------------Daily Routine-------------
daily_routine = Rtn_Start_200;
};
FUNC VOID Rtn_Start_200 ()
{
TA_Boss (08,00,23,00,"OCR_THORUS");
TA_Sleep (23,00,08,00,"OCC_BARONS_UPPER_RIGHT_ROOM_BED1");
}; |
Na pewno zauważyliście że to Thorus teraz dowiecie się dlaczego Thorus jest/wygląda/zachowuje się... jak Thorus xD (głupio to brzmi).
Kod: | instance Grd_200_Thorus (Npc_Default) |
Jest to instancja która inicjuje NPC'ka jest potrzebna, zawsze powinna zawierać frazę "instance", następnie coś w stylu nazwy NPC, czyli: "Gildia_ID_Imie",(ale nie trzeba się tego tak trzymać), na końcu mamy też "(Npc_Default)", który odpowiada za odwołanie Thorusa do proto-NPC, omówie to przy tutku o prototypach.
Kod: | {
//-------- primary data --------
name = "Thorus";
npctype = NPCTYPE_FRIEND;
guild = GIL_GRD;
level = 50;
voice = 9;
id = 200;
flags = NPC_FLAG_IMMORTAL; |
Na pewno zwróciliście uwagę na linijkę //------primary data------------, nie jest ona częścią kodu NPC, poniewać znajduję się za znakiem "//" co oznacza komentarz, KAŻDY tekst znajdujący się za tym tagiem (w jednej linijce), albo w tagach "/*" i "*/" nie jest intrpretowany przez kod.
Dalej:
Name - po prostu imię, można także zawrzeć tam frazę definiującą NPC type ambient, ale o tym później.
npctype - najlepiej pisać NPCTYPE_MAIN, wtedy NPC jest najbardziej naturalny, FRIEND nie reaguje na atak (spróbujcie zrobić żeby Diego was zaatakował, ciężko co?)
guild - po prostu gildia, potrzebne żeby nasz NPC identyfikował się z otoczeniem (pomagał swojakom, bił wrogów).
level - Level... od tego jaki jest zależy czy NPC w konfrontacji z nami będzie uciekał, czy walczył (jak ma dużo niższy to ucieka) i ile dostaniemy za niego exp.
voice - Dialogi, dialogami, ale ten kawałek kodu decyduje o tym jakich fraz używa NPC podczas kontaktu z otoczeniem, jakim głosem: dopinguje, krzyczy gdy ucieka, rozmawia z innymi NPC.
id - potrzebne jest (chyba) każdemu NPC, występuje pare razy w kodzie NPC, więc trzeba uważać żeby się nie pomylić.
flags - Tutaj mamy Immortal, czyli nieśmiertelny, normalny NPC to NPC pozbawiony tej linijki kodu, jest wtedy śmiertelny
Kod: | //-------- abilities --------
attribute[ATR_STRENGTH] = 100;
attribute[ATR_DEXTERITY] = 80;
attribute[ATR_MANA_MAX] = 0;
attribute[ATR_MANA] = 0;
attribute[ATR_HITPOINTS_MAX]= 280;
attribute[ATR_HITPOINTS] = 280; |
To jest najłatwiejsze:
Strength - siła
Dexterity - zręczność
Mana_max - maksymalna ilość many
Mana - obecna ilość many (jeżeli NPC ma mikstury to może je od razu wypić, jeżeli brakuje mu trochę many do pełni)
Hitpoints_max - maksymalna ilość życia
Hitpoints - obecne życie
Kod: | //-------- visuals --------
// animations
Mdl_SetVisual (self,"HUMANS.MDS");
Mdl_ApplyOverlayMds (self,"Humans_Militia.mds");
// body mesh ,bdytex,skin,head mesh ,headtex,teethtex,ruestung
Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 3,"Hum_Head_Fighter", 12, 0, GRD_ARMOR_H);
B_Scale (self);
Mdl_SetModelFatness(self,0);
self.aivar[AIV_IMPORTANT] = TRUE;
|
Decyduje jak NPC wygląda, jest to najbardziej skomplikowane, na początku najlepiej kopiować kod z innych NPC którzy są podobni do naszego (zamierzonego) i przerabiać odpowiednio.
Kod: | Mdl_SetVisual (self,"HUMANS.MDS"); |
Decyduje jaki plik animacji używany będzie przez NPC, dla ludzia zawsze HUMANS.MDS
Kod: | Mdl_ApplyOverlayMds (self,"Humans_Militia.mds"); |
Sposób w jaki NPC będzie się poruszał (gdy nie truchta, ani nie ucieka) mamy tutaj trochę tego, najlepiej popatrzeć do innych plików z NPC.
Kod: | Mdl_SetVisualBody (self,"hum_body_Naked0", 0, 3,"Hum_Head_Fighter", 12, 0, GRD_ARMOR_H); |
To jest najgorsze : ).
Mdl_SetVisualBody - rozpoczęcie (tu się nie kłóćcie xD)
self - potrzebne aby gra wiedziała kogo dotyczy kod.
"hum_body_naked0" rodzaj ciała
0, 3 - określa teksturę ciała
"Hum_Head_Fighter" - model głowy
12, 0 - tekstura głowy
GRD_ARMOR_H - określa pancerz jaki NPC ma na sobie, bez pancerza ta wartość ma wynosić -1
Kod: | //-------- Talente --------
Npc_SetTalentSkill (self,NPC_TALENT_1H,2);
Npc_SetTalentSkill (self,NPC_TALENT_2H,2);
Npc_SetTalentSkill (self,NPC_TALENT_CROSSBOW,1); |
Zwykłe umiejętności, radzę poprzeglądać u innych NPC, ostatnia cyfra (zaraz przed nawiasem) określa stopien wystrenowania umiejętności.
Kod: | //-------- inventory --------
EquipItem (self, Thorus_Schwert);
EquipItem (self, ItRw_Crossbow_01);
CreateInvItems (self, ItAmBolt, 30);
CreateInvItems (self, ItMiNugget,200);
CreateInvItem (self, ItFo_Potion_Health_02);
CreateInvItem (self, ItLsTorch); |
Ekwipunek, frazą "EquipItem" poprzedzamy przedmioty które NPC ma urbać (tu miecz i kusza), a "CreateInvItem" przedmiot (JEDEN) który NPC ma w EQ, jest jeszcze "CreateInvItems" (Ma "s" na końcu!), które odpowiada za przyzwanie paru przedmiotów.
Kod: | //-------------Daily Routine-------------
daily_routine = Rtn_Start_200;
};
FUNC VOID Rtn_Start_200 ()
{
TA_Boss (08,00,23,00,"OCR_THORUS");
TA_Sleep (23,00,08,00,"OCC_BARONS_UPPER_RIGHT_ROOM_BED1");
}; |
Rutyna, odpowiada za to co NPC i w jakich godzinach będzie robił.
Zawsze zaczyna się od frazy "daily_routine = Rtn_Start_(ID npc);" jeszcze w głównej klasie z NPC, następnie w kolejnej klasie zawartej pomiędzy tagami { i } :
Kod: | FUNC VOID Rtn_Start_200 ()
{
TA_Boss (08,00,23,00,"OCR_THORUS");
TA_Sleep (23,00,08,00,"OCC_BARONS_UPPER_RIGHT_ROOM_BED1");
}; |
Określamy co nasz NPC robi, rutyn jest sporo, można poprzeglądać u innych, rutyna powinna wyglądać tak:
"Nasza_Rutyna (godzinapoczątkowa,godzinakońcowa,"Waypoint(w którym NPC robi rutynę)", w tym przypadku nasz Thorus od 8 do 23 stroi sobie przed bramą, a od 23 do 8 śpi w budynku magnatów : )
No to tyle...
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Post został pochwalony 0 razy
|
|
Powrót do góry |
|
|
|
|
Artex
Wojownik
Dołączył: 06 Sie 2008
Posty: 1048
Przeczytał: 0 tematów
Pomógł: 29 razy Ostrzeżeń: 0/5
Płeć: Mężczyzna
|
Wysłany: Czw 14:26, 21 Maj 2009 Temat postu: |
|
|
Cytat: | Modowanie od podstaw cz. 5.(tutek pod gothic 1).
Dialogi znajdują się w folderze
X:\MójFolderZGothicem\_Work\Data\Scripts\Content\Story\MISSIONS
Są ty wszystkie dialogi oprócz tzw. ambientów, czyli dialogów obsługiwanych przez co najmniej paru NPC (strażnicy, cienie, najemnicy...).
Oto przykładowy kawałek kodu:
Kod: | // **************************************
// EXIT
// **************************************
instance DIA_Gomez_Exit (C_INFO)
{
npc = Ebr_100_Gomez;
nr = 999;
condition = DIA_Gomez_Exit_Condition;
information = DIA_Gomez_Exit_Info;
permanent = 1;
description = DIALOG_ENDE;
};
FUNC int DIA_Gomez_Exit_Condition()
{
return 1;
};
FUNC VOID DIA_Gomez_Exit_Info()
{
AI_StopProcessInfos (self);
}; |
Jest to fraza potrzebna dla KAŻDEGO dialogu, ponieważ odpowiada ona za wyświetlanie opcji KONIEC, tak więc... no chyba że ktoś robi postać tylko z importami, a poza tym niemożliwością rozmowy, ale lepiej nie kusić losu i dodać ten KONIEC.
Teraz taki kawałek, zasadniczego dialogu:
Kod: | instance DIA_Gomez_Fault (C_INFO)
{
npc = Ebr_100_Gomez;
nr = 1;
condition = DIA_Gomez_Fault_Condition;
information = DIA_Gomez_Fault_Info;
permanent = 0;
description = "Przychodzę zaoferować swoje usługi.";
}; |
Typowa klasa, ale co się za nią kryje?
Przede wszystkim zwróćcie uwagę na każdą frazę gdzie pojawia się słowo Gomez, albo liczba 100, Gomez to oczywiście imię, a 100 to ID tego jakże upierdliwego NPC (odsyłam do tutka o NPC) teraz o poszczególnych wartościach:
npc: odpowiada za to do jakiego NPC odnosi się dialog, proste.
nr: numer dialogu, tutaj kwestia cokolwiek dyskusyjna, zapamiętajcie tylko żeby przy EXIT dawać 999, przy pierwszym 1, a przy każdym kolejnym o jeden więcej...
condition: trzeba podać nazwę condition tego dialogu (heh xD)
information: trzeba podać nazwę information tego dialogu (heh xD)... eee? De Javu?
Pernament: pierwsze ciekawe, odpowiada za to czy dialog będzie się powtarzać, np. Diego możesz zagadywać o trening tyle razy ile chcesz, ale o zadania przeważnie pytasz tylko raz, tu tkwi sedno, 0 daje jednorazową wypowiedź, a 1 powtarzaną frazę.
description: określa jak opcja dialogowa będzie widnieć w okienku wyboru.
Important: (tutaj akurat nie ma), określa czy NPC sam do nas zagada, jeżeli important jest równe 1, dialog nie potrzebuje description.
teraz tylko zamykamy nawias "};" : ).
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 6.(tutek pod gothic 1).
Oto kawałek dialogu:
Kod: | INSTANCE DIA_ARTO_Hello (C_INFO)
{
npc = Ebr_102_Arto;
nr = 3;
condition = DIA_ARTO_Hello_Condition;
information = DIA_ARTO_Hello_Info;
permanent = 0;
description = "Kim jesteś?";
};
FUNC INT DIA_ARTO_Hello_Condition()
{
return 1;
};
FUNC VOID DIA_ARTO_Hello_Info()
{
AI_Output (other, self,"DIA_ARTO_Hello_15_00"); //Kim jesteś?
AI_Output (self, other,"DIA_ARTO_Hello_13_01"); //Jestem Arto.
}; |
Instance omówiłem wcześniej, teraz popatrzmy na condition:
Kod: | FUNC INT DIA_ARTO_Hello_Condition()
{
return 1;
}; |
Odpowiada ona za to czy będziemy mogli o "czymś" rozmawiać z NPC ew. czy NPC nas zagada jeżeli important jest ustawiony na 1.
Jeżeli dialog ma być domyślnie "do zagadania" jedyne co potrzebujemy to "return 1;" zawarte pomiędzy klamrami.
Często zdarza się że jakiś NPC gada z nami o "czymś", jeżeli o "czymś innym" porozmawialiśmy z innym NPC'kiem, wtedy stawiamy warunek IF:
Kod: | FUNC INT DIA_ARTO_What_Condition()
{
if (Npc_KnowsInfo (hero,DIA_ARTO_Hello))
{
return 1;
};
}; |
Dalszy ciąg dialogu Arto, piszę tu że: Jeżeli pogadaliśmy z Arto na temat "DIA_ARTO_Hello" to pojawi się opcja dialogowa, można stwarzać dużo więcej warunków, np. ile dni minęło, czy jakiś NPC żyje/nie żyje (quest na zlecenie zabójstwa), czy mamy jakieś przedmioty... wystarczy przejrzeć skrypty.
Teraz sam dialog:
Kod: | FUNC VOID DIA_ARTO_Hello_Info()
{
AI_Output (other, self,"DIA_ARTO_Hello_15_00"); //Kim jesteś?
AI_Output (self, other,"DIA_ARTO_Hello_13_01"); //Jestem Arto.
}; |
Wszystkie warunki okazały się prawidłowe i zainicjował się dialog, ten jest jednym z najprostszych, każda wypowiedź wygląda następująco:
AI_Output (osoba,osoba,"DIA_szczegóły-dialogu_numer_numer");//Treść wypowiedzi
jeśli chodzi o osoby, należy ustalić KTO wypowiada dialog, kiedy piszemy other,self jest to nasz bohater, gdy self,other rozmówca.
Szczegóły dialogu, a właściwie jego identyfikator, koniecznie potrzebne, gra musi wiedzieć skąd brać informację o dialogu.
Numerki, tutaj nie mam 100% pewności, ale nie jest to jakieś specjalnie ważne, potrzebne zdaje się żeby móc przyporządkować dialogi (mówione) do skryptu. Dla naszego bohatera, zawsze 15.
Treść: Co prawda mieści się w komentarzu, ale dialogi kompiluje spacer, a nie zwykły kompilator C, więc wszystko jest w porządku
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 7.(tutek pod gothic 1).
Jeżeli mamy już swojego NPC, i chcemy go dodać do świata, to co zrobić? Nie będziemy przecież za każdym razem klepać całą konsolę żeby sobie pograć w moda xD.
Mamy taki plik o nazwie Startup, w folderze:
X:\FolderZGothicem\_Work\Data\Scripts\Content\Story
są w nim wypisane wszystkie instancje wszystkich NPC w grze (prawie).
Oto kawałek kodu:
Kod: | Wld_InsertNpc (Ebr_100_Gomez,"OC1"); //
Wld_InsertNpc (Ebr_101_Scar,"OC1");
Wld_InsertNpc (Ebr_102_Arto,"OC1");
Wld_InsertNpc (Ebr_105_Raven,"OC1");
Wld_InsertNpc (Ebr_106_Bartholo,"OC1");
Wld_InsertNpc (Ebr_108_Velaya,"OC1"); //Gomez Zimmer 24h
Wld_InsertNpc (Ebr_109_Syra,"OC1");
Wld_InsertNpc (Ebr_110_Seraphia,"OC1"); |
Jak dobrze widać, za przyzwanie każdego NPC odpowiada mniej więcej taka linijka:
Kod: | Wld_InsertNpc (Ebr_100_Gomez,"OC1"); |
Wld_InserNpc, to instrukcja hmm.... jakby "inicjująca", dalej mamy w nawiasie instancję naszego NPC i w cudzysołowiu waypoit w którym NPC zaczyna, jeżeli NPC ma rutynę (a jest to potrzebne), to będzie tam gdzie każe mu jego rutyna, więc piszemy "OC1", odpowiedź uniwersalna : ). Nie zapomnijcie o średniku!
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Cytat: | Modowanie od podstaw cz. 8.(tutek pod gothic 1).
Nowe Potwory:
Aby zrobić sobie nowego stworka musimy stworzyć nowy plik .d, najpierw zajrzyjmy do gotowych stworów: X:\Gothic PL\_Work\Data\Scripts\Content\AI\Monster
Kod: | /*************************************************************************
** Wolf Prototype **
*************************************************************************/
PROTOTYPE Mst_Default_Wolf(C_Npc)
{
name = "Wilk";
guild = GIL_WOLF;
aivar[AIV_MM_REAL_ID] = ID_WOLF;
level = 9;
//-----------------------------------------------------------
attribute [ATR_STRENGTH] = 40;
attribute [ATR_DEXTERITY] = 40;
attribute [ATR_HITPOINTS_MAX] = 80;
attribute [ATR_HITPOINTS] = 80;
attribute [ATR_MANA_MAX] = 0;
attribute [ATR_MANA] = 0;
//-----------------------------------------------------------
protection [PROT_BLUNT] = 20;
protection [PROT_EDGE] = 20;
protection [PROT_POINT] = 10;
protection [PROT_FIRE] = 10;
protection [PROT_FLY] = 0;
protection [PROT_MAGIC] = 0;
//-----------------------------------------------------------
damagetype = DAM_EDGE;
// damage [DAM_INDEX_BLUNT] = 0;
// damage [DAM_INDEX_EDGE] = 0;
// damage [DAM_INDEX_POINT] = 0;
// damage [DAM_INDEX_FIRE] = 0;
// damage [DAM_INDEX_FLY] = 0;
// damage [DAM_INDEX_MAGIC] = 0;
//-----------------------------------------------------------
fight_tactic = FAI_WOLF;
//-----------------------------------------------------------
senses = SENSE_HEAR | SENSE_SEE | SENSE_SMELL;
senses_range = 3000; // 30m
aivar[AIV_MM_Behaviour] = PACKHUNTER;
aivar[AIV_MM_PercRange] = 1500;
aivar[AIV_MM_DrohRange] = 1200;
aivar[AIV_MM_AttackRange] = 500;
aivar[AIV_MM_DrohTime] = 3;
aivar[AIV_MM_FollowTime] = 10;
aivar[AIV_MM_FollowInWater] = TRUE;
//-----------------------------------------------------------
start_aistate = ZS_MM_AllScheduler;
aivar[AIV_MM_RoamStart] = OnlyRoutine;
};
//-----------------------------------------------------------
func void Set_Wolf_Visuals()
{
Mdl_SetVisual (self,"Wolf.mds");
// Body-Mesh Body-Tex Skin-Color Head-MMS Head-Tex Teeth-Tex ARMOR
Mdl_SetVisualBody (self, "Wol_Body", DEFAULT, DEFAULT, "", DEFAULT, DEFAULT, -1);
};
/*************************************************************************
** Wolf **
*************************************************************************/
INSTANCE Wolf (Mst_Default_Wolf)
{
Set_Wolf_Visuals();
Npc_SetToFistMode(self);
}; |
Jest tu wiele tablic i funkcji, omówię tylko te które są potrzebne żeby przerobić starego/zrobić nowego stworka.
Kod: | PROTOTYPE Mst_Default_Wolf(C_Npc)
{
name = "Wilk";
guild = GIL_WOLF;
aivar[AIV_MM_REAL_ID] = ID_WOLF;
level = 9; |
Deklaracja i parę informacji:
Name - imię potworka
Guild - jego gildia, warte uwagi, np. ścierwojady biją się z krwiopijcami, a wilki gonią kretoszczury. Zmiana wilkowi tej gildii na np. ścierwojada sprawi że będą bić się z bloodfly'ami
aivar - tablica ze zmiennymi, nam niepotrzebna, robiąc nowego potworka wzorujemy się na jakimś i zapożyczamy tą wartość.
level - odpowiada za otrzymane przez naszego hero doświadczenie
Kod: | attribute [ATR_STRENGTH] = 40;
attribute [ATR_DEXTERITY] = 40;
attribute [ATR_HITPOINTS_MAX] = 80;
attribute [ATR_HITPOINTS] = 80;
attribute [ATR_MANA_MAX] = 0;
attribute [ATR_MANA] = 0; |
Definiujemy po kolei siłę/zręczność/życie maksymalne/życie początkowe/manę maksymalną/manę początkową.
Kod: | protection [PROT_BLUNT] = 20;
protection [PROT_EDGE] = 20;
protection [PROT_POINT] = 10;
protection [PROT_FIRE] = 10;
protection [PROT_FLY] = 0;
protection [PROT_MAGIC] = 0; |
Odporności, pozwala na zrobienie potworka odpornego na np. magię, albo na odwrót, możliwego do zabicia tylko przy pomocy magii.
Kod: | fight_tactic = FAI_WOLF; |
Zależnie od modelu naszego stworka dajemy mu stosowny FAI, możemy dać mu FAI np. krwiopijcy, ale jeżeli gra się nie zatnie to i tak nic z tego nie będzie bo stwór straci dużo czasu na skakanie wokół nas (krwiopijca ma wpisane sekwencję uskoku w bok).
Kod: | senses = SENSE_HEAR | SENSE_SEE | SENSE_SMELL;
senses_range = 3000; // 30m
aivar[AIV_MM_Behaviour] = PACKHUNTER;
aivar[AIV_MM_PercRange] = 1500;
aivar[AIV_MM_DrohRange] = 1200;
aivar[AIV_MM_AttackRange] = 500;
aivar[AIV_MM_DrohTime] = 3;
aivar[AIV_MM_FollowTime] = 10;
aivar[AIV_MM_FollowInWater] = TRUE; |
A to są "inne takie".
Sense odpowiada za zmysły używane przez stworka, ich range to zasięg wyczuwania potworka.
Dalej widzimy tablice odpowiedzialne za to z jakiej odległości potwór nas goni i ile nas goni, czy goni nas w wodzie itd. Można się np. zabawić robiąc potwora który ściga nas po całej koloni. Przy ustawieniu remove distance na bardzo dużo w "Edit AI" efekt może być ciekawy.
Kod: | func void Set_Wolf_Visuals()
{
Mdl_SetVisual (self,"Wolf.mds");
// Body-Mesh Body-Tex Skin-Color Head-MMS Head-Tex Teeth-Tex ARMOR
Mdl_SetVisualBody (self, "Wol_Body", DEFAULT, DEFAULT, "", DEFAULT, DEFAULT, -1);
}; |
Wygląd potworka, wilk to wilk, nie ma tu zbyt dużego wyboru.
Zastrzegam sobie prawo do kopiowania tego turtoriala poza tym forum©. |
Post został pochwalony 0 razy
|
|
Powrót do góry |
|
|
|
|
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach
|
|