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żejZadania 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 tabelcepublic 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: 1
0 użytkowników, 1 gości, 0 anonimowych


Dodatki SourceMod






challenge_wprowadzenie.amxx







