Czasowe zwiększenie dmg 4030 17

O temacie

Autor pagi111

Zaczęty 17.10.2018 roku

Wyświetleń 4030

Odpowiedzi 17

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Chciałem zrobić coś z efektem czasowego zwiększenia obrażeń, np. miksturę, czar, itp. To tak na początek, żeby właśnie nauczyć się używania funkcji zwiększającej dmg. Potem mam ambitny plan zrobienia czegoś takiego, żeby damage zmieniał się w zależności od tego, który atak w sekwencji jest wyprowadzany, ale po kolei :P

Patrzyłem na ten wątek https://themodders.org/index.php?topic=28962.0 i ten na https://forum.worldofplayers.de/forum/archive/index.php/t-1347048.html. Niestety, jak na razie nie za wiele rozumiem z tych funkcji. Mógłby to ktoś wytłumaczyć dokładniej?

Tzn. np w skrypcie Preriowego Ścierwojada, czyli tym:
Spoiler
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg)
{
   // Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden.
    return dmg;
};
   
   
func void _DMG_OnDmg()
{
    EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI);
};
func void InitDamage()
{
    const int dmg = 0;
    if (dmg) { return; };
    HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg);
    dmg = 1;
};
mamy 3 funkcje.

1) I teraz tak, pierwsza ma 3 argumenty, które potem są określone jako (EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI) - co to w ogóle oznacza? Czy ja tu mam cokolwiek zmieniać, podkładać jakieś swoje zmienne, czy to ma po prostu zostać tak, jak jest? Co znaczy EDI, EBP, itp.?

2) Druga sprawa: w funkcji InitDamage() co oznacza ta liczba przy hook engine 6736583 ? Jak wyczytałem na WoP to chyba jest funkcja do której podpinamy czy hookujemy naszą funkcję - ale co to jest za funkcja? Gdzie mogę sprawdzić te numery funkcji? I znowu pytanie, czy mam tutaj cokolwiek zmieniać?

3) Gdzie ustalam o ile ma się mi zmienić dmg np. po wypiciu mikstury? No bo jak rozumiem mogę zrobić, że np po wypiciu dmg zwiększa się 2 razy/o 50%/o 10%, itp. Gdzie to ustawić?

4) Co mam wpisać w OnState w skrypcie swojej mikstury? Wypicie mikstury ma włączać którąś z tych trzech funkcji (jeśli tak, to którą?) czy jeszcze jakąś inną funkcję? (Pomijam teraz użycie Timera - wiadomo, że to trzeba zrobić, ale to umiem - tutaj pytam tylko konkretnie o funkcję zwiększania obrażeń)

5) I gdzie mam umieścić te funkcje? W startupie.d czy powiedzmy w pliku z moją miksturą? Tzn one mają "chodzić" cały czas po włączeniu gry czy tylko się włączać na chwilę po wypiciu mikstury?

To tyle na początek  :D pomóżcie mi to zrozumieć, bo chyba sam do tego nie dojdę  :/
 

Bogdan Zwei

Bogdan Zwei

Użytkownicy
Wulgarny skurwiel pierdolony.
posty1864
Propsy541
Profesjabrak
  • Użytkownicy
  • Wulgarny skurwiel pierdolony.
1) Określenie npców, ten co atakuje i dostaje wpierdol, na końcu jest pobieranie obrażeń z systemu.
2) Funkcja zadawania obrażeń, znajdziesz ją używając IDA.
3) Pokombinuj. Nic tutaj trudnego. Dosłownie poziom "podstawówki", o ile mogę tak powiedzieć.
4) Popatrz do 3.
5) Jest tutorial tutaj, sam robiłem. Startup.
 
:ok: zachęca do dalszej pomocy. Nie zapominaj o tym!

Prywatne wiadomości typu "Ej, pomocy" kasuję od razu. Od tego jest forum, a nie PW.

To me, defeat in anything is merely temporary, and its punishment is but an urge for me to greater effort to achieve my goal. Defeat simply tells me that something is wrong in my doing; it is a path leading to success and truth.

In order to realize our true self we must be willing to live without being dependent upon the opinion of others.

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
1) EBP, ESP, EAX, EDI, ESI i inne to rejestry assemblera, więcej o nich znajdziesz w tym wątku:
https://themodders.org/index.php?topic=27030.msg1258154#msg1258154

