Skocz do zawartości

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.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

Kapucha112 - zdjęcie

Kapucha112

Rejestracja: 25.02.2011
Aktualnie: Nieaktywny
Poza forum Ostatnio: 26.01.2012 01:42
-----

#264478 [Challenge] Gotowce i przykłady

Napisane przez R3X w 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ź
//#define USING_ORPHEU
zamień na
#define USING_ORPHEU
i 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/default/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/default/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


#264223 [Challenge] Gotowce i przykłady

Napisane przez R3X w 29.06.2011 20:33

Szkielet


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
Dołączona grafika
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:Dołączona grafika


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


  • +
  • -
  • 5