Czasowy czar/mikstura a działanie po wczytaniu zapisu gry 6058 16

O temacie

Autor pagi111

Zaczęty 13.10.2018 roku

Wyświetleń 6058

Odpowiedzi 16

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Witam,

Zrobiłem czar, który tymczasowo zwiększa pancerz, inspirując się instrukcjami @Toworish a z tego wątku: https://themodders.org/index.php?topic=26931.0
Nie próbowałem jeszcze sposobu, który proponował @Siemekk , ale mam następujący problem, który związany jest z wczytywaniem zapisanego stanu gry. Jeśli efekt czasowy przeminie normalnie, to wszystko jest ok. Jednak problem pojawia w dwóch przypadkach:
1) rzucam czar, wtedy zapisuję grę i ją wczytuje
2) zapisuję grę, rzucam czar, wczytuje zapis sprzed rzucenia czaru (podczas gdy czar jeszcze trwa)
Problem jest taki, że efekt zostaje na stałe w pierwszym przypadku (bo po wczytaniu gry funkcja timera przestaje działać i nie odejmuje mi dodanego wcześniej pancerza), a w drugim przypadku, po ponownym rzuceniu czaru nie ma efektu zwiększenia pancerza, jest natomiast efekt odjęcia punktów, gdy czar przestaje działać (więc de facto permanentnie postać dostaje minus do pancerza).

Oto skrypt funkcji timera
Spoiler
const int SPL_Cost_ImproveArmour = 1; // Koszt czaru - mana
const int SPL_Improve_ImproveArmour = 10; // Sila czaru - o ile zwieksza armour
const int SPL_Duration_ImproveArmour = 15; // Czas trwania czaru
const int SPL_Time_ImproveArmour = 0; // To tylko potrzebne do funkcji timera
const int SPL_Stop_ImproveArmour = 0; // Tez potrzebne do timera


// ****************
// Improve Spells Functions
// ****************

func void TimerImproveArmour() //Funkcja timera
{
  SPL_Time_ImproveArmour = SPL_Time_ImproveArmour + 1; // Czyli co sekunde licznik timera bedzie dodawal sekunde
  print(IntToString(SPL_Time_ImproveArmour)); // To tylko taki print - testowe, zeby sprawdzac czy kod dziala i jak liczy
if(SPL_Stop_ImproveArmour == 0) // Czyli tylko jesli parametr Stop_ r˘wna sie 0 (wyjasnienie nizej), wywola to zwiekszenie pancerza
&&(SPL_Time_ImproveArmour == 1)
{
print("Teraz sie powinno zw o 5"); // Testowe
B_RaiseProtection (hero, PROT_BLUNT, 5);
B_RaiseProtection (hero, PROT_POINT, 5);
}
if(SPL_Time_ImproveArmour == 2) // W pierwszej sekundzie...
{
SPL_Stop_ImproveArmour = 1; // ...ustawia parametr Stop_ na 1 (dzieki temu nie doda nam to pancerza co sekunde, lecz tylko raz - po to powyzej jest ze tylko gdy Stop_ = 0
print("Stop_ImproveArmour = 1"); // Testowe
};
if(SPL_Time_ImproveArmour == SPL_Duration_ImproveArmour) // Jesli uplynie 10 sec, tzn czas zdefiniowany na poczatku jako czas trwania zaklecia
{
print("Prot - 5"); // Testowe, chociaz mozna tez zostawic jako informacje, gdy sie skonczy czar
B_RaiseProtectionBack (hero, PROT_BLUNT, 5); // Pancerz sie zmniejsza do poczatkowego...
B_RaiseProtectionBack (hero, PROT_POINT, 5);
SPL_Stop_ImproveArmour = 0; // ...resetuje sie parametr Stop_ na 0...
};
};

func void TimerImproveArmourApply() //funkcja wywolujaca timer
{
FF_ApplyOnceExt (TimerImproveArmour, 1000, -1); // wywoluje timer, co 1 sek, na stałe
};
i mojego czaru:
Spoiler
if ( Npc_GetActiveSpell(self) == SPL_ImproveArmour )
{
if (Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_ImproveArmour;
};
SPL_Time_ImproveArmour = 0; // ...resetuje sie parametr Time_ na 0...
TimerImproveArmourApply(); // Czyli czar wywoluje funkcje, kt˘ra wywoluje timer :D
return;
};

