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.
|

[Challenge] Gotowce i przykłady
#1
Napisano 29.06.2011 19:33
Popularny
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
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

//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

Załączone pliki
#3
Napisano 30.06.2011 12:13
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

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
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
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

#7
Napisano 01.07.2011 21:33
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
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
#10
Napisano 03.07.2011 22:31

natywów kilka dodam przy następnym wydaniu
#11
Napisano 04.07.2011 19:31
#12
Napisano 18.07.2011 18:38
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