2) Ta liczba, to adres, pod którym znajduje się funkcja w silniku gry, pod którą chcemy się podczepić.
Hook pozwala nam podpiąć własną funkcje pod tą oryginalną (dzięki czemu wiemy, kiedy gra wywołała daną funkcje, np: jak założysz hook na funkcje oCGame::Pause, będziesz wiedział, kiedy gra została spauzowana, czyli kiedy ta funkcja została wywołana przez silnik). Krótko mówiąc twoja funkcja wywoła się wtedy, gdy wywoła się ta silnikowa, na którą zakładasz hook.

Adresy tych funkcji najprościej wyciągnąć przez jakiś disassembler taki jak np: IDA czy OllyDbg.
Oczywiście, na WoG'u jest też ich spis, wystarczy poszukać, lub alternatywnie możesz pobrać przykład modułu AST, tam znajdziesz plik tekstowy G2_Names, w którycm znajduje się większość adresów.

3) Tak jak pisał Bogdan, wystarczy trochę pokombinować, sam możesz sobie obliczyć taki procent, wiedząc, ile zada dmg twoja postać i potem wyznaczyć bonusowy dmg (np: bazowyDMG + polowaBazowegoDMG)

4) Jak już przejdziesz do realizacji, to raczej będziesz wiedział co gdzie dodać ;).

5) Część kodu na pewno musi zostać zainicjowana (Startup), reszta zależy od tego, jak chcesz to wykonać.
 

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy

pagi111

Czasowe zwiększenie dmg
#3 2018-10-17, 15:55(Ostatnia zmiana: 2018-10-18, 09:13)
Dzięki, najbardziej szczerze mówiąc pomógł mi Twój tutorial Bogdan o mieczach srebrnych i stalowych, bo chyba jego miałeś na myśli :P  https://themodders.org/index.php?topic=23935.msg1184853#msg1184853
Co do tych rejestrów assemblera i adresów funkcji, to dzięki Patrix za wyjaśnienie, coś tam zaczynam powolutku łapać, ale na razie jeszcze niewiele z tego rozumiem :P no ale do tej funkcji nie jest mi potrzebne dogłębne rozumienie tego - ważne, że działa.

Ostatecznie na razie żadnej części kodu nie inicjowałem w startupie, tylko w pliku z miksturą, bezpośrednio przed instancją samej mikstury. Gdy dawałem to do starup, był błąd, że nie znaleziono funkcji InitDamage. Wynikałoby z tego, że plik startup ładuje się gdzieś pod koniec, a odniesienie do tej funkcji jest w pliku z miksturami, który pewnie w takim razie ładuje się wcześniej. Tak czy inaczej, nie ma to chyba większego znaczenia. Mam jeszcze parę pytań:
1) ściągnąłem skrypt, o którym pisał Bogdan w swoim poradniku i skopiowałem go całego, czyli wygląda on tak:
Spoiler
class oSDamageDescriptor {
var int validFields; // zDWORD 0x00

var int attackerVob; // zCVob* 0x04
var int attackerNpc; // oCNpc* 0x08
var int hitVob; // zCVob* 0x0C
var int hitPfx; // oCVisualFX* 0x10
var int itemWeapon; // oCItem* 0x14

var int spellID; // zDWORD 0x18
var int spellCat; // zDWORD 0x1C
var int spellLevel; // zDWORD 0x20

var int dmgMode; // zDWORD 0x24
var int weaponMode; // zDWORD 0x28

var int dmgArray[8]; // zDWORD[8] 0x2C Vermutlich vor Abzug der Rüstungswerte
var int dmgTotal; // zREAL 0x4C // Nach Abzug der Rüstungswerte?
var int dmgMultiplier; // zREAL 0x50

var int locationHit[3]; // zVEC3 0x54
var int directionFly[3]; // zVEC3 0x58

var string visualFXStr; // zSTRING 0x5C

var int duration; // zREAL 0x60
var int interval; // zREAL 0x64
var int dmgPerInterval; // zREAL 0x68
var int dmgDontKill; // zBOOL 0x6C

var int bitfield; // 1 -> Once, 2 -> finished, 4 -> isDead, 8 -> isUnconscious

var int azimuth; // zREAL 0x74
var int elevation; // zREAL 0x78
var int timeCurrent; // zREAL 0x7C
var int dmgReal; // zREAL 0x80
var int dmgEffective; // zREAL 0x84
var int dmgArrayEffective[8]; // zDWORD[8] 0x104 // Vermutlich nach Abzug der Rüstungswerte, ohne Mindestschaden
var int vobParticleFX; // zCVob* 0x108
var int particleFX; // zCParticleFX* 0x10C
var int visualFX; // zCVisualFX* 0x110
};