Pytanie jak to zrobić, żeby po zapisie i wczytaniu gry wszystko działało normalnie? Nie wiem czy jest jakaś funkcja, która uruchamia się bezpośrednio po zapisaniu gry, jeśli jest, to myślę, że to by rozwiązało problem. Jeśli nie, to nie mam innego pomysłu :P
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
Serializacji ulegają wszystkie zmienne, utwórz po prostu zmienne (var'y), w których będziesz zapisywać ten bonusowy armor itp, a same statystyki możesz wczytywać w funkcji init_global() (wczytywać, czyli wywoływać funkcje B_RaiseProtection i podawać bonusowe staty z tych zmiennych (po wczytaniu save'a, zmienne będą posiadać swoje wartości z czasu zapisu));

Są funkcje, które wywołują utworzenie save'u, itp., ale pojawia się pytanie, po co komplikować sam system, skoro można go zrealizować znacznie prościej?

Dla jasności:

Funkcja startup <- Wywołuje się po rozpoczęciu nowej gry (nie po wczytaniu)
Funkcja init <- Wywołuje się po zainicjowaniu rozgrywki (nowa gra, wczytanie gry, itp.)

@Edit:

Żeby to wszystko miało ręce i nogi, musisz oczywiście też zamienić const int'y, które pozwalają wyznaczyć czas bonusowy w timerze (ile trwa bonus), na var'y.
 

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Ok, dzięki @Patrix9999 , podziałało ;)
Rozwiązanie całkiem proste, zwyczajnie nie wiedziałem, że vary, w odróżnieniu od const są zapisywane podczas save'a, a później z niego odczytywane. To wiele wyjaśnia :P

Dla jasności i przyszłych pokoleń napisze co dokładnie zrobiłem. W pliku mojego czaru zamieniłem:
const int SPL_Time_ImproveArmour = 0;
const int SPL_Stop_ImproveArmour = 0;
na:
var int SPL_Time_ImproveArmour;            
var int SPL_Stop_ImproveArmour;   

Dodatkowo w pliku startup.d, pod func void INIT_GLOBAL() dodałem
if(SPL_Stop_ImproveArmour == 1)
{
TimerImproveArmourApply();
};

Czyli ten fragment pliku wygląda tak:
Spoiler
func void INIT_GLOBAL()
{
// wird fuer jede Welt aufgerufen (vor INIT_<LevelName>)
Game_InitGerman();
LeGo_Init (LeGo_All);
if(SPL_Stop_ImproveArmour == 1)
{
TimerImproveArmourApply();
};
};
Dzięki temu wszystko działa, jak należy :)

Ale skoro już jesteśmy przy tym temacie, to jeszcze jedna kwestia mnie nurtuje. Funkcja timera działa jakby "poza grą", tzn. gdy np wejdę do menu albo do ekranu statystyk, czyli gdy gra normalnie się zatrzymuje, to timer nadal działa, a więc w tym wypadku leci czas trwania czaru. Czy to ma tak być? Tzn. robię coś źle z tym timerem albo czy da się zastosować jakąś inną funkcję, która zatrzymuje się razem z grą?
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
Timer to funkcja, która będzie aktywnie wykonywana zawsze gdy program/aplikacja działa w tle, tak samo funkcja, która rysuje nam to, co widzimy na ekranie (onRender).

Jeśli chcesz, by twój skrypt "pauzował się", gdy spauzujesz grę, musisz wykryć, czy gra jest "spauzowana".
Można to zrobić na kilka sposobów, najprościej by było nałożyć hook na funkcje, która odpowiada za pauzowanie gry, utworzyć stałą (żeby nie ulegała niepotrzebnie zapisowi), w której byśmy zapisywali, czy gra jest obecnie spauzowana lub nie.

