Rutyna: ćwiczenia strzeleckie 10471 15

O temacie

Autor inż. Avallach

Zaczęty 15.02.2012 roku

Wyświetleń 10471

Odpowiedzi 15

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator

inż. Avallach
Administrator

Rutyna: ćwiczenia strzeleckie
2012-02-15, 18:25(Ostatnia zmiana: 2013-07-19, 18:45)
Zapewne wiele osób kojarzy rutynę ćwiczenia walki mieczem. Pierwotnie do gry miała zostać dodana także rutyna ćwiczenia strzelectwa przez strzelanie do tarcz, jednak została porzucona (w skryptach jest ona "pusta", nie działa). Miałem pomóc RafałowiBudzisowi coś takiego zrobić, ale w końcu napisałem skrypt sam. Możecie go używać w modzie pod warunkiem zaznaczenia jego autorstwa w informacjach o modyfikacji.

Rutyna: func void ZS_PracticeBow ()
{
B_SetPerception (self);    
AI_SetWalkmode (self, NPC_WALK);
if (!Hlp_StrCmp(self.wp, Npc_GetNearestWP(self))) { AI_GotoWP(self, self.wp); };
AI_EquipBestRangedWeapon (self);
AI_ReadyRangedWeapon (self);
};

func void ZS_PracticeBow_Loop ()
{
var c_npc tarcza; tarcza = Hlp_GetNPC(self.aivar[43]); if (!tarcza) { tarcza = Hlp_GetNPC(tarcza_strzelecka_01); }; if (!tarcza) { return; };
var c_item RangedWeapon; RangedWeapon = Npc_GetEquippedRangedWeapon (self); CreateInvItem (self, RangedWeapon.munition);
AI_LookAtNpc(self, tarcza);
AI_AimAt (self, tarcza);
AI_Wait(self, 2);
AI_ShootAt (self, tarcza);
};

func void ZS_PracticeBow_End ()
{
AI_StopLookAt(self);
AI_StopAim(self);
Npc_ClearAIQueue (self);
AI_RemoveWeapon (self);
};
Tak naprawdę tarcza jest do zrobienia jako niewidzialny npc, który musi stać tam gdzie model. Należy go wstawić z poziomu Spacera, najpierw wyłączając kolizje tarczy, a na koniec włączając je z powrotem. Skrypt "tarczy":
prototype tarcza_strzelecka (C_NPC)
{
name = "Tarcza";
attribute[0] = 1; attribute[1] = 1;
flags = NPC_FLAG_IMMORTAL;
};

instance tarcza_strzelecka_01 (tarcza_strzelecka){};

Jeśli w danym zenie jest wiele tarcz, trzeba dać im osobne identyfikatory (kopiując instance i zmieniając numerek) i w skrypcie npc'ów którzy z nich korzystają, zapisywać z której (pod aivar[43]):
self.aivar[43] = tarcza_strzelecka_02;

Opcjonalne modyfikacje:
Spoiler
Początkowo kiedy pisałem ten skrypt, zamiast linijki
var c_npc tarcza; tarcza = Hlp_GetNPC(self.aivar[43]); if (!tarcza) { tarcza = Hlp_GetNPC(tarcza_strzelecka_01); }; if (!tarcza) { return; };byłoWld_DetectNpc (self, tarcza_strzelecka, NOFUNC, -1)); tarcza = other;Gdyby funkcja działała odpowiednio, można by używać wspólnego instance tarczy, a ona znajdowałaby najbliższą. Niestety tester dał znać że to nie działa. Kto chce może pokombinować i spróbować to naprawić, trochę upraszcza korzystanie z rutyny (nie trzeba ręcznie określać do której tarczy ma strzelać dany npc).




Kto chce, a także ma dostęp do klasy oCNpc (definicja dołączona m.in. do Ikarusa), może naprawdę wyłączyć kolizje tego niewidzialnego npc'a który jest celem dla strzał, a nawet uczynić go niewykrywalnym dla gracza (wyłączyć zaznaczalność itd). Należy w skrypcie instancji tarczy dodać:
var oCNpc ocnpc_self; ocnpc_self = Hlp_GetNpc(self);
ocnpc_self._zCVob_bitfield[0] = ocnpc_self._zCVob_bitfield[0] &~ zCVob_bitfield0_physicsEnabled;
ocnpc_self._zCVob_bitfield[0] = ocnpc_self._zCVob_bitfield[0] &~ zCVob_bitfield0_collDetectionStatic;
ocnpc_self._zCVob_bitfield[0] = ocnpc_self._zCVob_bitfield[0] &~ zCVob_bitfield0_collDetectionDynamic;
ocnpc_self._zCVob_type = 129; ocnpc_self.noFocus = 1;