func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg, var int dmgDescriptorPtr) {
var oSDamageDescriptor dmgDesc; dmgDesc = _^(dmgDescriptorPtr);
var c_npc attackerNpc; attackerNpc = _^(attackerptr);
        var c_npc victimNpc; victimNpc = _^(victimPtr);
var c_npc slf; slf = _^(attackerptr); // atakujący
var c_npc oth; oth = _^(victimPtr); // ofiara
var C_Item EQWeapon; EQWeapon = Npc_GetReadiedWeapon(slf); // broń wyciągnięta
if (Hlp_IsItem(EQWeapon, ItMW_Addon_Knife01)) && (SPL_Stop_Moja == 0)

{
dmg = dmg*10;//tutaj piszemy formułkę, ja napisałem coś z dupy
};

// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden
return dmg;
};


var int _DMG_DmgDesc;

func void _DMG_OnDmg_Post() {
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI, _DMG_DmgDesc);
};

func void _DMG_OnDmg_Pre() {
_DMG_DmgDesc = ESI; // I'm preeeeetty sure it won't get moved in the meantime...
};



func void InitMojaDamage()
{
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg_Post);
const int oCNpc__OnDamage_Hit = 6710800;
HookEngineF(oCNpc__OnDamage_Hit, 7, _DMG_OnDmg_Pre);
dmg = 1;
};
Tak z czystej ciekawości czy wszystko, co w nim jest, jest mi potrzebne? W wątku, który podałem w pierwszym poście jest tego znacznie mniej, więc się po prostu zastanawiam. W szczególności to na początku: class oSDamageDescriptor, te funkcje _pre i _post i te linijki:
var c_npc slf; slf = _^(attackerptr); // atakujący
var c_npc oth; oth = _^(victimPtr); // ofiara
2) druga sprawa to jak Wam się chce, to zerknijcie na mój skrypt i powiedzcie czy to jest dobrze, czy ewentualnie można coś uprościć/zmienić. Oprócz tego, co dałem powyżej w swoim skrypcie mam to:
Spoiler
// *********
// MOJA
// *********
const int SPL_Duration_Moja =   8;
var int SPL_Time_Moja; // To tylko potrzebne do funkcji timera
var int SPL_Stop_Moja; // Tez potrzebne do timera



func void TimerMoja() //Funkcja timera
{
  if(!MEM_GAME.pause_Screen) // jeśli gra jest zatrzymana...
{
SPL_Time_Moja = SPL_Time_Moja + 1; // Czyli co sekunde licznik timera bedzie dodawal sekunde
  print(IntToString(SPL_Time_Moja)); // To tylko taki print - testowe, zeby sprawdzac czy kod dziala i jak liczy
if(SPL_Time_Moja == 1)
{
SPL_Stop_Moja = 0;
print("Jest dmg"); // test. chociaz można zostawić
InitMojaDamage();
};
if(SPL_Time_Moja == SPL_Duration_Moja) // Jesli uplynie 10 sec, tzn czas zdefiniowany na poczatku jako czas trwania
{
print("Już nie ma dmg"); // Testowe, chociaz mozna tez zostawic jako informacje, gdy sie skonczy czar
SPL_Stop_Moja = 1;
};
};
};


func void TimerMojaApply() //funkcja wywolujaca timer
{
FF_ApplyOnceExt (TimerMoja, 1000, -1); // wywoluje timer, co 1 sek, na czas trwania zaklecia
};


