Hookowanie wzięcia przedmiotu z oCMobContainer 5491 5

O temacie

Autor Woad

Zaczęty 31.05.2021 roku

Wyświetleń 5491

Odpowiedzi 5

Woad

Woad

Użytkownicy
posty82
Propsy11
ProfesjaProgramista
  • Użytkownicy
Hej Wszystkim,

Mam mały problem, z którym pewnie prędzej czy później sobie poradzę, ale może ktoś akurat ma większe doświadczenie albo robił coś podobnego. Szukałem tego pobieżnie, ale informacje są tak porozrzucane, że ciężko znaleźć gotowe rozwiązanie na forach.

Robię z użyciem LeGo i Ikarusa system, w którym wszechwiedzący Innos ocenia nasze czyny. I nie jak jakiś tam NPC, tylko widzi nawet to, czego nikt inny nie będzie w stanie dostrzec. W skrócie - globalnie. Podobne systemy są na pewno w innych modach.

Mam praktycznie wszystko gotowe - morderstwa npc i kradzieże vobów, z wyjątkiem jednej rzeczy - kradzieży ze skrzyń. Zdefiniowałem już condition, który będzie sprawdzał, czy dany oCMobContainer jest przez kogoś posiadany i nawet w celu debugowania podświetlam ich nazwy na czerwono. Wszystko śmiga.

Problemem jest to, że ni jak nie mogę znaleźć dobrej funkcji do zhookowania. Kombinowałem z oboma oCMobContainer::Remove i oCMobContainer::Insert i jeszcze parę innych, ale w ogóle się nie triggerują z tego co widzę podczas zwykłego wyciągania przedmiotu. Myślałem, że coś nie tak robię podczas hookowania, że jest gdzieś problem w kodzie, ale wszystko wskazuje na to, że używane przeze mnie funkcje po prostu się akurat wtedy nie wywołują. Żadne debugi na ekranie, nic nie przechodzi, a ten sam kod podpięty do DoTakeVob daje zadowalajace rezultaty.

To próbki hooków, które nic mi nie dają. Oczywiście zostały umieszczone w init itp.

func void Hook_oCMobContainer__Remove()
{
const int oCMobContainer__Remove = 7495808; //0x0726080
HookEngineF (oCMobContainer__Remove, 10, EVT_MobContainerRemove);
};

func void Hook_oCMobContainer__Remove()
{
const int oCMobContainer__Remove = 7495664; //0x0725FF0
HookEngineF (oCMobContainer__Remove, 6, EVT_MobContainerRemove);

};

Ma ktoś jakiś pomysł, co warto by zhookować? Potrzebuję na pewno dostępu do oCItem i oCMobContainer. Dostęp do podnoszącego oCNpc byłby na duży plus.

EDIT:

Dobra, sprawa częściowo rozwiązana. Chyba do zamknięcia. Jakby ktoś był ciekawy, to użyłem oCItemContainer::Remove. Wada jest taka, że nie miałem w ten sposób dostępu do oCMobContainer. Ominąłem to pobierając focus gracza jako container.

Jedynym problemem jest teraz tylko to, że przy przyspieszonym zabieraniu funkcja Remove jest wywoływana mniejszą liczbę razy i jak przytrzymamy mysz, to źle oblicza wartość skradzionych dóbr, bo przerzuca kilka itemów na raz. Poszukam, czy da się temu zaradzić.
 

Splash

Splash

Moderator
posty4209
Propsy3412
ProfesjaNierób
  • Moderator
Tylko jest jeden mały problem: gra nie definiuje w żaden sposób czy przedmioty znajdujące się w skrzyni nie zostały wcześniej umieszczone przez gracza. Tak więc będziesz karał gracza nawet za zabranie przedmiotu, który wcześniej tam umieścił
 
Nie zajmuję się multiplayerami do Gothica. Przestańcie zawracać mi tym głowę...
Ps. Siemekk ma downa i śpi w pufie

Woad

Woad

Użytkownicy
posty82
Propsy11
ProfesjaProgramista
  • Użytkownicy
To prawda, chociaż mogę zrobić, że odstawienie przedmiotu na miejsce w przypadku już istniejącej "kary" do czyjejś prywatnej skrzyni nam tą karę cofnie, bo trackuję łączną wartość itemów. Mógłbym też trzymać ich listę. Wtedy problemem pozostanie to, że gracz może sobie poprzekładać itemy do różnych prywatnych skrzyń po mieście i nie będzie ukarany.

Jeszcze pokombinuję nad różnymi rozwiązaniami. Generalnie i tak karam gracza tylko za ruszanie skrzyń przy których ktoś nazwałby go złodziejem.