edit: ten aivar 43 jest przykładowy dla G1. W G2NK jest on zajęty przez oryginalne skrypty. Musicie sobie wybrać taki aivar, który jest nieużywany.

RafalBudzis

RafalBudzis

Użytkownicy
posty1967
Propsy808
ProfesjaSkrypter
  • Użytkownicy
Może ktos się zadowoli moją wcześniejszą prowizorką z samymi animacjami i dźwiękiem (bez lotu strzały).
Zalety ? brak kombinowania z nie widocznym NPC.
Wady lepsi gracze sie dopatrzą ze NPC ma ciągle te samą strzałę w ręku ;d
No i warunek jakiś dać do dźwięku bo po zakończonej rozmowie słyszymy strzałę xD nie chciało mi sie kończyć ;d

func void ZS_PracticeBow ()
{
    PrintDebugNpc(PD_TA_FRAME,"ZS_PracticeBow");
   
B_SetPerception (self);    
AI_SetWalkmode (self,NPC_WALK); // Walkmode für den Zustand
if !(Hlp_StrCmp(self.wp,Npc_GetNearestWP(self)))
{
AI_GotoWP(self, self.wp);               // Gehe zum Tagesablaufstart
};
if (Wld_IsFPAvailable (self, "PRACTICEBOW"))
{
AI_GotoFP (self,"PRACTICEBOW");
AI_AlignToFP( self ); //Richte Dich aus
};
AI_ReadyRangedWeapon(self);
AI_PlayAni (self,"T_BOWWALK_2_BOWAIM");
AI_PlayAni (self,"s_BOWAIM");//namierzanie

};

func void ZS_PracticeBow_Loop ()
{



AI_PlayAni  (self,"T_BOWRELOAD");//strzał / ładowanie

AI_Wait(self,2);

AI_PlayAni (self,"s_BOWAIM");//namierzanie

var int los_czekania;//długośc mierzenia do celu
los_czekania = Hlp_Random(2);

if (los_czekania == 0) {

AI_Wait(self,2);

}else if (los_czekania == 2) {

AI_Wait(self,4);

}else if (los_czekania == 1) {

AI_Wait(self,8);

};

Snd_Play3D  (self, "BOW_FIRE_02");//dźwięk wystrzału zawsze wykonuje sie na POCZATKU funkcji


};

func void ZS_PracticeBow_End ()
{
    PrintDebugNpc(PD_TA_FRAME,"ZS_PracticeBow_End");
AI_PlayAni (self,"T_BOWAIM_2_BOWWALK");
//B_FullStop (self);
B_RemoveWeapon (self);

};

Ponury Żniwiarz

Ponury Żniwiarz

Użytkownicy
♠ 6661 ♠
posty34
Propsy8
ProfesjaConcept Artist
  • Użytkownicy
  • ♠ 6661 ♠
Szukałem właśnie czegoś w tym stylu, przyda się na 100%, tylko jeszcze nie wiem, której wersji użyć : )
 

gothic1210
  • Gość
Avallach, dodanie npc bezpośrednio w spacerze powoduje błąd. Można to wywołać klasycznie, czyli na waypoincie? Jak mniemam tobie chodziło o dodanie tego przez InsertCNpc w spacerze.
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator

inż. Avallach
Administrator

Rutyna: ćwiczenia strzeleckie
#4 2013-06-11, 20:04(Ostatnia zmiana: 2013-06-11, 20:08)
Tak, do tego o ile pamiętam Rafał pisał że działa, z tym że musiał dodawać voby w odpowiedniej kolejności. Co to za błąd?

Chodzi o to że npc musi być równo w miejscu modelu, żeby strzała leciała tam gdzie trzeba.

Ewentualnie gdyby w jakiś sposób dostać referencję do zCVoba tarczy (bez kombinowania z npc), prawie na pewno funkcje
AI_LookAtNpc
AI_AimAt
AI_ShootAt
Akceptowałyby go jako argument. Ale tu już trzeba by użyć Ikarusa.

gothic1210
  • Gość
Avallach ten kod jest nieoprawny:
Cytuj
prototype tarcza_strzelecka (C_NPC)
{
name = "Tarcza";
attribute[0] = 1; attribute[1] = 1;
flags = NPC_FLAG_IMMORTAL;
};

instance tarcza_strzelecka_01 (tarcza_strzelecka){};
Mimo iż parser go przyjmuje to po wywołaniu tarczy (spacer/gra) występuje crash. Jesteś pewien, że o niczym nie zapomniałeś?
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator

inż. Avallach
Administrator