INSTANCE ItPo_Moja_01(C_Item)
{
name = NAME_Trank;

mainflag = ITEM_KAT_POTIONS;
flags = ITEM_MULTI;

value = Value_MegaDrink;

visual = "ItPo_Mana_01.3ds";
material = MAT_GLAS;

on_state[0] = TimerMojaApply; SPL_Time_Moja = 0;
scemeName = "POTIONFAST";

wear = WEAR_EFFECT;
effect = "SPELLFX_MANAPOTION";

description = "DMG Elixier";

TEXT[1] = "DMG Steigern";
COUNT[1] = 2;

TEXT[5] = NAME_Value;
COUNT[5] = Value_MegaDrink;

};
3) napotkałem bardzo dziwny problem. Otóż w OnState mam to:
TimerMojaApply; SPL_Time_Moja = 0;reset time na 0 jest potrzebny w razie gdyby wypiło się drugą miksturę, podczas działania pierwszej, żeby się wydłużał czas działania. Uważam jednak, że działałoby to troszkę lepiej, gdybym zamienił kolejność na:
SPL_Time_Moja = 0; TimerMojaApply;I tu jest właśnie ten problem, bo gdy tak zrobię, to zSpy pokazuje mi błąd - expected ";". Najlepsze jest to, że w pierwszym przypadku działa, a w drugim nie. Co więcej, jeśli wstawiam tam coś innego zamiast SPL_Time_Moja = 0 to też działa. No nie rozumiem tego zupełnie, skąd nagle taki błąd. Oczywiście popatrzyłem dobrze i wstawiam na końcu ";", więc naprawdę nie wiem o co z tym chodzi :P

@Edit
Co do punktu 3:
Doszedłem do wniosku, że może nie może być w onstate =. bo już jeden taki znak jest. I że może musi tam być jakaś funkcja. Więc na szybko zrobiłem:
func void SetSPL_Time_Moja()
{
SPL_Time_Moja = 0;
};
Spoko, Gothic się uruchamia, ale gdy chcę otworzyć eq albo insertować w konsoli moją miksturę, to gra crashuje i pojawia się taki błąd (najpierw ta mniejsza ramka, potem access violation - tu zrobiłem na jednym zdjęciu dla wygody):
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
func void TimerMojaApply() //funkcja wywolujaca timer
{
FF_ApplyOnceExt (TimerMoja, 1000, -1); // wywoluje timer, co 1 sek, na czas trwania zaklecia
};

Ta funkcja powinna być wywołana w startupie, skoro tworzysz jeden timer, to nie musisz jej wywoływać przy kazdym użyciu mikstury.

Wywala ci błąd tu:

on_state[0] = TimerMojaApply; SPL_Time_Moja = 0;

Bo ten zapis jest nieprawidłowy, do on_state[0] musisz przypisać tylko funkcje TimerMojaApply, a dokładniej mówiąc, przypisać referencje na tą funkcje, zerowanie SPL_TIME_Moja, powinieneś dodać wewnątrz funkcji TimerMojaApply, nawet gdyby ten zapis nie byłby błędny, to wyzerowanie wykonałoby się tylko przy tworzeniu instancji.

PS: Klasa oCDamageDescriptor nie jest ci potrzebna, by założyć hooki. A te funkcje _pre _post już tak, bo pełnią one dosyć ważną rolę ;p.
 

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Hmm, no ale jeśli timer się będzie wywoływał w startupie, to przecież od razu po wczytaniu gry dostanę bonus do dmg, a nie po wypiciu mikstury. No i co wtedy powinienem dać w on_state?

Poza tym tak sobie pomyślałem, że po co taką funkcję wywoływać w startupie skoro mogę tylko po wypiciu mikstury. Zwłaszcza jeśli tego typu mikstur stworzę powiedzmy 10, do tego jakiś czar, może jeszcze jakiś inny efekt i będę miał powiedzmy 20 timerów, to po co wszystkie się mają wywoływać przy wczytaniu gry, skoro mogą tylko wtedy, gdy jest taka potrzeba? Nie wiem czy to jest jakieś obciążenie dla gry, no ale nie widzę i tak sensu, żeby to tak robić. Chyba, że czegoś nie biorę tu pod uwagę?

on_state[0] = TimerMojaApply; SPL_Time_Moja = 0;Właśnie ten zapis chyba jest prawidłowy, tzn. działa w grze. Nie działa tylko, gdy zmienię kolejność :p czyli tak:
on_state[0] = SPL_Time_Moja = 0; TimerMojaApply;
Co więcej, nie mam pomysłu jak przypisać zerowanie SPL_TIME_Moja wewnątrz funkcji, bo przecież to nie ma się zerować zawsze, a tylko wtedy, gdy akurat zostaje wypita mikstura.
 

Toworish

Toworish