Mając taką "stałą", możemy wrzucić sobie warunek w timer i po problemie ;).
Problemem głównym czegoś takiego (tego podejścia) jest to, że im większy jest odstęp pomiędzy wywołaniem funkcji (timer wywołuje się co sekundę), to gdy odpauzowujemy gre, to natychmiastowo takie funkcje się nie wywołają. Przy większym opóźnieniu np: minutowym zauważyłbyś pewne odstępstwa czasu, pomiędzy kolejnymi wywołaniami, ten problem można też rozwiązać, ale przy opóźnieniu 1 sekundy nawet nie warto tego tykać, później dam ci przykład hooka i wykrywania kiedy gra jest spauzowana ;).
 

bogu9821

bogu9821

Użytkownicy
posty407
Propsy185
ProfesjaProgramista
  • Użytkownicy
Najprostszy sposób na sprawdzenie, czy gra jest „spauzowana” to sprawdzenie, czy pause_Screen z ogame (MEM_GAME w ikarusie) ma wartość: if(MEM_GAME.pause_Screen)
{
// coś

};
 
while(false) Do();

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
W sumie słuszna uwaga :).

Wystarczy że dodasz warunek, który dał bogu do swojego timera (odwrotny warunek, gdy gra nie jest spauzowana).
 

Toworish

Toworish

Użytkownicy
http://chomikuj.pl/ToWoRiSh
posty1664
Propsy254
ProfesjaNierób
  • Użytkownicy
  • http://chomikuj.pl/ToWoRiSh
Pierdol Ikarusa z LeGo. Baw się na AST :)
 
Niebawem...Pierdolnę se poradniki do Goticzka. Albo i nie, bo sie mnie nie chce.

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Ok, dzięki chłopaki, działa jak należy ;)

Dodałem na początku funkcji timera:
if(MEM_GAME.pause_Screen)
{
SPL_Time_ImproveArmour = SPL_Time_ImproveArmour;
}
else
{
            // cała reszta funkcji
        };

Nie wiem czy właśnie o taki warunek chodziło, ale działa, więc chyba ok ;)

O tym hooku tylko słyszałem, ale nawet nie wiem jeszcze jak się to robi - dopiero zaczynam się bawić w modowanie :D

Toworish - a co, ten AST lepszy? :P
 

Toworish

Toworish

Użytkownicy
http://chomikuj.pl/ToWoRiSh
posty1664
Propsy254
ProfesjaNierób
  • Użytkownicy
  • http://chomikuj.pl/ToWoRiSh
No wiele większe możliwości są, No i przyda ci się bo ćwiczysz/uczysz się cpp okazjonalnie. Tam jak wolisz, ale polecam zapoznać się po prostu z tematem, od wyjścia AST Ikarus (CHYBA) powoli idzie w zapomnienie.
 
Niebawem...Pierdolnę se poradniki do Goticzka. Albo i nie, bo sie mnie nie chce.

Cruc

Cruc

Użytkownicy
posty669
Propsy236
Profesjabrak
  • Użytkownicy
A powiedz mi ilu modderów w Polsce rzeczywiście korzysta z AST (mam na myśli wykorzystywanie w modyfikacjach)? Bo oprócz Siemkka to na razie chyba nikt xD

Choć prawdą jest, że AST jest lepszy niż Ikarus. Niestety wymaga też pewnej wiedzy, no ale od czego są poradniki na tM, albo discord, gdzie w razie czego ktoś podpowie? :x
 
while (!success) try{...}

Najlepszy modder od gothic multiplayer - polecam pytać go o wszystko!

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
No dobra, a skoro już przy tym temacie jesteśmy, to jakieś pomysły od czego powinienem zacząć z AST? W  sensie polecacie jakieś podstawowe poradniki, tak żebym mniej więcej ogarnął o co w tym w ogóle chodzi? :D
 

Toworish

Toworish

Użytkownicy
http://chomikuj.pl/ToWoRiSh
posty1664
Propsy254
ProfesjaNierób
  • Użytkownicy
  • http://chomikuj.pl/ToWoRiSh
Od Poradników Siemmka na forum. @Cruc No ta ikarus łatwy i nie trzeba sępić pomocy na themodders.org

Właściwie to Poradników do ikarusa jest w sumie tyle samo co do ast xd

Jedynie w Problematyce jest wiecej zapytań o ikarusa, ponieważ AST to chwilowo nowość. Niech się rozwijają młodzi programiści, Kto będzie pracował na twoją emeryture? :P
 