Rutyna: ćwiczenia strzeleckie
#6 2013-06-12, 21:45(Ostatnia zmiana: 2013-06-12, 21:52)
Zdecydowanie nie jestem, pisałem to z pamięci i nigdy nie testowałem :D
Jakbym miał zgadywać, to być może niezbędny jest visual. Byłoby to dość przykre, trzeba by napisać pustego mds'a (i może nawet zrobić do niego pusty asc ze szkieletem animacji - których nie będzie).

Jeśli rzeczywiście tak jest, to już lepiej byłoby ustawić mu visual tarczy. Nie jestem pewien czy taka tarcza nie mogła by się sama z siebie obracać (lol). Sposobów przychodzi mi do głowy kilka, nie mam pojęcia jakie efekty by dawały. Od ustawienia modelu .3ds w polu visual, poprzez mds używający niestandardowych komend, po banalne rozwiązanie jakim jest zapisanie modelu tarczy jako pliku .asc z jedną kością szkieletu.

Jak widać trzeba z tym ciut więcej kombinować.

Istota sprawy jest taka, że zwykłymi skryptami możemy sprawić żeby npc strzelał jedynie do innego npc. Nie jesteśmy w stanie bez Ikarusa podać odniesienia do innego zCVoba. Zaraz, przecież jesteśmy. Lol. Dajcie mi chwilę, chyba mam pomysła :D

gothic1210
  • Gość
Zdecydowanie nie jestem, pisałem to z pamięci i nigdy nie testowałem :D
Jakbym miał zgadywać, to być może niezbędny jest visual. Byłoby to dość przykre, trzeba by napisać pustego mds#msg1088138a (i może nawet zrobić do niego pusty asc ze szkieletem animacji - których nie będzie).
Też o tym pomyślałem i wpisałem byle co;
visual            =   "ItAr_Rune_42.3ds";
ale dalej wywalało.
Wątpię, że to coś pomogło ale wrzucam co mi się wyświetla.
Spoiler
http://ifotos.pl/zobacz/Beztytuuj_nxxqwaa.jpg/

Te lody to nie te lody o których myślicie ... żeby nie było
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator

inż. Avallach
Administrator

Rutyna: ćwiczenia strzeleckie
#8 2013-06-12, 22:00(Ostatnia zmiana: 2013-06-12, 22:27)
Jak napisałem, normalnie npc mogą strzelać tylko do innych npc. Więc zachodziła konieczność żeby albo tarcza była npc'em, albo żeby w miejscu tarczy stał niewidzialny, unieruchomiony npc. Z drugiej strony, można by spróbować zgadywać że tak naprawdę funkcja zaakceptuje jako argument dowolnego zCVoba. Problem jest w tym, że jedyne zCVoby do jakich mamy dostęp z poziomu skryptów to npc i itemy. Na dodatek w drugim przypadku zwykle posiadamy odniesienia jedynie do obiektów przechowywanych w ekwipunku. Są jednak dwie funkcje, które sądząc po nazwach, pozwoliłyby uzyskać odniesienie do przedmiotu przechowywanego w świecie. A dokładnie, zapisywać je do zmiennej "item". Moi kandydaci to AI_LookForItem i Wld_DetectItem. To żeby gracz nie mógł zabrać itemu, nie jest problemem. O ile pamiętam była to kwestia ustawienia niestandardowego flags / mainflag. Bodajże 0 albo -1. Wystarczy sprawdzić. Tutaj testowo daję nieużywane ITEM_KAT_LIGHT.

Procedura testowa:
instance cel (c_item) { mainflag = ITEM_KAT_LIGHT; }; //być może trzeba ustawić jakieś inne pola, np. visual, nie pamiętam

func void test1 ()
{
    Wld_DetectItem(self, ITEM_KAT_LIGHT);
    AI_ShootAt (self, item);
};

func void test2 ()
{
    AI_LookForItem(self, cel);
    AI_ShootAt (self, item);
};
Sprawdzi ktoś czy npc u którego się to wywoła przynajmniej raz strzela do itemu? Aha, oczywiście taki item musi być zespawnowany w pobliżu, a npc musi mieć wyciągniętą broń dystansową do której ma amunicję. W ramach testu można też kazać mu tą samą funkcją strzelić do hero.

Swoją drogą, dobrze by było jakby RafałBudzis wypowiedział się na temat metody z pierwszego posta, wydawało mi się że testował to z niewidzialnym npc i pisał że działa. Wtedy nie trzeba by kombinować z itemem, chociaż to też ciekawy pomysł :D

gothic1210
  • Gość