Użytkownicy
http://chomikuj.pl/ToWoRiSh
posty1664
Propsy254
ProfesjaNierób
  • Użytkownicy
  • http://chomikuj.pl/ToWoRiSh
Musisz ją zerować gdy kończysz timer xd kurła weź sobie od nowa napisz te skrypty. Ponazywaj jakoś lepiej, a nie SPL z tutka xd
 
Niebawem...Pierdolnę se poradniki do Goticzka. Albo i nie, bo sie mnie nie chce.

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy

pagi111

Czasowe zwiększenie dmg
#7 2018-10-18, 09:07(Ostatnia zmiana: 2018-10-18, 11:54)
Dobra, dobra, wiem, że te nazwy to tak całkiem ściągnięte, ale to akurat sobie skopiowałem ze swojego innego skryptu, gdzie miałem timer do czaru i dlatego tak :P ale spokojnie, jak wszystko ogarnę, to ponazywam. To nie jest tak, że nawet nie wiem co kopiuję :D

Ale wracając do rzeczy, zauważcie, że mam dwie zmienne SPL_Time_Moja i SPL_Stop_Moja. _Stop rzeczywiście zmienia się na końcu timera i o to chodzi. Ale _Time nie może się zerować na końcu timera, bo wtedy cały efekt zaczynałby się od początku i tak w kółko. TYLKO wypicie mikstury ma zerować timer, ponieważ efekt ma się przedłużać lub zaczynać od początku TYLKO po ponownym wypiciu mikstury, a nie jakoś sam z siebie.

Jestem pewien, że to jest dobrze napisane, bo działa w grze tak, jak ma być ;) poza tym miałem podobny problem z czarem zwiększającym pancerz, tyle, że tam bez problemu dodałem właśnie zerowanie czasu podczas rzucania czaru, a w miksturze z jakiegoś powodu nie mogę tego zrobić w on_state (tzn. no mogę, ale tak jak opisałem, tylko PO włączaniu timera, a przydałoby się PRZED). I właśnie nie rozumiem dalej, dlaczego tak się dzieje.

A propos, chciałem wrzucić w poprzednim poście zdjęcie z tym błędem i ono się ładuje i niby jest, ale potem po jakimś czasie znika. Jak się tu wrzuca zdjęcia, coś robię nie tak? Wrzucam je z chomika. Może byłby jakiś trop, jakbyście zobaczyli o czym jest błąd :P

@Edit
Dobra, zrobiłem tak, że działa :P
Napisałem sobie taką funkcję:
func void SetSPL_Time_Moja()
{
SPL_Time_Moja = 0;
TimerMojaApply();
};

a w on_state to:
on_state[0] = SetSPL_Time_Moja;
Działa tak, jak chciałem ;) Dzięki za pomoc, ale to jeszcze nie koniec moich problemów egzystencjalnych :P

                                                                                                                                                                                                                                                                                                                                                   

NO WIĘC TERAZ KOLEJNY ETAP :P
Pomijając już całkowicie tę miksturę, bo to było tylko na próbę. Chcę zrobić stały efekt, żeby każdy cios w kombinacji zadawał coraz więcej dmg. Przykładowo mistrz walki 1h ma 4 ataki, 1- to normalny dmg, 2- 150% dmg, 3- 200%, 4 - 250%. Chodzi o to, żeby się bardziej opłacało wyprowadzać całe kombinacje ciosów. Wartości oczywiście przykładowe.

Pytanie teraz jak to zrobić :D Ja mam pomysł taki, żeby użyć funkcji
if(MEM_KeyState(KEY_W)==KEY_PRESSED)i połączyć ją z bardzo szybkim timerem, takim co klatkę. No i zrobiłbym to tak: każdy atak w sekwencji trwa określoną liczbę klatek, więc piszę po prostu warunki, że jeśli wcisnąłem klawisz W && time jest powiedzmy o 1-25, czyli klatki pierwszego ataku (przykładowe klatki, z głowy piszę) to dmg=dmg, jeśli W jest wciśnięty znowu i time jest od 25-50, czyli przykładowe klatki drugiego ataku, to dmg=dmg*1,5, itd. Wiadomo, tam trzeba by raczej dodać jeszcze parę warunków. No ogólnie sporo pisania, ale chyba do zrobienia.

