Witamy w Nieoficjalnym polskim support'cie AMX Mod X
Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
|
Guest Message by DevFuse
[Challenge] Gotowce i przykłady
Temat rozp. R3X, 29.06.2011 19:33
12 odpowiedzi w tym temacie
#1
Napisano 29.06.2011 19:33
Popularny
Odnośnie platformy Challenge
Za namową Kapuchy112 >> tworzę miejsce publikowania wyzwań. Zacznę od ogólnego wprowadzenia do pisania wyzwań, potem w miarę możliwości będę uzupełniał listę o to gotowe pluginy, czyli to co mi lub Wam przyjdzie do głowy. Propozycje ciekawych wyzwań i nagród można wysłać mi na PW z tagiem [Challenge] lub w tym temacie
Opisy na podstawie wersji 1.5, jednak zgodność z 1.4 jest prawie zupełna
Wprowadzenie
Gotowce
Za namową Kapuchy112 >> tworzę miejsce publikowania wyzwań. Zacznę od ogólnego wprowadzenia do pisania wyzwań, potem w miarę możliwości będę uzupełniał listę o to gotowe pluginy, czyli to co mi lub Wam przyjdzie do głowy. Propozycje ciekawych wyzwań i nagród można wysłać mi na PW z tagiem [Challenge] lub w tym temacie
Opisy na podstawie wersji 1.5, jednak zgodność z 1.4 jest prawie zupełna
Wprowadzenie
Gotowce
#2
Napisano 29.06.2011 20:33
Popularny
Szkielet
Krok 1
Na początku załączamy plik challenge.inc do naszego pluginu i rejestrujemy wyzwanie
Zadania nie można wykonać, postęp tym bardziej nie jest monitorowany, stąd czerwone "brak danych"
Krok 2
Teraz wymyślamy cel wyzwania. Na początek niech będzie to pewna ilość zabójstw z M4. Wygodnie jest użyć pomocniczej funkcji, której wynik decyduje wprost czy spełniliśmy wymagania.
jeśli jako 3 parametr ch_get_user_stats() podamy wartość różną od 0 to funkcja zwróci liczbę samych headshowtów
ch_get_user_stats() zwraca dane zapisane w bazie; sam pomysł dotyczył lekkiej wersji statystyk, z tego względu sam Challenge.amxx automatycznie zbiera informacje jedynie o czasie przebywania gracza na serwerze, pozostałe funkcje musimy włączyć ręcznie. Do zapisywania zabić ze standardowych broni służy funkcja
Póki co ch_get_user_stats() zawsze zwraca 0, w rezultacie hasAccess zawsze zwraca fałsz. Włączmy więc zapisywanie statystyk M4, a otrzymamy poniższy kod:
Krok 3
Monitorowanie postępu wymaga doklejenia do naszego kodu funkcji publicznej challenge_progress()
Jak umieścić tam coś sensownego? Na przykład dać łamańca
Co jeśli gracz już zabił tych 100 graczy z emki? Do oznaczenia wyzwania jako zaliczonego służy funkcja
chid jest zwracany przez register_challenge()
Są 2 przypadki zaliczonego zadania:
- gracz wszedł do gry z zaliczonym już zadaniem:
tuż po załadowaniu danych z bazy wykonywana jest funkcja
- gracz zaliczył zadanie na tej mapie
tutaj sprawa się nieco komplikuje, podobnie jak moment odczytu także moment zdobycia punktu jest sygnalizowany, odpowiada za to funkcja
Dodajmy zmienną pilnującą czy danych gracz wykonał już zadanie, żeby można było go poinformować o spełnieniu warunków od razu. Tablica typu bool:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Cały kod wygląda teraz tak jak w załączniku
Te 50 linijek realizuje wszystko co potrzebne jest do podstawowego zadania....oprócz nagrody o tym wkrótce, bo jestem głodny
Krok 1
Na początku załączamy plik challenge.inc do naszego pluginu i rejestrujemy wyzwanie
#include <amxmodx> #include <amxmisc> #include <challenge> #define PLUGIN "Challenge : Wprowadzenie" #define VERSION "1.0" #define AUTHOR "R3X" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR); register_challenge("Wykonaj zadanie", "to dostaniesz nagrode"); }Efektem tej linijki jest dodanie nowego wyzwania do listy, jak na screenie poniżej
Zadania nie można wykonać, postęp tym bardziej nie jest monitorowany, stąd czerwone "brak danych"
Krok 2
Teraz wymyślamy cel wyzwania. Na początek niech będzie to pewna ilość zabójstw z M4. Wygodnie jest użyć pomocniczej funkcji, której wynik decyduje wprost czy spełniliśmy wymagania.
stock hasAccess(id){ return (ch_get_user_stats(id, CSW_M4A1) >= 100); }Taka funkcja zwraca prawdę tylko jeśli ilość zabójstw z M4 jest większa lub równa 100. (słowo kluczowe stock jest tu po to, żeby kod w obecnym stanie kompilował się bez ostrzeżeń)
jeśli jako 3 parametr ch_get_user_stats() podamy wartość różną od 0 to funkcja zwróci liczbę samych headshowtów
ch_get_user_stats() zwraca dane zapisane w bazie; sam pomysł dotyczył lekkiej wersji statystyk, z tego względu sam Challenge.amxx automatycznie zbiera informacje jedynie o czasie przebywania gracza na serwerze, pozostałe funkcje musimy włączyć ręcznie. Do zapisywania zabić ze standardowych broni służy funkcja
native challenge_uses_stats(wid);gdzie wid jest identyfikatorem broni CSW_*
Póki co ch_get_user_stats() zawsze zwraca 0, w rezultacie hasAccess zawsze zwraca fałsz. Włączmy więc zapisywanie statystyk M4, a otrzymamy poniższy kod:
#include <amxmodx> #include <amxmisc> #include <challenge> #define PLUGIN "Challenge : Wprowadzenie" #define VERSION "1.0" #define AUTHOR "R3X" public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR); register_challenge("Zabij 100 graczy z M4", "to dostaniesz nagrode"); challenge_uses_stats(CSW_M4A1); } stock hasAccess(id){ return (ch_get_user_stats(id, CSW_M4A1) >= 100); }
Krok 3
Monitorowanie postępu wymaga doklejenia do naszego kodu funkcji publicznej challenge_progress()
public challenge_progress(id, challenge, szProgress[], size){ }to co wpiszemy do szProgress[] zostanie pokazane w tabelce
public challenge_progress(id, challenge, szProgress[], size){ formatex(szProgress, size, "Wskaznik postepu"); }wynikiem tego jest:
Jak umieścić tam coś sensownego? Na przykład dać łamańca
tylu zabiłeś/ tyle wymagamy
//Postep wyzwania public challenge_progress(id, challenge, szProgress[], size){ formatex(szProgress, size, "%d/%d", ch_get_user_stats(id, CSW_M4A1), 100); }
Co jeśli gracz już zabił tych 100 graczy z emki? Do oznaczenia wyzwania jako zaliczonego służy funkcja
native challenge_done(id, chid, showinfo = 1);id to indeks gracza, chid to indeks wyzwania a showinfo 1|0 decyduje o tym, czy pokazana zostanie informacja (0 oczywiście załatwia sprawę po cichu )
chid jest zwracany przez register_challenge()
Są 2 przypadki zaliczonego zadania:
- gracz wszedł do gry z zaliczonym już zadaniem:
tuż po załadowaniu danych z bazy wykonywana jest funkcja
public client_data_loaded(id){ }Tutaj wystarczy sprawdzić czy gracz spełnia warunki wyzwania i ewentualnie zaliczyć mu zadanie po cichu
//aktualizacja tabeli od razu przy podlaczeniu sie gracza public client_data_loaded(id){ if(hasAccess(id)) challenge_done(id, chid, 0); //wykonanie bez informacji }Teraz bez pytania o postęp w tabelce pokaże się zielone OK.
- gracz zaliczył zadanie na tej mapie
tutaj sprawa się nieco komplikuje, podobnie jak moment odczytu także moment zdobycia punktu jest sygnalizowany, odpowiada za to funkcja
public client_gain_point(id, wid, hs){ }
Dodajmy zmienną pilnującą czy danych gracz wykonał już zadanie, żeby można było go poinformować o spełnieniu warunków od razu. Tablica typu bool:
new bool:gbDone[33];czyszczona przy łączeniu się gracza z serwerem załatwi sprawę. Dobierzmy dobry warunek w tym forwardzie i gotowe. Po pierwsze czy gracz już wykonał zadanie, jeśli tak nic tu po nas. Potem warto sprawdzić id broni, bo jeśli dostał punkt od innej to na bank nie zdobył nagrody na końcu oczywiście hasAccess(id)
//Postep wyzwania w grze public client_gain_point(id, wid, hs){ if(!gbDone[id] && wid == CSW_M4A1 && hasAccess(id){ challenge_done(id, chid); //wykonanie z informacja gbDone[id] = true; } }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Cały kod wygląda teraz tak jak w załączniku
Te 50 linijek realizuje wszystko co potrzebne jest do podstawowego zadania....oprócz nagrody o tym wkrótce, bo jestem głodny
Załączone pliki
#3
Napisano 30.06.2011 12:13
Niestandardowe bronie
Plugin umożliwia zapisywanie statystyk dowolnej broni w grze. Fragi są zliczane przy każdej wiadomości DeathMsg (lista zabójstw w prawym, górnym rogu). Aby to działało plugin musi mieć możliwość złapania tej wiadomości. Dobrym sposobem jest skompilowanie Challenge z wykorzystaniem modułu Orpheu, jednak wtedy musi on być zainstalowany na serwerze.
znajdź
Jeśli nie chcemy angażować orpheu równie skuteczne jest rozsyłanie wiadomości funkcją emessage_begin(), wtedy w naszym pluginie dodającym broń trzeba znaleźć fragment odpowiedzialny za DeathMsg. W przykładzie użyłem head_splash, a w nim znajduje się funkcja:
Dzięki jednemu i drugiemu wyjściu możemy być pewni, że statystyki będą liczone.
Jak to wykorzystać w wyzwaniu? Wystarczy przypisać nowej broni numer do statystyk funkcją
Zabójstwa z head_splasha mają nazwę broni "his/her feet ", więc kod wygląda tak:
Całość od szkieletu różni się tym fragmentem:
Plugin umożliwia zapisywanie statystyk dowolnej broni w grze. Fragi są zliczane przy każdej wiadomości DeathMsg (lista zabójstw w prawym, górnym rogu). Aby to działało plugin musi mieć możliwość złapania tej wiadomości. Dobrym sposobem jest skompilowanie Challenge z wykorzystaniem modułu Orpheu, jednak wtedy musi on być zainstalowany na serwerze.
znajdź
//#define USING_ORPHEUzamień na
#define USING_ORPHEUi przekompiluj
Jeśli nie chcemy angażować orpheu równie skuteczne jest rozsyłanie wiadomości funkcją emessage_begin(), wtedy w naszym pluginie dodającym broń trzeba znaleźć fragment odpowiedzialny za DeathMsg. W przykładzie użyłem head_splash, a w nim znajduje się funkcja:
_make_deathmsg(pwnzor, pwned, hs, const szWeapon[]){ static msgDeathMsg=0; if(!msgDeathMsg) msgDeathMsg = get_user_msgid("DeathMsg"); message_begin(MSG_ALL, msgDeathMsg); write_byte(pwnzor); write_byte(pwned); write_byte(hs); write_string(szWeapon); message_end(); }zamiast tych funkcji trzeba użyć ich odpowiedników z e na początku, czyli to
_make_deathmsg(pwnzor, pwned, hs, const szWeapon[]){ static msgDeathMsg=0; if(!msgDeathMsg) msgDeathMsg = get_user_msgid("DeathMsg"); emessage_begin(MSG_ALL, msgDeathMsg); ewrite_byte(pwnzor); ewrite_byte(pwned); ewrite_byte(hs); ewrite_string(szWeapon); emessage_end(); }
Dzięki jednemu i drugiemu wyjściu możemy być pewni, że statystyki będą liczone.
Jak to wykorzystać w wyzwaniu? Wystarczy przypisać nowej broni numer do statystyk funkcją
challenge_custom_weapon("nazwa broni");to nam zwróci indeks, który potem używamy tak jak indeksy innych broni CSW_*; nazwa to parametr szWeapon[] z _make_deathmsg(), czyli to co się pokazuje w konsoli po zdobyciu fraga daną bronią
R3X killed SomeOne with <nazwa broni>
Zabójstwa z head_splasha mają nazwę broni "his/her feet ", więc kod wygląda tak:
CSW_HEADSPLASH = challenge_custom_weapon("his/her feet <img src='http://img.amxx.pl/public/style_emoticons/<#EMO_DIR#>/smile.gif' class='bbc_emoticon' alt=':)' />");
Całość od szkieletu różni się tym fragmentem:
new CSW_HEADSPLASH; public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR); chid = register_challenge("Zabij 100 graczy z HeadSplash", "to dostaniesz nagrodę"); CSW_HEADSPLASH = challenge_custom_weapon("his/her feet <img src='http://img.amxx.pl/public/style_emoticons/<#EMO_DIR#>/smile.gif' class='bbc_emoticon' alt=':)' />"); challenge_uses_stats(CSW_HEADSPLASH); } //czy spełnia wymagania stock hasAccess(id){ return (ch_get_user_stats(id, CSW_HEADSPLASH) >= 100); }
Załączone pliki
#4
Napisano 30.06.2011 23:26
Samodzielne zliczanie
Jeśli chcemy zliczać punkty czegoś innego niż zabójstwa potrzebujemy zarezerwować indeks w statystykach. Robi się to tak samo jak w przypadku niestandardowych broni, funkcją:
Jednak zamiast wyczekiwać na fragi z takiej broni, będziemy ręcznie dodawać punkty za pomocą:
wid to indeks broni
hs 1|0, z headshotem lub bez
W przypadku własnych statystyk możemy potraktować punkty z hs i bez jako 2 niezwiązane ze sobą pola.
Możemy np jako jedną broń zapisywać dane o podłożonych i rozbrojonych bomb:
I w ten sposób 'zabicia z paki' oznaczają podłożone, a 'zabicia z paki headshotem' oznaczają rozbrojone paki
Funkcja ch_add_user_stats() działa dla wszystkich dostępnych statystyk, więc można nią rozdawać bonusy/nieco oszukiwać
Jeśli chcemy zliczać punkty czegoś innego niż zabójstwa potrzebujemy zarezerwować indeks w statystykach. Robi się to tak samo jak w przypadku niestandardowych broni, funkcją:
challenge_custom_weapon(const szWeapon[])zwraca ona odpowiedni indeks.
Jednak zamiast wyczekiwać na fragi z takiej broni, będziemy ręcznie dodawać punkty za pomocą:
ch_add_user_stats(id, wid, hs=0)id to indeks gracza
wid to indeks broni
hs 1|0, z headshotem lub bez
W przypadku własnych statystyk możemy potraktować punkty z hs i bez jako 2 niezwiązane ze sobą pola.
Możemy np jako jedną broń zapisywać dane o podłożonych i rozbrojonych bomb:
new CSW_BOMBA; public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR); chid = register_challenge("Rozbroj lub podloz 100 bomb", "to dostaniesz nagrodę"); CSW_BOMBA= challenge_custom_weapon("paka"); } //czy spełnia wymagania stock hasAccess(id){ return (ch_get_user_stats(id, CSW_BOMBA) + ch_get_user_stats(id, CSW_BOMBA, 1) >= 100); } public bomb_planted(id){ ch_add_user_stats(id, CSW_BOMBA);//dodaj punkt } public bomb_defused(id){ ch_add_user_stats(id, CSW_BOMBA, 1);//dodaj punkt }
I w ten sposób 'zabicia z paki' oznaczają podłożone, a 'zabicia z paki headshotem' oznaczają rozbrojone paki
Funkcja ch_add_user_stats() działa dla wszystkich dostępnych statystyk, więc można nią rozdawać bonusy/nieco oszukiwać
Załączone pliki
#5
Napisano 30.06.2011 23:43
Nagrody (ogólnie)
No i najciekawsza część wyzwania - nagroda. Tutaj w końcu można się wykazać. Nagrodą może być wszystko, jeśli przejdzie test funkcji hasAccess(), przypominam:
Zanim przyznamy nagrodę wystarczy sprawdzić hasAccess() lub wartość gbDone[] (jeśli mamy ją w kodzie). I tyle.
Możemy wykorzystać np.:
Zdobycie wyzwania (jednorazowo)
Spawn
Bonus z innego pluginu
jeśli np. mamy plugin dający spadochron lub dodatkowe obrażenia to
No i najciekawsza część wyzwania - nagroda. Tutaj w końcu można się wykazać. Nagrodą może być wszystko, jeśli przejdzie test funkcji hasAccess(), przypominam:
stock hasAccess(id){ return (ch_get_user_stats(id, CSW_M4A1) >= 100); }to właśnie hasAccess() decydowało o tym, czy przyznać gracz zaliczył zadanie. Jeśli używasz szkieletu sprzed kilku postów to globalna tablica w kodzie była zsynchronizowana ze stanem tej funkcji.
new bool:gbDone[33];
Zanim przyznamy nagrodę wystarczy sprawdzić hasAccess() lub wartość gbDone[] (jeśli mamy ją w kodzie). I tyle.
Możemy wykorzystać np.:
Zdobycie wyzwania (jednorazowo)
public client_gain_point(id, wid, hs){ if(!gbDone[id] && hasAccess(id)){ //Daj nagrodę challenge_done(id, chid); //wykonanie z informacja gbDone[id] = true; } }
Spawn
#include <hamsandwich> public plugin_init(){ RegisterHam(Ham_Spawn, "player", "fwSpawn", 1); } public fwSpawn(id){ if(is_user_alive(id) && hasAccess(id)){ //Daj nagrodę } }
Bonus z innego pluginu
jeśli np. mamy plugin dający spadochron lub dodatkowe obrażenia to
public uzyjBonusu(){ if(!hasAccess(id)) return; //.. //Normalny przebieg bonusowej funkcji <img src='http://img.amxx.pl/public/style_emoticons/<#EMO_DIR#>/smile.gif' class='bbc_emoticon' alt=':)' /> }
#6
Napisano 30.06.2011 23:48
Dobra skończyłem wprowadzenie, teraz się zaczną gotowe wyzwania Lista będzie w 1 poście, więc chyba temat może być otwarty na sugestie
#7
Napisano 01.07.2011 21:33
Kasa co runde
W nagrodę co rundę gracz dostaje tyle dolarów na ile ustawiony jest cvar
To co trzeba dodać (plugin_init() przekopiować zawartość do istniejącej funkcji):
W załączniku pełen przykład
W nagrodę co rundę gracz dostaje tyle dolarów na ile ustawiony jest cvar
amx_challenge_money_bonus
To co trzeba dodać (plugin_init() przekopiować zawartość do istniejącej funkcji):
#include <cstrike> new gcvarMoneyBonus; public plugin_init() { register_logevent( "eventRoundStart",2, "1=Round_Start"); gcvarMoneyBonus = register_cvar("amx_challenge_money_bonus", "1000"); } public eventRoundStart(){ static iMaxPlayers = 0; if(iMaxPlayers == 0) iMaxPlayers = get_maxplayers(); new iMoneyBonus = get_pcvar_num(gcvarMoneyBonus); for(new id = 1; id <= iMaxPlayers; id++) if(is_user_alive(id) && hasAccess(id)){ cs_set_user_money(id, cs_get_user_money(id)+iMoneyBonus); //Odkomentuj jesli chcesz pokazywac graczowi info //challenge_done(id, chid); } }
W załączniku pełen przykład
Załączone pliki
#8
Napisano 01.07.2011 21:46
Ciche chodzenie do końca mapy
Po ukończeniu wyzwania gracz do końca mapy będzie chodził cicho
To należy dodać/ ew. uzupełnić jeśli funkcje już istnieją
W załączniku pełen przykład
Po ukończeniu wyzwania gracz do końca mapy będzie chodził cicho
To należy dodać/ ew. uzupełnić jeśli funkcje już istnieją
#include <fun> #include <hamsandwich> new bool:gbSilent[33]; public plugin_init() { RegisterHam(Ham_Spawn, "player", "fwSpawn", 1); } public client_connect(id){ gbSilent[id] = false; } //Postep wyzwania w grze public client_gain_point(id, wid, hs){ if(!gbDone[id] && wid == CSW_M4A1 && hasAccess(id)){ //Te 2 linijki set_user_footsteps(id); gbSilent[id] = true; challenge_done(id, chid); //wykonanie z informacja gbDone[id] = true; } } public fwSpawn(id){ if(is_user_alive(id) && gbSilent[id]) set_user_footsteps(id); }
W załączniku pełen przykład
Załączone pliki
#9
Napisano 03.07.2011 22:20
Ja bym proponował dodać nowe natywy: czy ktoś wykonał jakieś, konkretne zadanie, no i też jakieś ograniczenie info o zadaniach. Ja zrobiłem, że osoba, która wykonała osiągnięcie to dostaje dodatkowy damage i cały czas mi spamuje hud takimi wiadomościami, że zaliczyłem osiągnięcie.
#10
Napisano 03.07.2011 22:31
challenge_done ma trzeci parametr, który jak ustawisz na 0 to nie będzie spamu
natywów kilka dodam przy następnym wydaniu
natywów kilka dodam przy następnym wydaniu
#11
Napisano 04.07.2011 19:31
Myślę jednak, że lepiej dodać forward, np: challenge_end i tam dać info o wykonaniu zadania oraz też zmianę w kodzie, że np. co 5 minut wyświetla wszystkie wykonane osiągnięcia w dHUD'zie.
#12
Napisano 18.07.2011 18:38
Ja tam czekam na nagrodę w formie expa do war3ft , gdy zobaczymy jak to wygląda w danym modzie to łatwiej będzie edytować pod resztę.
DiabloMod Reloaded? [90%]
Testowanie integracji poszczególnych sub-pluginów. Zwiększanie możliwości i optymalizacja kodu.
CodMod MW2 [100%]
Całkowicie nowy silnik z tworzeniem własnych klas z własnymi nazwami! Proste w obsłudze API, nie nawiązuje niczym do Codów podróbek [OGóLNODOSTĘPNYCH]. Nowy system killstreak, misje, rewardy xp, samochody, samoloty, bombowce, ekwipunek, zrzuty zaopatrzenia, npc
Testować można na moim forum
Testowanie integracji poszczególnych sub-pluginów. Zwiększanie możliwości i optymalizacja kodu.
CodMod MW2 [100%]
Całkowicie nowy silnik z tworzeniem własnych klas z własnymi nazwami! Proste w obsłudze API, nie nawiązuje niczym do Codów podróbek [OGóLNODOSTĘPNYCH]. Nowy system killstreak, misje, rewardy xp, samochody, samoloty, bombowce, ekwipunek, zrzuty zaopatrzenia, npc
Testować można na moim forum
Użytkownicy przeglądający ten temat: 0
0 użytkowników, 0 gości, 0 anonimowych