Niebawem...Pierdolnę se poradniki do Goticzka. Albo i nie, bo sie mnie nie chce.

Cruc

Cruc

Użytkownicy
posty669
Propsy236
Profesjabrak
  • Użytkownicy
Jak ktoś przez większość kariery modderskiej (kariera xd) siedział na Ikarusie to teraz może mu się zwyczajnie nie chcieć przesiadać na AST.

@pagi111 Zrozumienie AST dla kogoś, kto nie miał styczności z programowaniem obiektowym/Ikarusem może sprawić nieco trudności, dlatego zawsze możesz przemyśleć dołączenie do discorda (https://discordapp.com/invite/mEPeebN) - ale ohydnie reklamuję :F

Z poradnikami jest ten problem, że prawie ich nie ma. (oprócz tych co zrobił Siemekk, w dziale samouczków/gotowców - nie pamiętam dokładnie nazwy). Dlatego bazujesz głównie na swojej wiedzy i zrozumieniu.
 
while (!success) try{...}

Najlepszy modder od gothic multiplayer - polecam pytać go o wszystko!

bogu9821

bogu9821

Użytkownicy
posty407
Propsy185
ProfesjaProgramista
  • Użytkownicy
Naucz się c++.
Bez tego ciężko będzie ci używać AST, choć nie musisz mieć z tego magistra. :D
Do zaawansowanych rzeczy przyda też się znajomość matematyki i fizyki. :lol:
No ale nikt ci nie karze robić, nie wiadomo czego, ale tak jak pisałem, znajomość c++ to podstawa. ;)
A co do poradników, to w tym temacie je znajdziesz, bądź w problematyce: https://themodders.org/index.php?topic=28421.0
A jakbyś chciał się czegoś podpytać, to zapraszam na ten discord: https://discordapp.com/invite/mEPeebN

Największymi zaletami AST (Union) nad ikarusem jest to, że jest dużo szybsze i to, że można zedytować wszystko w silniku, lecz do AST trzeba mieć większą wiedzę, niż pisanie dialogów.
 
while(false) Do();

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
Dobra, dzięki Wam za pomoc, myślę, że spróbuję coś ogarnąć z tym AST. Chociaż teraz sobie kojarzę, że kiedyś zerkałem na poradnik Siemkka i nic z niego nie rozumiałem :D:D ale może muszę się mu lepiej przyjrzeć albo właśnie ogarnąć najpierw coś z C++. W sumie właśnie chciałem, żeby takie modowanie Gothica stanowiło dla mnie jakiś wstęp do programowania, więc będzie jak znalazł ;)

Swoją drogą chciałbym teraz zrobić do Gothica jakiś efekt, który zwiększa na pewien czas dmg - na razie nie wiem jak się za to zabrać, ale gdzieś chyba czytałem, że można właśnie za pomocą AST (choć pewnie można też inaczej), więc może będzie to dobry wstęp. Ale to już założę nowy wątek, żeby tutaj nie mieszać tematów :P

Jeszcze raz dzięki wszystkim za pomoc :)
 

Patrix9999

Patrix9999

Użytkownicy
posty127
Propsy38
Profesjabrak
  • Użytkownicy
Manipulować DMG możesz również poprzez Ikarusa.
Z tym AST to się nie śpiesz, bo żeby ogarnąć je, trzeba znać już podstawy RE i cpp.
Na Ikarusie i LeGo ździałasz dosyć dużo i przede wszystkim poduczycz się podstaw.

@Edit

jeszcze odnośnie tego kodu:

if(MEM_GAME.pause_Screen)
{
SPL_Time_ImproveArmour = SPL_Time_ImproveArmour;
}
else
{
            // cała reszta funkcji
        };

Uprość go ;)

Można tak:

if (!MEM_GAME.pause_Screen)
{
 // cała reszta funkcji
};

Lub tak:

if (MEM_GAME.pause_Screen == 0)
{
 // cała reszta funkcji
};
 

pagi111

pagi111

Użytkownicy
posty51
Propsy2
Profesjabrak
  • Użytkownicy
 


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