Teraz tak, problemy, jakie już przy tym rozwiązaniu widzę:
1) sterowanie musi być z G1, tzn, że atak jest po przytrzymaniu kliknięcia myszą i wciśnięciu klawisza W - ja akurat lubię sterowanie z G1, ale niektórzy może grają z innym. Albo sobie ustawią atak nie pod W, tylko pod innym klawiszem. Jak to rozwiązać?
Może zamiast funkcji if(MEM_KeyState(KEY_W)==KEY_PRESSED)jakaś inna, np. taka, która sprawdza czy postać wyprowadza akurat atak. No tutaj Was proszę o pomoc, jeśli znacie taką funkcję albo macie inny pomysł.

2) Dodatkowo, tutaj musi być wciśnięty przycisk myszy i dodatkowo klawisz W (żeby się to nie włączało przy zwykłym chodzeniu). Czy tą funkcją KeyState da się też sprawdzać wciśnięcie przycisku myszy, czy tylko klawisze na klawiaturze?

3) to działałoby tylko dla gracza. Jak zrobić, żeby NPC też dostawali dodatkowy dmg z każdym następnym atakiem? Może też inna funkcja po prostu byłaby rozwiązaniem.

4) tak czy inaczej, z moim pomysłem jest sporo pisania, bo skrypt trzeba zrobić inny do każdego poziomu walki (nowicjusz-wojownik-mistrz), tzn. będą inne klatki i osobno do broni 1h i 2h. Więc jeśli macie pomysł na funkcję, która zamiast sprawdzać czy jest wciśnięty klawisz i które aktualnie są klatki, sprawdza raczej który atak w sekwencji jest akurat wyprowadzany, to kolosalnie uprościłoby pracę. Nie wiem czy wgl taka funkcja istnieje, ale może macie jakieś pomysły.
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
Kombinujesz xD.

Skoro masz już założony hook, który wywołuje się w momencie, gdy ty lub NPC zadacie DMG, to czemu tam wszystkiego nie okodzić? Możesz sprawdzić, czy gracz posługuje się mieczem i później odpowiednio to okodzić. W argumencie w hooku masz obecnie zadany dmg, na samym początku musisz sprawdzić, czy atakującym jest gracz, jeśli tak, to wtedy sprawdzić czy gracz ma jakiś bonus do dmg (jakaś zmienna, z której korzysta gracz). Jeśli ma, to po prostu odpowiednio doliczyć do obecnego DMG dodatkowy dmg.

Z bonusem dla NPC jest trochę więcej problemów, dlatego, że obiektów NPC może być dużo, a gracz jest tylko jeden, więc nie możesz nadać jednej zmiennej dla każdego NPC ;p. Można wykorzystać tablicę AIVAR by coś podziałać.

PS: Ten hook jest zrealizowany specjalnie w taki sposób, byś mógł wpływać na damage.
 

Bogdan Zwei

Bogdan Zwei

Użytkownicy
Wulgarny skurwiel pierdolony.
posty1864
Propsy541
Profesjabrak
  • Użytkownicy
  • Wulgarny skurwiel pierdolony.
Nie chcę być chujem, ale większość tego, co chcesz zrobić jest w Ikarusie, wystarczy poszukać i przerobić delikatnie. Da się to zrobić w inny, lepszy sposób. Popatrz do tego tematu z woga o obszarowych obrażeniach i pokombinuj. Potem będziesz na etapie, gdzie i tak nic nie zrobisz, bo do tego trzeba wiedzy, której ty nie masz.
 
:ok: zachęca do dalszej pomocy. Nie zapominaj o tym!

Prywatne wiadomości typu "Ej, pomocy" kasuję od razu. Od tego jest forum, a nie PW.

To me, defeat in anything is merely temporary, and its punishment is but an urge for me to greater effort to achieve my goal. Defeat simply tells me that something is wrong in my doing; it is a path leading to success and truth.

In order to realize our true self we must be willing to live without being dependent upon the opinion of others.

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy

pagi111

Czasowe zwiększenie dmg
#10 2018-10-18, 15:58(Ostatnia zmiana: 2018-10-18, 16:10)
@Bogdan Zwei
Cytuj
Potem będziesz na etapie, gdzie i tak nic nie zrobisz, bo do tego trzeba wiedzy, której ty nie masz.
Jak bym miał wiedzę, to bym nie zakładał wątku na forum. Od tego chyba forum jest, żeby swoją wiedzę pogłębiać. Jeszcze wczoraj nie wiedziałem w ogóle jak zmieniać dmg, dziś wiem, bo mi to pomogliście zrozumieć. Jak trafię na inny problem, to też go rozwiążę, gdy mi ktoś pomoże.

