Przechwycenie itemku, który wypada z dłoni [IKARUS][LEGO][G1] 3112 7

O temacie

Autor DerDrache

Zaczęty 19.11.2021 roku

Wyświetleń 3112

Odpowiedzi 7

DerDrache

DerDrache

Użytkownicy
posty18
Propsy3
ProfesjaProgramista
  • Użytkownicy
Do 3 razy sztuka..

Próbuję zrobić system, który poprawia AIV_ITEMSCHWEIN, aby nie reagował na przedmioty na które nie powinien reagować. Oczywiscie hookuję funkcję ikarusem/lego. Udało mi się zrobić już upuszczanie przedmiotu przy NPC, zostało jeszcze upuszczanie broni czy co tam osoba trzyma w dłoni przy śmierci/unconscious. Niestety nie jestem w stanie określić która z funkcji to określa

Próby z róznymi funkcjami wygląda tak:

func void Hook_oCNPC_DropFromSlot()
{
const int oCNpc__DropFromSlotAddr = 6972016; //006A6270
HookEngineF(oCNpc__DropFromSlotAddr, 6, EVT_oCNPC_DropFromSlot);
};

func void EVT_oCNPC_DropFromSlot()
{
var c_npc slf; slf = MEM_PtrToInst(ECX);

if(Npc_GetInvItemBySlot(slf, INV_WEAPON, 1))
{
item.change_atr[0] = 99;
PrintScreen (ConcatStrings(ConcatStrings(slf.name, ": DROPFROMSLOT, flage AIV_ITEMSCHWEIN przedmiotu: "), item.name), 15,40,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
} else
{
PrintScreen (ConcatStrings(slf.name, ": DROPFROMSLOTNIC NIE MA NA SLOT1"), 15,42,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
};

if(Npc_GetInvItemBySlot(slf, INV_WEAPON, 2))
{
item.change_atr[0] = 99;
PrintScreen (ConcatStrings(ConcatStrings(slf.name, ": DROPFROMSLOT, flage AIV_ITEMSCHWEIN przedmiotu: "), item.name), 15,44,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
} else
{
PrintScreen (ConcatStrings(slf.name, ": DROPFROMSLOTNIC NIE MA NA SLOT2"), 15,46,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
};
};

func void Hook_oCNPC_DropAllInHand()
{
const int oCDropAllInHandAddr = 6898224; //694230
HookEngineF(oCDropAllInHandAddr, 1, EVT_oCNPC_DropAllInHand);
};

func void EVT_oCNPC_DropAllInHand()
{
var c_npc slf; slf = MEM_PtrToInst(ECX);

PrintScreen (ConcatStrings(slf.name, "DropAllInHand, enter:"), 65,5,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);

if(Npc_GetInvItemBySlot(slf, INV_WEAPON, 1))
{
item.change_atr[0] = 99;
PrintScreen (ConcatStrings(ConcatStrings(slf.name, ": DROPALLI HAND, fl AIV_ITEMSCHWEIN SLOT1 ITEMOWI:"), item.name), 15,70,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
} else
{
PrintScreen (ConcatStrings(slf.name, ": DROPALLI NIC NIE MA NA SLOT1"), 15,72,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
};

if(Npc_GetInvItemBySlot(slf, INV_WEAPON, 2))
{
item.change_atr[0] = 99;
PrintScreen (ConcatStrings(ConcatStrings(slf.name, ": DROPALLINHAND, fl AIV_ITEMSCHWEIN SLOT2 ITEMOWI:"), item.name), 15,70,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
} else
{
PrintScreen (ConcatStrings(slf.name, ": DROPALLI NIC NIE MA NA SLOT2"), 15,74,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
};
};

func void Hook_oCNpc_EquipWeapon()
{
const int oCNpc_EquipWeaponAddr = 6908960; //696C20
HookEngineF(oCNpc_EquipWeaponAddr, 1, EVT_oCNpc_EquipWeapon);
};

func void EVT_oCNpc_EquipWeapon()
{
var c_npc slf; slf = MEM_PtrToInst(ECX);
var C_ITEM itm; itm = MEM_PtrToInst(MEM_ReadInt(ESP + 8));

PrintScreen ("wchodzenie w equip wepaon", 15,60,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);

if (!Hlp_IsValidItem (itm))
{
PrintScreen ("ZLY ITEM", 15,62,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
return;
};

PrintScreen ("EquipWeapon: ZMIENIAMY ITEMSWINIE", 15,62,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
itm.change_atr[0] = 99;
};

func void Hook_oCNpc_Equip()
{
const int oCNpc_EquipAddr = 6908144; //6968F0
HookEngineF(oCNpc_EquipAddr, 3, EVT_oCNpc_Equip);
};

func void EVT_oCNpc_Equip()
{
var c_npc slf; slf = MEM_PtrToInst(ECX);
var C_ITEM itm; itm = MEM_PtrToInst(MEM_ReadInt(ESP + 8));

PrintScreen ("wchodzenie w equip", 15,64,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);

if (!Hlp_IsValidItem (itm))
{
PrintScreen ("ZLY ITEM", 15,66,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
return;
};

PrintScreen ("Equip: ZMIENIAMY ITEMSWINIE", 15,66,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
itm.change_atr[0] = 99;
};

func void Hook_oCNpc_EquipItem()
{
const int oCNpc_EquipItemAddr = 6879552; //68F940
HookEngineF(oCNpc_EquipItemAddr, 2, EVT_oCNpc_EquipItem);
};

func void EVT_oCNpc_EquipItem()
{
var c_npc slf; slf = MEM_PtrToInst(ECX);
var C_ITEM itm; itm = MEM_PtrToInst(MEM_ReadInt(ESP+48+4));

PrintScreen ("wchodzenie w equipITEM", 15,60,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);

if (!Hlp_IsValidItem (itm))
{
PrintScreen ("ZLY ITEM", 15,62,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
return;
};

PrintScreen ("ZMIENIAMY ITEMSWINIE", 15,62,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
itm.change_atr[0] = 99;
};

Nie wiem czy wszędzie są itemy poprawnie przekazane (jak ktoś wie jak to robić, i jest w stanie wytłumaczyć, można używać stricte programistycznego jezyka bo zawodowo jestem programistą cepa; starałem się sledzić skąd po kolei w danym rejestrze brał się itemek, ale nie wiem czy jest to dobrze zrobione, prawdopodobnie moznaby jakieś funkcje powywoływać ręcznie i pobrać ten item), ale ogólnie te funkcje.. w ogóle się nie wywołują. Np żadna z tych z rodziny "equip" nie pokazuje się ani razu, przy zakladaniu czegokolwiek przez kogokolwiek. Jedyna funkcja, jaka sie wywołuje to DropFromSlot(), ale nie mam pojęcia kiedy, bo zdaje się robić to dość losowo, czasem gdy przejdę koło NPC, czasem gdy przyzwę NPC insertem, gdy postać zginie zazwyczaj sie wywołuje, ale nie zawsze itp.

Generalnie w systemie rozchodzi się o to, zeby ustawić itemowi change_atr[0] = 99;. Najłatwiej i najsensowniej wydaje mi sie ze w funkcjach equip, bo potem by to nie lagowało ewentualnie przy zabijaniu wiekszej ilości NPC na raz, ale tak jak mówiłem nie działa to.

 
GOTHIC I: AMPLIFIED


bogu9821

bogu9821

Użytkownicy
posty405
Propsy185
ProfesjaProgramista
  • Użytkownicy
Po pierwsze hooklen nie może być mniejszy niż 5, jeżeli nie masz na początku instrukcji, która ma 5 bajtów, to dodajesz kolejną, aż masz >= 5 bajtów.

Offsetu na razie nie chce mi się sprawdzać, ale wydaje mi się, że twój sposób może nie działać poprawnie, bo myślę, że change_atr nie jest zapisywany do pliku, a podczas wczytania bierze wartości zczytane z instance itemu.
W G2 po prostu nadpisali jedną flage (ITEM_BURN na ITEM_FLAG_DROPPED, ale pewnie w g1 jest ona nadal używana), która jest archiwizowana i w oCNpc :: DoDropVob oraz oCNpc :: DropFromSlot jest ustawiana i czyszczona w oCNpc :: DoTakeVob.
Jakiś sposób na to pewnie by był, ale na razie nie mam na to siły, spróbuj kombinować inaczej, jeżeli mam rację.
 
while(false) Do();

Splash

Splash

Moderator
posty4207
Propsy3404
ProfesjaNierób
  • Moderator
Cytuj
Jakiś sposób na to pewnie by był, ale na razie nie mam na to siły, spróbuj kombinować inaczej, jeżeli mam rację.
Już tego kiedyś próbowałem. Z kompletnie nieznanych dla mnie przyczyn hook nie reaguje, a zmiana bajtów nic nie robi.


Próbowałem hookować nawet poprzednie instrukcje i też nic xD
 
Nie zajmuję się multiplayerami do Gothica. Przestańcie zawracać mi tym głowę...
Ps. Siemekk ma downa i śpi w pufie

DerDrache

DerDrache

Użytkownicy
posty18
Propsy3
ProfesjaProgramista
  • Użytkownicy
Dzięki za zwrócenie uwagi, @bogu9821 ,  rzeczywiście jest problem z wczytywaniem gry, spróbuję coś z flagami.

//ed:
na szybko nadanie tej flagi działa jesli chodzi o zapisy, pozostaje testować dalej czy nie wywoła to jakichś niepożądanych efektow.

I nie wiem czy masz rację z tymi adresami. Przykładowo


Wpisanie 7 w hookEngine EquipItem powoduje crasha

00:21 Warn:  0 U:       SPAWN: Spawnpoint TOT not found. Npc MEM_HELPER_INST cannot be spawned. .... <oSpawn.cpp,#386>
00:21 Info:  0 Q:       Ikarus log functions now print in colour with prefix 'Q:'.
00:21 Info:  0 Q:       LeGo 2.3.0b wird initialisiert.
00:21 Info:  0 Q:       Locals: Install at CREATE
00:21 Info:  0 Q:               Offset is 11
00:21 Info:  0 Q:       Locals: Install at NEW
00:21 Info:  0 Q:               Offset is 11
00:21 Info:  0 Q:       LeGo 2.3.0b wurde erfolgreich initialisiert.
00:21 Fault: 0 Q:       [start of stacktrace]
00:22 Fault: 0 Q:               EVT_OCNPC_EQUIPITEM()                                          +   89 bytes
00:22 Fault: 0 Q:       [end of stacktrace]
00:22 Fault: 0 Q:       Exception handler was invoked. Ikarus tried to print a Daedalus-Stacktrace to zSpy. Gothic will now crash and probably give you a stacktrace of its own.
 
GOTHIC I: AMPLIFIED


bogu9821

bogu9821

Użytkownicy
posty405
Propsy185
ProfesjaProgramista
  • Użytkownicy
Rację mam, bo ten rodzaj hooków to byte patching, który potrzebuje przynajmniej 5 bajtów, nawet masz w funkcji od hookowania, że jeżeli jest mniej niż 5 bajtów, to nie hookuje tego po prostu.
Dalej nie mam zbytnio siły na analizę tego, ale nie wiem czemu tam dajesz esp+48 i potem jeszcze +4 (nie zaglądałem do ida na razie), skoro raczej ten item do którego chcesz się dostać jest w pierwszym argumencie, czyli esp+4.
A i jeszcze dlaczego używasz tak starej wersji lego? Zrób update koniecznie (ikarusa też).
https://github.com/Lehona/Ikarus/releases/tag/v1.2.2
https://github.com/Lehona/LeGo/releases/tag/v2.8.0
 
while(false) Do();

DerDrache

DerDrache

Użytkownicy
posty18
Propsy3
ProfesjaProgramista
  • Użytkownicy
Używam wersji która została dostosowana do G1, bo najnowsze pobierane ręcznie nie były kompatybilne (była gdzieś na forum).

Jak możesz mieć rację, skoro stosując sie do twoich porad wywala mi exception (które jest zhandlowane przez Ikarusa albo i nie)? :)

Na analizę, skąd pobrać itemki przyjdzie czas później, tego w ogóle zbyt dokładnie nie sprawdzałem. Najważniejsze, ze zhookowane funkcje wogóle się nie wywołują, ani nie crashują, po prostu nic się nie dzieje.

W kazdym razie na początek sprawdze tego najnowszego ikarusa/lego.
 
GOTHIC I: AMPLIFIED


bogu9821

bogu9821

Użytkownicy
posty405
Propsy185
ProfesjaProgramista
  • Użytkownicy
Niekompatybilna była może z X lat temu (na początku ikarusa, gdzie początek był w 2010-2011, lego trochę później), teraz najnowsze wersje są dla obu wersji silników.

Wywala, bo prawdopodobnie to nie jest prawidłowy pointer do itemu, a ty go próbujesz jako pointer do itemu traktować. Spróbuj to zakomentować i zobacz czy dalej wywala.
var C_ITEM itm; itm = MEM_PtrToInst(MEM_ReadInt(ESP+48+4));
Też lepiej wpierw pointer dać do var int i sprawdzić czy nie jest null lub czy np. Hlp_Is_oCItem (ale to tylko jak nie wiesz czy to jest item, tutaj w odpowiednim miejscu w pamięci zawsze powinien być item, a także jeżeli pointer jest poprawny i najlepiej jak wiesz, że to obiekt zCObject)
To nie jest czysty daedalus, że jak dasz w hlp_getnpc postać, której nie ma w świecie to tylko log do zspy pójdzie.
Tutaj trzeba być uważnym, bo się korzysta z niebezpiecznych rozwiązań w celu dostania się do pamięci niedostępnej normalnie.
Dlatego trzeba dobrze to przeanalizować, bo inaczej będzie ci wywalać.

A tutaj masz dowód, że ci tego po prostu nie hookuje jak dałeś tam len 2 (HookEngineF wywołuje HookEngineI)
func void HookEngineI(var int address, var int oldInstr, var int function) {

    var int SymbID;         // Symbol index of 'function'
    var int ptr;            // Pointer to temporary memory of the old instruction
    var int relAdr;         // Relative address from 'address' to new assembly code

    // ----- Safety checks -----
    if (oldInstr < 5) {
        PrintDebug("HOOKENGINE: oldInstr is too small. The minimum required length is 5 bytes.");
        return;
    };

A jak chcesz jeszcze znaleźć gdzie jest błąd, na podstawie tego co ci do zspy daje ikarus, to możesz pobrać decdata stąd: https://forum.worldofplayers.de/forum/threads/1151032-Tool-DecDat
I tam dajesz gothic.dat, szukasz tej funkcji i dajesz potem tokens i szukasz instrukcji początek + tyle bajtów ile ci wyświetla (tutaj wyświetla w 10, a tam masz w 16 adresy)
To też ci wszystkie nie powie, ale z tego tokens można wyczytać miejsce błędu.

Nie mam teraz nawet g1 na kompie, ale raczej ta metoda ma takie same argumenty w g1 jak w g2, więc raczej adres do pointera itemu masz w esp+4, ale pewnie może też być czasem null, więc to trzeba sprawdzić po mem_readint.
 
while(false) Do();

DerDrache

DerDrache

Użytkownicy
posty18
Propsy3
ProfesjaProgramista
  • Użytkownicy
OK, jednak masz rację. Zmylił mnie fakt, że wcześniej, gdy podałem nieodpowiednią długość oldInstr w HookEngine, to gra mi sie od razu crashowala przy hookowaniu. A tu nie. Podejrzewam, ze wtedy crashowało się jeśli trafiłem akurat "w środek" gdzieś w bajcie między instrukcjami. Pozostaje znaleźć ten item w EquipItem (co bedzie raczej proste jako ze ta funkcja bierze go jako param; podobnie juz zrobiłem przy upuszaniu w DoDropVob) i nadać co trzeba.

//ed.
wszystko zdaje się działać
 
GOTHIC I: AMPLIFIED



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