Problem z EDITa rozwiązałem callując oCItemContainer::GetTransferCount. Uciążliwa rzecz, bo zwracany short, więc musiałem się trochę pobawić stosem, żeby to ściągnąć, ale w końcu się udało i liczy sumę w złocie poprawnie nawet przy przyspieszonym transferze.

Jak ktoś ma jakieś sugestie, to śmiało. Od strony technicznej jest to raczej ogarnięte.

EDIT:

Albo wsadzanym do skrzyń itemom ustawię ownera na hero. Przy kradzieży będę sprawdzał, czy przypadkiem ownerem itemu nie jest już gracz. Nie wiem, czy wypali, ale zaraz sprawdzę. Teoretycznie nie powinno naliczać ani kradzieży dwa razy ani wsadzonych itemów jako kradzież.

EDIT2:

Dobra, wszystko działa i to nawet elegancko. W momencie wkładania przez nas itemów do skrzyni PC_Hero staje się ich ownerem. Wtedy wyciągając nasz item z obcego kufra nie jesteśmy już złodziejem. Podobnie zrobiłem z ciuchami od Lobarta. Będziemy mogli wyjąć ubranie ze skrzyni po zakupie, ale nic więcej.

Równie dobrze mógłbym zrobić, że podnosząc itemy od razu jesteśmy już ich ownerem, ale musiałbym lekko przebudować kilka rzeczy. To się zobaczy. Dzięki za sugestię.
 

bogu9821

bogu9821

Użytkownicy
posty407
Propsy185
ProfesjaProgramista
  • Użytkownicy
Co do edit2, to niestety to chyba nie zadziała poprawnie, bo owner chyba nie jest archiwizowany i przez to po wczytaniu gry, większość pól itemu zostanie zczytana ze skryptów, wraz z ownerem, chociaż mogę się mylić.
I w sumie to według mnie nie ma sensu robić X funkcji, aby tylko zhookować jedną funkcję, lepiej wywoływać to raczej w jednej funkcji, aby ograniczać ilość symboli parsera, chociaż przy względnie małej ilości skryptów to zbyt dużego znaczenia raczej nie ma.
Ja bym poszukał jakichś nieużywanych i archiwizowanych pól w klasie skrzyni/ekwipunku skrzyni, a w ostateczności można zrobić tablicę tablic, czy tam listę list za pomocą lego i przechowywać np. instance i ilość.
Ale w sumie to też pytanie brzmi w jaki sposób te skrzynie wtedy identyfikować.
Może przechowywać xyz w świecie skrzyń, czyli odpowiednie elementy trafo z klasy zCVob.
 
while(false) Do();

Woad

Woad

Użytkownicy
posty82
Propsy11
ProfesjaProgramista
  • Użytkownicy
Faktycznie, zapisywanie ownera nie działa po wczytaniu gry.

Ja to mam wszystko zrobione w jednej funkcji, eksperymentowałem tylko z kilkoma wariantami.

Chyba będę musiał zrobić jakąś kolekcję tych itemów, containerów i liczby. Chociaż nie jest to duży problem. Możemy uznać, że jeśli coś komuś wrzuciliśmy do prywatnej skrzyni i minął jakiś czas, to ten przedmiot należy już do niego.

EDIT:

Nie chciało mi się bawić w robienie tych kolekcji, przynajmniej na razie. Po prostu jeśli ktoś odłoży itemy o równej wartości, to kara jest z niego zdejmowana, bo trackuję łączną wartość kradzionych dóbr. Istnieje szansa, że ktoś nakradnie złotych talerz, a pooddaje miecze, ale trudno. W sumie co do wartości okradana osoba i tak musi wyjść na 0, więc nie jest tak źle.
 

Splash

Splash

Moderator
posty4209
Propsy3412
ProfesjaNierób
  • Moderator
Dobra, sprawa częściowo rozwiązana. Chyba do zamknięcia. Jakby ktoś był ciekawy, to użyłem oCItemContainer::Remove. Wada jest taka, że nie miałem w ten sposób dostępu do oCMobContainer. Ominąłem to pobierając focus gracza jako container.

Ten sposób będzie bezpieczniejszy:
    var oCNpc her; her = Hlp_GetNpc(hero);

    if (!Hlp_Is_oCMobContainer(her.interactMob)) {
        return;
    };

    var oCMobContainer mob; mob = _^(her.interactMob);

    if (ECX != mob.items) {
        return;
    };
 
    <dalsza część twojego kodu>
 
Nie zajmuję się multiplayerami do Gothica. Przestańcie zawracać mi tym głowę...
Ps. Siemekk ma downa i śpi w pufie


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