@Patrix9999
Zaczynam chyba rozumieć, ale:
1) żeby damage zwiększał się w zależności od tego, który jest atak w sekwencji, to funkcja musi jakoś sprawdzać, który to jest atak w sekwencji :D no i właśnie jak to zrobić?
Hmm, chyba, że zrobiłbym tak: w momencie zadawania dmg, jakaś tam zmienna ustawia się na 1, dmg = 1, jeśli w ciągu 25 klatek znowu zadaje się dmg, to zmienna = 2, dmg = 150%, itd. Jeśli w ciągu tych 25 klatek nie było dmg, to zmienna = 1, czyli dmg normalny. Jeśli o to Ci chodziło, to tak spróbuje? :P

2) druga sprawa, chciałem się jeszcze upewnić o której funkcji mówisz pisząc
Cytuj
masz już założony hook, który wywołuje się w momencie, gdy ty lub NPC zadacie DMG
jeśli dobrze rozumiem to chodzi o to:
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg_Post);
Czyli on się wywołuje przy tej funkcji silnika: 0x66CAC7? I tu właśnie mam problem, bo ściągnąłem sobie listę funkcji silnika, o której pisałeś w op na moj pierwszy post. Tyle że tam tej funkcji nie ma. Próbowałem szukać przez jej nr albo nazwę, ale nie ma jej w tym spisie.

const int oCNpc__OnDamage_Hit = 6710800;
HookEngineF(oCNpc__OnDamage_Hit, 7, _DMG_OnDmg_Pre);
Ta funkcja tam już jest, ale nie wiem czemu nie ma tej pierwszej. Ta lista jest niekompletna czy co? I sprawdzałem w obu, tzn w tej z WoGa i w G2_Names ze ściągniętego przykładowego modułu AST.
@Edit
Szukałem też przez disassemblera IDA, więc lista jest ok, tej funkcji po prostu nie ma :D No przyznam szczerze, że nie rozumiem o co chodzi...
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
Tego adresu nie ma na liście, ponieważ hook jest nałożony nie na początku funkcji, a w jej wnętrzu, tuż przed pushem obliczonego DMG'a (jest tak zrealizowany, by można było mieć wpływ na DMG).

Co do wykrywania, w którym jesteśmy uderzeniu, musiałbym poszukać jakiejś funkcji, która pozwala na sprawdzenie tego, na pewno da się to zrobić.
 

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
@Patrix9999
Jakby Ci się udało taką funkcję znaleźć, to byłbym super, bo ja jeszcze chyba na tyle nie ogarniam tego wszystkiego. Zwłaszcza, że taka funkcja to pewnie właśnie w silniku jest, więc to już w ogóle :P
 

Splash

Splash

Moderator
posty4207
Propsy3403
ProfesjaNierób
  • Moderator
Nie sprawdzałem, ale powinno zwracać sekwencję combo:
var oCNpc her; her = Hlp_GetNpc(hero);
var oCAniCtrl_Human ani; ani = _^(her.anictrl);
var int sekwencja; sekwencja = ani.comboNr;
 