Dałem do rutyny najpierw test1 potem test2. Obydwa scrashowały. Myślę, że pomysł ze strzelaniem do NPC jest lepszy tylko trzeba zrobić niewidzialnego MDS'a. Tak sobie teraz myślę, czy nie można byłoby zrobić modelu np. tarczy lub słomianej kukły, zapisać go do ASC i podstawić wszędzie w MDS ten model. Wtedy byłaby tylko ta jedna statyczna animacja. Przejdzie takie coś?
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator

inż. Avallach
Administrator

Rutyna: ćwiczenia strzeleckie
#10 2013-06-13, 22:03(Ostatnia zmiana: 2013-07-18, 13:44)
Tak, oczywiście. Tak jak napisałem, wystarczyłby w nim nagłówek, określenie pliku asc ciała/szkieletu. Animacje nie są potrzebne. Nie jestem tylko pewien czy nie mógłby się obracać dookoła własnej osi (a to nie byłoby dobrze :D ).

INVISIBLE.MDS:
Spoiler
Model ("Invisible")
{
meshAndTree ("Invisible_Body.asc" DONT_USE_MESH)
registerMesh ("Invisible_Body.ASC")
aniEnum
{
}
}
Mogą być potrzebne te animacje, wtedy trzeba by zrobić dla nich pusty .asc animacji:s_FistRun
s_FallDn
s_FistWalk
t_FistRun_2_FistWalk
t_FistWalk_2_FistRun

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator
Chetnik podlinkował takie coś z WoGa: http://www.worldofgothic.de/?go=moddb&action=view&fileID=919&cat=1&page=1&order=0
Tarcza do której może strzelać gracz. Jest to to o czym pisałem wcześniej ja i gothic1210 - czyli npc którego mds nie ma prawdziwych animacji (są puste), a w pliku asc ciała ma model tarczy.

Jak najbardziej nadaje się to do połączenia z moją rutyną. Dla osób które nie ogarniają co się w tych skryptach dzieje: najprościej zmienić "INSTANCE Aim    (Mst_Default_Aim)" na "INSTANCE tarcza_strzelecka_01 (Mst_Default_Aim)". Dodawanie kolejnych tarcz według instrukcji z pierwszego posta  - skopiowanie tego:
INSTANCE tarcza_strzelecka_01 (Mst_Default_Aim)
{
        B_SetVisuals_Aim();
        Npc_SetToFistMode(self);
        start_aistate                           = ZS_MM_AllScheduler;
        aivar[AIV_MM_RoamStart]         = OnlyRoutine;
 
};
Zmiana numerka w identyfikatorze (np na tarcza_strzelecka_02) i w skrypcie npc ćwiczącego strzelanie wybór do której tarczy będzie miał strzelać, np:
self.aivar[43] = tarcza_strzelecka_02;

Vesemir

Vesemir

Użytkownicy
posty44
Propsy3
ProfesjaGracz
  • Użytkownicy
Czy te kody można jakoś zaimplementować do G2NK? Czy może po tylu latach są już gotowe pliki z rutyną tylko do wklejenia ?
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator
Nie ma gotowych plików, ale ten kod jak najbardziej nadaje się do G2NK - różnice w silniku gry są tu nieistotne. Musisz tylko zmienić indeks używanego aivara na inny o ile planujesz używać wielu tarcz w jednym zenie.

Vesemir

Vesemir

Użytkownicy
posty44
Propsy3
ProfesjaGracz
  • Użytkownicy
Czyli rozumiem że jak użyję tego kodu na rutynę w pliku w folderze TA_Human to pomimo różnic w kodzie miedzy G1 a G2NK powinno działać? Dopiero rozpoczynam przygodę z moddingiem dlatego niezbyt się dobrze orientuję. I niezbyt rozumiem na jakiej zasadzie zaimplementować tą tarczę do strzelania? Jaki plik stworzyć i gdzie dokładnie go wrzucić aby pozniej był w spacerze jako cVob do wstawienia w Zenie
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5238
NagrodyV
ProfesjaProgramista
  • Administrator
To jaki plik i gdzie tworzysz jest ogólnie bez znaczenia - najlepiej trzymaj po prostu swój kod w osobych plikach niż kod podstawowej gry. Tarcza do strzelania to zwykły npc, w pierwszym poście jest nawet pełny skrypt:
prototype tarcza_strzelecka (C_Npc)
{
    name = "Tarcza";
    attribute[0] = 1;
    attribute[1] = 1;
    flags = NPC_FLAG_IMMORTAL;
};

instance tarcza_strzelecka_01 (tarcza_strzelecka)
{
};
Tak jak napisałem - dowolny plik w scripts/content, zadbaj tylko żeby był wpisany w gothic.src później niż katalog _intern. Od zwykłego NPC różni się to głównie tym że wstawiasz go do świata Spacerem a nie skryptami.


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