Hej, to znowu ja.
Jak pewnie wiecie, strzała/pocisk magiczny wystrzelona/y przez NPC ignoruje wszystkich NPC po co drodze do celu, chyba że ten NPC to potwór lub ork. Potrzebuję to zmienić, a dokladnie, kiedy NPC który strzela jest orkiem i ten NPC po drodze jest rownież orkiem, to strzała przez niego przelatuje
Szukajac rozwiązan, trafiłem na teoretycznie rozwiązanie niemal gotowe, idealne w Gothic Free Aim. Otóż hookują oni tam oCAIArrow::CanThisCollideWith(zCVob*) przed samym koncem funkcji, sprawdzając kilka warunków i co najważniejsze dla mnie, pobierając strzelającego z oCAIArrow, a "ofiarę" oczywiście z parametru zCVob.
(
https://github.com/szapp/GothicFreeAim/blob/master/_work/data/Scripts/Content/GFA/_intern/collision.d #554, GFA_ExtendCollisionCheck())
Niestety próby zhookowania tego u mnie całkowicie nie wypalają. Po zhookowaniu tego w miejscu w którym zrobili to tworcy GFA, nic sie nie dzieje, funkcja sie nie wywołuje nigdy, po prostu nic się nie dzieje. Po shookowaniu tego na początku(co ogólnie nie ma raczej sensu, bo chce zmodyfikowac wartosc zwracana) nastepuje crash w momencie próby edycji voblisty i wpisywania czegoś do rejestru.
Wygląda to mniej więcej tak (wersja z hookiem jak w GFA):
func void EVT_oCAIArrow_CanThisCollideWith()
{
var int collidingVobPointer; collidingVobPointer = MEM_ReadInt(ESP + 8);
var int arrowAI; arrowAI = MEMINT_SwitchG1G2(ESI, EDI);
if ((collidingVobPointer == 0) ||
(arrowAI == 0) ||
(!Hlp_Is_oCNpc(collidingVobPointer)))
{
return;
};
var C_Npc shooter; shooter = _^(MEM_ReadInt(arrowAI + oCAIArrow_origin_offset));
var C_NPC collidingNpc; collidingNpc = MEM_PtrToInst(collidingVobPointer);
if(C_NpcIsOrc(shooter) &&
C_NpcIsOrc(collidingNpc))
{
// var int ignoreVobList; ignoreVobList = MEM_ReadInt(arrowAI + oCAIArrowBase_ignoreVobList_offset);
// List_AddFront(ignoreVobList, collidingVobPointer);
// // // Increase reference counter, otherwise NPC/vob will be deleted on list destruction!
// var zCVob vob; vob = _^(collidingVobPointer);
// vob._zCObject_refCtr += 1;
// // Set return value of collision check to false
//ECX = 0;
} else
{
PrintScreen("Something differrent than orc hit", 15,54,"FONT_OLD_10_WHITE.TGA",_TIME_MESSAGE_GIVEN);
};
};
func void Hook_oCAIArrow_CanThisCollideWith()
{
HookEngineF(oCAIArrow_CanThisCollideWithAddr_positive, 6, EVT_oCAIArrow_CanThisCollideWith);
};
Wszystko rozbija się o pobranie z odpowiednich miejsc shootera i victima. Jak rozumiem, ten vob który przelatuje jest na ESP + 8, poniewaz jedno słowo juz zostalo dolozone na stos, i to by sie zgadzało z liczbą pushy:

(call zdejmuje tych 5 pushy/argumetow koło siebie)
Natomiast nie do konca rozumiem dlaczego oCAIArrow jest odczytywane z ESI zamiast ESP + 4(wszak jest to ukryty argument).
Ogółem cały koncept reprezentowania rejestrów w LeGo/Ikarusie jest dość niezrozumiały dla mnie.
Np. tutaj (całkiem inna funkcja, ale pewnie niedługo się za to zabiorę)
EDI = DMG_OnDmg(EBP, MEM_ReadInt(dmgDesc + 8), EDI, +dmgDesc, +dmg_IsHit);
powyzszy kawałek kodu powstał na kanwie implementacji onDmg, która będzie mi potrzeban do czego innego: EDI jako deadalusowa zmienna jest traktowany jako wartość, ale z drugiej strony w przypisaniu collidingVobPointera juz ESP traktujemy jako adres? wuteef?