Nie zajmuję się multiplayerami do Gothica. Przestańcie zawracać mi tym głowę...
Ps. Siemekk ma downa i śpi w pufie

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
@Splash dokładnie tak jest :D
Czyli wszystko działa, tak jak chciałem, dzięki wszystkim za pomoc ;)
Cały skrypt wygląda tak:
Spoiler
class oSDamageDescriptor {
var int validFields; // zDWORD 0x00

var int attackerVob; // zCVob* 0x04
var int attackerNpc; // oCNpc* 0x08
var int hitVob; // zCVob* 0x0C
var int hitPfx; // oCVisualFX* 0x10
var int itemWeapon; // oCItem* 0x14

var int spellID; // zDWORD 0x18
var int spellCat; // zDWORD 0x1C
var int spellLevel; // zDWORD 0x20

var int dmgMode; // zDWORD 0x24
var int weaponMode; // zDWORD 0x28

var int dmgArray[8]; // zDWORD[8] 0x2C Vermutlich vor Abzug der Rüstungswerte
var int dmgTotal; // zREAL 0x4C // Nach Abzug der Rüstungswerte?
var int dmgMultiplier; // zREAL 0x50

var int locationHit[3]; // zVEC3 0x54
var int directionFly[3]; // zVEC3 0x58

var string visualFXStr; // zSTRING 0x5C

var int duration; // zREAL 0x60
var int interval; // zREAL 0x64
var int dmgPerInterval; // zREAL 0x68
var int dmgDontKill; // zBOOL 0x6C

var int bitfield; // 1 -> Once, 2 -> finished, 4 -> isDead, 8 -> isUnconscious

var int azimuth; // zREAL 0x74
var int elevation; // zREAL 0x78
var int timeCurrent; // zREAL 0x7C
var int dmgReal; // zREAL 0x80
var int dmgEffective; // zREAL 0x84
var int dmgArrayEffective[8]; // zDWORD[8] 0x104 // Vermutlich nach Abzug der Rüstungswerte, ohne Mindestschaden
var int vobParticleFX; // zCVob* 0x108
var int particleFX; // zCParticleFX* 0x10C
var int visualFX; // zCVisualFX* 0x110
};


func int DMG_OnDmgCombo(var int victimPtr, var int attackerPtr, var int dmg, var int dmgDescriptorPtr)
{
var oSDamageDescriptor dmgDesc; dmgDesc = _^(dmgDescriptorPtr);
var c_npc attackerNpc; attackerNpc = _^(attackerptr);
    var c_npc victimNpc; victimNpc = _^(victimPtr);
var c_npc slf; slf = _^(attackerptr); // atakujący
var c_npc oth; oth = _^(victimPtr); // ofiara
var oCNpc her; her = Hlp_GetNpc(hero);
var oCAniCtrl_Human ani; ani = _^(her.anictrl);
var int sekwencja; sekwencja = ani.comboNr;

if (sekwencja == 0)  //&& (Npc_HasReadiedMeleeWeapon (hero)) - w sumie niepotrzebne, bo sekwencje działają tylko w melee
{
dmg = dmg;
print(IntToString(dmg));
}

else if (sekwencja == 1)
{
dmg = dmg*5;
print(IntToString(dmg));
}

else if (sekwencja == 2)
{
dmg = dmg*10;
print(IntToString(dmg));
}
else if (sekwencja == 3)
{
dmg = dmg*20;
print(IntToString(dmg));
};

return dmg;
};


var int _DMG_DmgDesc;

func void _DMG_OnDmg_Post() {
EDI = DMG_OnDmgCombo(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI, _DMG_DmgDesc);
};

func void _DMG_OnDmg_Pre() {
_DMG_DmgDesc = ESI; // I'm preeeeetty sure it won't get moved in the meantime...
};


func void InitComboDamage()
{
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg_Post);
const int oCNpc__OnDamage_Hit = 6710800;
HookEngineF(oCNpc__OnDamage_Hit, 7, _DMG_OnDmg_Pre);
dmg = 1;
};

Jedyne, co można by ewentualnie zmienić to to, że obecnie dodatkowy dmg naliczany jest tylko w zależności od numeru ciosu w sekwencji. Czyli nawet jeśli pierwsze uderzenie nie trafi w przeciwnika, to drugie i tak zada większe obrażenia. Idealnie byłoby chyba, gdyby dodać jeszcze jakiś warunek, że dmg zmienia się tylko jeśli przeciwnik rzeczywiście zostanie trafiony. Może coś nad tym jeszcze pomyślę :P
 

Splash

Splash

Moderator
posty4207
Propsy3403
ProfesjaNierób
  • Moderator
Tak na szybko wymyśliłem:
var int previous;

if (sekwencja - previous == 1) {
    previous = sekwencja;
}
else {
    sekwencja = 0;
};
 
Nie zajmuję się multiplayerami do Gothica. Przestańcie zawracać mi tym głowę...
Ps. Siemekk ma downa i śpi w pufie

Siemekk

Siemekk

Złote Wrota
Untersturmfuhrer
posty2143
Propsy1151
ProfesjaProgramista
  • Złote Wrota
  • Untersturmfuhrer
Wiesz, że w MDS też można dopisać zwiększenie obrażeń :F?
 

P.S A Splash w szafie i nie ma psychy by mi dać bana.

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
No ale co to da, że w mds będzie? :P
 


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