Proszę.
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
Grundek
Rejestracja: 30.03.2013Aktualnie: Nieaktywny
Poza forum Ostatnio: 01.02.2014 09:40





Statystyki
- Grupa: Użytkownik
- Całość postów: 7
- Odwiedzin: 1 109
- Tytuł: Nowy
- Wiek: Wiek nie został ustalony
- Urodziny: Data urodzin nie została podana
-
Płeć
Mężczyzna
-
Lokalizacja
Poznan
Kontakt
#611312 [ROZWIĄZANE] Modyfikacja klasy Kapitan
Napisane przez
ILoveFootball
w 31.01.2014 12:04
#477125 Informacje wstępne, czyli Jak zacząć Scripting AMXX
Napisane przez
Gość
w 09.11.2012 19:47
Tutorial dla początkujących
Informacje wstępne
Scripting AMXX
[kotwica='cel']Cel[/kotwica]
Nauka tworzenia pluginów AMXX
Wymagania
Na samym początku zadajmy sobie pytanie: czym są pluginy AMXX i jak działają.
Pluginy AMXX to algorytmy modyfikacji rozgrywki na serwerach HLDS, pisane w języku Pawn,
zrozumiałym dla ludzi i zapisywane pod postacią plików SMA, które w wyniku kompilacji przybierają
postać kodu niezrozumiałego dla człowieka, ale zrozumiałego dla AMXX, zapisywane pod postacią
plików AMXX, które komunikują się z serwerem HLDS poprzez Metamoda:P, zmieniając rozgrywkę.
[kotwica='istota']Istota[/kotwica]
Tym samym, plugin komunikuje się z Metamodem:P, a Metamod:P z silnikiem gry (serwerem HLDS).
Musimy pamiętać, że każda wymiana informacji pomiędzy serwerem a silnikiem gry, zużywa liczne
zasoby sprzętowe i należy zadawać możliwie jak najmniej zapytań do silnika gry poprzez Metamoda:P.
[kotwica='plugins_ini']Plugins.ini[/kotwica]
Plik plugins.ini zawiera listę pluginów, które zostaną załadowane do AMXX i będą wykonywać swoje
algorytmy, komunikując się z serwerem HLDS poprzez MetaModa:P, modyfikując przebieg gry.
Jednak kolejność pluginów wpisanych w pliku plugins.ini nie jest bez znaczenia.
Zwróćmy teraz uwagę na sposób działania AMXX, czyli interakcję z serwerem gry.
AMXX pozwala nam, poprzez MetaModa:P, na następujące operacje:
Należy zatem zwracać uwagę na kolejność pluginów w pliku plugins.ini, przy czym algorytmy
kolejnych pluginów, od góry pliku plugins.ini, wykonywane są proporcjonalnie sekwencyjnie.
Przykładowo, jeśli w pluginie pierwszym od góry pliku plugins.ini, zablokujemy możliwość mówienia,
to w pluginie drugim od góry, nie zostanie zarejestrowane powiedzenie na sayu określonej wartości.
W odwrotnej kolejności tych pluginów w pliku plugins.ini zaś, będzie to z kolei możliwe do wykonania.
[kotwica='AMXMODX']AMXMODX[/kotwica]
Pierwszą, podstawową biblioteką, jaką będziemy musieli załączyć do naszego pluginu, jest AMXMODX.
W tym celu, dodajemy na samej górze naszego kodu SMA następującą linijkę kodu
AMXX posiada parę publicznych, predefiniowanych funkcji, a oto one:
[kotwica='plugin_natives']plugin_natives[/kotwica]
Ta funkcja wywoływana jest jako pierwsza, tuż po załadowaniu pluginu do pamięci AMXX.
W niej należy zainicjować wszelkie natywy do współpracy z innymi pluginami, czyli sprawić,
by możliwa była kompleksowa komunikacja pomiędzy funkcjami poszczególnych pluginów.
Jak już pisałem, funkcje ładowane są kolejno, od góry pliku plugins.ini, tak więc kolejność jest istotna.
[kotwica='plugin_precache']plugin_precache[/kotwica]
Ta funkcja wywoływana jest po załadowaniu wszytkich pluinów z natywami, lecz jeszcze przed pełnym zainicjowaniem
serwera HLDS i to w niej należy zarejestrować wszelkie wymagane do pobrania przez Użytkowników pliki niestandardowe,
z których będzie korzystał plugin, by powiadomić klienta gry o konieczności pobrania tych plików przed ustaleniem połączenia.
W tej właśnie funkcji należy zarejestrować wszelkie modyfikatory skryptów startowych serwera HLDS, by móc
w nie ingerować, zanim zostaną załadowane i wykonane skrypty startowe, uniemożliwiając ich identyfikację.
[kotwica='plugin_init']plugin_init[/kotwica]
Ta funkcja wywoływana jest podczas inicjalizacji pluginu, po pełnym załadowaniu funkcji startowych serwera.
W tej funkcji należy zarejestrować nasz plugin przy użyciu funkcji register_plugin o następujących parametrach
Warto zidentyfikować plugin w celu późniejszego testowania stanu pluginu i odnalezienia go na liście pluginów.
Składnia argumentów funkcji nie wymaga chyba większego komentarza, w przypadku wątpliwości zapraszam do manuala.
[kotwica='przyklad']Przykład[/kotwica]
Na tym etapie, potrafimy już stworzyć i zarejestrować pierwszy plugin, nie robiący praktycznie nic.
W trzeciej linijce zainicjowaliśmy publiczną funkcję plugin_init, wykonywaną po pełnym załadowaniu skryptów startowych HLDS.
Przypominam, że funkcja plugin_init winna być funkcją publiczną, inaczej może nie zostać ona wykonana w oczekiwanym momencie.
W czwartej linijce, rejestruję plugin i na tym kończy się działanie naszego testowego pluginu, który praktycznie nie zmienia rozgrywki.
W funkcji plugin_init należy także zarejestrować wszelkie nasłuchiwacze zdarzeń, jak śmierć gracza, czy nowa runda.
[kotwica='plugin_cfg']plugin_cfg[/kotwica]
Ta funkcja wywoływana jest tuż po plugin_init i służy konfiguracji pluginu, m.in. pobraniu zmiennych globalnych z silnika gry,
ustanowieniu połączenia z bazą danych, czy pobrania innych, istotnych danych do współpracy pluginu z zasobami zewnętrznymi.
[kotwica='register_event']register_event[/kotwica]
Pierwsza z funkcji, którą poznamy, pozwala na przechwycenie wybranych zdarzeń, które dokonywane są na serwerze.
Tutaj odwołuję do niezwykle istotnej strony, na której wypisane są zdarzenia silnika HLDS wraz z argumentami:
Half-Life 1 Game Events
Teraz spróbujemy przechwycić funkcję śmierci, w tym celu musimy zarejestrować w funkcji plugin_init nasłuchiwacz tego zdarzenia
Drugi parametr oznacza funkcję publiczną, która będzie wywoływana w momencie wystąpienia tego zdarzenia. Trzeci parametr
wynosi "a", gdyż DeathMsg jest eventem globalnym. Tym samym utworzymy sobie funkcję publiczną DeathMsg i damy zabójcy 200$.
[kotwica='read_data']read_data[/kotwica]
Jak możemy wyczytać z powyższego linku, DeathMsg posiada cztery argumenty. Nam wystarczy pierwszy argument, czyli id zabójcy.
Za pomocą funkcji read_data
możemy odczytać dany parametr funkcji, ponieważ pierwszy argument
to numer identyfikacyjny zabójcy, ten właśnie numer pobierzemy i zapiszemy do nowo utworzonej zmiennej killer.
Teraz będziemy chcieli nagrodzić zabójcę, przekazując mu dodatkowe 200 dolarów za zabójstwo.
W tym celu, skorzystamy z funkcji z biblioteki cstrike, cs_set_user_money
.
[kotwica='import_biblioteki']Import biblioteki[/kotwica]
Aby móc skorzystać z tej funkcji, musimy najpierw zaimportować kolejną bibliotekę,
w tym celu dodajemy do naszego kodu następującą linijkę (najlepiej pod bilioteką amxmodx)
[kotwica='sprawdzenie_obecnosci_gracza']Sprawdzenie obecności gracza[/kotwica]
Teraz dochodzimy do niezwykle istotnej rzeczy, którą musisz zapamiętać raz na zawsze!
Operując na jakimkolwiek graczu, upewnij się, że gracz może zostać danej operacji poddany.
W przykładzie, chcemy dodać pieniądze graczowi, jednak zanim to zrobimy, musimy się upewnić,
czy gracz jest jeszcze na naszym serwerze. Zawsze mógł rzucić granat, wyjść z serwera, a opiero po chwili
nastąpi zdarzenie śmierci. Co się stanie przy próbie dodania pieniędzy graczowi, którego nie ma na serwerze?
Na pewno jest to niepotrzebne zapytanie do silnika gry, dużo większe zużycie zasobów sprzętowych, a także stale
powiększające się logi błędów. Na dłuższą metę, takie właśnie błędy skutkują dużymi lagami bądź crashami serwera.
Tym samym, użyjemy funkcji is_user_connected
, w celu sprawdzenia, czy gracz jest jeszcze na serwerze.
Pamiętajmy, że aktualnie killer reprezentuje numer identyfikacyjny zabójcy, jednak w różnych funkcjach, możemy różnie
identyfikować poszczególne byty czy zdarzenia. Przy okazji, każdy byt na mapie ma swój własny, unikalny numer identyfikacyjny,
jednakże numerem identyfikacyjnym gracza jest numer z zakresu od 1 do maksymalnej liczby graczy włącznie. Tym samym, numer
bytu, będący większy lub równy 1 i nie większy, niż maksymalna liczba graczy na serwerze, oznacza na pewno gracza. (niekoniecznie online!)
Jak można zauważyć, nie mamy wprost funkcji dodającej pieniądze. W związku z tym,
musimy jako drugi parametr funkcji cs_set_user_money
podać sumę 200
i obecnej liczby dolarów gracza, pobieranej przy użyciu funkcji cs_get_user_money
[kotwica='zwracana_wartosc']Zwracana wartość[/kotwica]
W nowo utworzonej funkcji DeathMsg, zwrócimy na końcu odpowiednią wartość.
Dostępne wartości do zwrócenia:
PLUGIN_CONTINUE
Domyślna wartość, przerywająca dalsze wywołanie funkcji, jednak przez każdy inny plugin, a także silnik gry,
zdarzenie zostanie wywołane. Po prostu nic niżej od tego polecenia nie zostanie wywołane w tej danej jednej funkcji.
PLUGIN_HANDLED_MAIN
Dalsze wywołanie funkcji nie będzie możliwe, podobnie, jak w przypadku PLUGIN_CONTINUE, dalej wszystkie
pluginy będą mogły odnotować tę funkcję, jednak event ten zostanie zablokowany dla silnika właściwego gry.
PLUGIN_HANDLED
Dalsze wywoływanie funkcji zostanie przerwane, a ani silnik gry nie odnotuje tego eventu, ani, w przeciwieństwie
do PLUGIN_HANDLED_MAIN, żaden z kolejnych pluginów, wypisanych poniżej od tego obecnego w plugins.ini.
Nam wystarczy PLUGIN_CONTINUE, bowiem nie chcemy blokować śmierci w silniku, ani pozbawiać informacji o śmierci
kolejnych pluginów. Na koniec zmienimy nazwę pluginu na odzwierciedlającą rzeczywiste zastosowanie pluginu. Gotowy kod:
Tym samym, właśnie napisaliśmy swój pierwszy plugin, który daje dodatkowe 200 dolarów za zabójstwo.
Tutorial napisany, choć z drobnym opóźnieniem, z okazji Światowego Dnia Jakości.
Jeśli przypadnie on Wam do gustu, to mogę pokusić się w wolnym czasie o napisanie kolejnych
części, jako kontynuację, z rozwinięciem wątku i coraz bardziej zaawansowanymi przykładami Scriptingu.
Informacje wstępne
Scripting AMXX
[kotwica='cel']Cel[/kotwica]
Nauka tworzenia pluginów AMXX
Wymagania
- Znajomość obsługi AMXX
- Umiejętność programowania
- Podstawowa znajomość Pawna
- Racjonalne tworzenie algorytmów
- Umiejętność korzystania z manuala
- Edytor Pawna wraz z kompilatorem AMXX
Na samym początku zadajmy sobie pytanie: czym są pluginy AMXX i jak działają.
Pluginy AMXX to algorytmy modyfikacji rozgrywki na serwerach HLDS, pisane w języku Pawn,
zrozumiałym dla ludzi i zapisywane pod postacią plików SMA, które w wyniku kompilacji przybierają
postać kodu niezrozumiałego dla człowieka, ale zrozumiałego dla AMXX, zapisywane pod postacią
plików AMXX, które komunikują się z serwerem HLDS poprzez Metamoda:P, zmieniając rozgrywkę.
[kotwica='istota']Istota[/kotwica]
Tym samym, plugin komunikuje się z Metamodem:P, a Metamod:P z silnikiem gry (serwerem HLDS).
Musimy pamiętać, że każda wymiana informacji pomiędzy serwerem a silnikiem gry, zużywa liczne
zasoby sprzętowe i należy zadawać możliwie jak najmniej zapytań do silnika gry poprzez Metamoda:P.
[kotwica='plugins_ini']Plugins.ini[/kotwica]
Plik plugins.ini zawiera listę pluginów, które zostaną załadowane do AMXX i będą wykonywać swoje
algorytmy, komunikując się z serwerem HLDS poprzez MetaModa:P, modyfikując przebieg gry.
Jednak kolejność pluginów wpisanych w pliku plugins.ini nie jest bez znaczenia.
Zwróćmy teraz uwagę na sposób działania AMXX, czyli interakcję z serwerem gry.
AMXX pozwala nam, poprzez MetaModa:P, na następujące operacje:
- Zarejestrowanie danego zdarzenia czy wartości (np. odczytanie liczby pieniędzy danego gracza, czy zaobserwowanie wybuchu bomby)
- Modyfikowanie danego zdarzenia czy wartości (np. zmiana punktów życia danego gracza, czy przedłużenia czasu trwania oślepienia)
- Zablokowanie danego zdarzenia czy usunięcie wartości (np. brak obrażeń od granatów, czy usunięcie limitu posiadanych dolarów)
- Wywołanie danego zdarzenia (np. zabicie gracz, teleportacja gracza na respawn wrogów, czy pozbawienie gracza jego broni)
- Tworzenie danego zdarzenia czy wartości (np. zabicie vipa lub ucieczka terrorystów, czy stworzenie nowych cvarów)
Należy zatem zwracać uwagę na kolejność pluginów w pliku plugins.ini, przy czym algorytmy
kolejnych pluginów, od góry pliku plugins.ini, wykonywane są proporcjonalnie sekwencyjnie.
Przykładowo, jeśli w pluginie pierwszym od góry pliku plugins.ini, zablokujemy możliwość mówienia,
to w pluginie drugim od góry, nie zostanie zarejestrowane powiedzenie na sayu określonej wartości.
W odwrotnej kolejności tych pluginów w pliku plugins.ini zaś, będzie to z kolei możliwe do wykonania.
[kotwica='AMXMODX']AMXMODX[/kotwica]
Pierwszą, podstawową biblioteką, jaką będziemy musieli załączyć do naszego pluginu, jest AMXMODX.
W tym celu, dodajemy na samej górze naszego kodu SMA następującą linijkę kodu
#include <amxmodx>
AMXX posiada parę publicznych, predefiniowanych funkcji, a oto one:
[kotwica='plugin_natives']plugin_natives[/kotwica]
Ta funkcja wywoływana jest jako pierwsza, tuż po załadowaniu pluginu do pamięci AMXX.
W niej należy zainicjować wszelkie natywy do współpracy z innymi pluginami, czyli sprawić,
by możliwa była kompleksowa komunikacja pomiędzy funkcjami poszczególnych pluginów.
Jak już pisałem, funkcje ładowane są kolejno, od góry pliku plugins.ini, tak więc kolejność jest istotna.
[kotwica='plugin_precache']plugin_precache[/kotwica]
Ta funkcja wywoływana jest po załadowaniu wszytkich pluinów z natywami, lecz jeszcze przed pełnym zainicjowaniem
serwera HLDS i to w niej należy zarejestrować wszelkie wymagane do pobrania przez Użytkowników pliki niestandardowe,
z których będzie korzystał plugin, by powiadomić klienta gry o konieczności pobrania tych plików przed ustaleniem połączenia.
W tej właśnie funkcji należy zarejestrować wszelkie modyfikatory skryptów startowych serwera HLDS, by móc
w nie ingerować, zanim zostaną załadowane i wykonane skrypty startowe, uniemożliwiając ich identyfikację.
[kotwica='plugin_init']plugin_init[/kotwica]
Ta funkcja wywoływana jest podczas inicjalizacji pluginu, po pełnym załadowaniu funkcji startowych serwera.
W tej funkcji należy zarejestrować nasz plugin przy użyciu funkcji register_plugin o następujących parametrach
register_plugin(const plugin_name[], const version[], const author[])
Warto zidentyfikować plugin w celu późniejszego testowania stanu pluginu i odnalezienia go na liście pluginów.
Składnia argumentów funkcji nie wymaga chyba większego komentarza, w przypadku wątpliwości zapraszam do manuala.
[kotwica='przyklad']Przykład[/kotwica]
Na tym etapie, potrafimy już stworzyć i zarejestrować pierwszy plugin, nie robiący praktycznie nic.
#include <amxmodx>Przypomnijmy, w pierwszej linijce zaimportowaliśmy wymaganą zawsze dla AMXX, bibliotekę amxmodx.
public plugin_init(){
register_plugin("Nauka AMXX", "0.1", "benio101");
}
W trzeciej linijce zainicjowaliśmy publiczną funkcję plugin_init, wykonywaną po pełnym załadowaniu skryptów startowych HLDS.
Przypominam, że funkcja plugin_init winna być funkcją publiczną, inaczej może nie zostać ona wykonana w oczekiwanym momencie.
W czwartej linijce, rejestruję plugin i na tym kończy się działanie naszego testowego pluginu, który praktycznie nie zmienia rozgrywki.
W funkcji plugin_init należy także zarejestrować wszelkie nasłuchiwacze zdarzeń, jak śmierć gracza, czy nowa runda.
[kotwica='plugin_cfg']plugin_cfg[/kotwica]
Ta funkcja wywoływana jest tuż po plugin_init i służy konfiguracji pluginu, m.in. pobraniu zmiennych globalnych z silnika gry,
ustanowieniu połączenia z bazą danych, czy pobrania innych, istotnych danych do współpracy pluginu z zasobami zewnętrznymi.
[kotwica='register_event']register_event[/kotwica]
Pierwsza z funkcji, którą poznamy, pozwala na przechwycenie wybranych zdarzeń, które dokonywane są na serwerze.
Tutaj odwołuję do niezwykle istotnej strony, na której wypisane są zdarzenia silnika HLDS wraz z argumentami:
Half-Life 1 Game Events
Teraz spróbujemy przechwycić funkcję śmierci, w tym celu musimy zarejestrować w funkcji plugin_init nasłuchiwacz tego zdarzenia
register_event("DeathMsg", "DeathMsg", "a");Pierwszy parametr, zgodnie z dokumentacją, oznacza nazwę zdarzenia.
Drugi parametr oznacza funkcję publiczną, która będzie wywoływana w momencie wystąpienia tego zdarzenia. Trzeci parametr
wynosi "a", gdyż DeathMsg jest eventem globalnym. Tym samym utworzymy sobie funkcję publiczną DeathMsg i damy zabójcy 200$.
[kotwica='read_data']read_data[/kotwica]
Jak możemy wyczytać z powyższego linku, DeathMsg posiada cztery argumenty. Nam wystarczy pierwszy argument, czyli id zabójcy.
public DeathMsg(){ new killer=read_data(1); }Funkcja DeathMsg wywoływana jest w momencie wystąpienia zdarzenia śmierci.
Za pomocą funkcji read_data

to numer identyfikacyjny zabójcy, ten właśnie numer pobierzemy i zapiszemy do nowo utworzonej zmiennej killer.
Teraz będziemy chcieli nagrodzić zabójcę, przekazując mu dodatkowe 200 dolarów za zabójstwo.
W tym celu, skorzystamy z funkcji z biblioteki cstrike, cs_set_user_money

[kotwica='import_biblioteki']Import biblioteki[/kotwica]
Aby móc skorzystać z tej funkcji, musimy najpierw zaimportować kolejną bibliotekę,
w tym celu dodajemy do naszego kodu następującą linijkę (najlepiej pod bilioteką amxmodx)
#include <cstrike>Przypomnijmy, jak powinien wyglądać nasz obecny, pełny kod:
#include <amxmodx>
#include <cstrike>
public plugin_init(){
register_plugin("Nauka AMXX", "0.1", "benio101");
register_event("DeathMsg", "DeathMsg", "a");
}
public DeathMsg(){
new killer=read_data(1);
}
[kotwica='sprawdzenie_obecnosci_gracza']Sprawdzenie obecności gracza[/kotwica]
Teraz dochodzimy do niezwykle istotnej rzeczy, którą musisz zapamiętać raz na zawsze!
Operując na jakimkolwiek graczu, upewnij się, że gracz może zostać danej operacji poddany.
W przykładzie, chcemy dodać pieniądze graczowi, jednak zanim to zrobimy, musimy się upewnić,
czy gracz jest jeszcze na naszym serwerze. Zawsze mógł rzucić granat, wyjść z serwera, a opiero po chwili
nastąpi zdarzenie śmierci. Co się stanie przy próbie dodania pieniędzy graczowi, którego nie ma na serwerze?
Na pewno jest to niepotrzebne zapytanie do silnika gry, dużo większe zużycie zasobów sprzętowych, a także stale
powiększające się logi błędów. Na dłuższą metę, takie właśnie błędy skutkują dużymi lagami bądź crashami serwera.
Tym samym, użyjemy funkcji is_user_connected

Pamiętajmy, że aktualnie killer reprezentuje numer identyfikacyjny zabójcy, jednak w różnych funkcjach, możemy różnie
identyfikować poszczególne byty czy zdarzenia. Przy okazji, każdy byt na mapie ma swój własny, unikalny numer identyfikacyjny,
jednakże numerem identyfikacyjnym gracza jest numer z zakresu od 1 do maksymalnej liczby graczy włącznie. Tym samym, numer
bytu, będący większy lub równy 1 i nie większy, niż maksymalna liczba graczy na serwerze, oznacza na pewno gracza. (niekoniecznie online!)
public DeathMsg(){Teraz skorzystamy z natywów biblioteki cstrike i dodamy zabójcy 200 dolarów.
new killer=read_data(1);
if(is_user_connected(killer)){
// Dodawanie pieniedzy
}
}
cs_set_user_money(killer, cs_get_user_money(killer) + 200);
Jak można zauważyć, nie mamy wprost funkcji dodającej pieniądze. W związku z tym,
musimy jako drugi parametr funkcji cs_set_user_money

i obecnej liczby dolarów gracza, pobieranej przy użyciu funkcji cs_get_user_money

[kotwica='zwracana_wartosc']Zwracana wartość[/kotwica]
W nowo utworzonej funkcji DeathMsg, zwrócimy na końcu odpowiednią wartość.
Dostępne wartości do zwrócenia:
PLUGIN_CONTINUE
Domyślna wartość, przerywająca dalsze wywołanie funkcji, jednak przez każdy inny plugin, a także silnik gry,
zdarzenie zostanie wywołane. Po prostu nic niżej od tego polecenia nie zostanie wywołane w tej danej jednej funkcji.
PLUGIN_HANDLED_MAIN
Dalsze wywołanie funkcji nie będzie możliwe, podobnie, jak w przypadku PLUGIN_CONTINUE, dalej wszystkie
pluginy będą mogły odnotować tę funkcję, jednak event ten zostanie zablokowany dla silnika właściwego gry.
PLUGIN_HANDLED
Dalsze wywoływanie funkcji zostanie przerwane, a ani silnik gry nie odnotuje tego eventu, ani, w przeciwieństwie
do PLUGIN_HANDLED_MAIN, żaden z kolejnych pluginów, wypisanych poniżej od tego obecnego w plugins.ini.
Nam wystarczy PLUGIN_CONTINUE, bowiem nie chcemy blokować śmierci w silniku, ani pozbawiać informacji o śmierci
kolejnych pluginów. Na koniec zmienimy nazwę pluginu na odzwierciedlającą rzeczywiste zastosowanie pluginu. Gotowy kod:
#include <amxmodx>
#include <cstrike>
public plugin_init(){
register_plugin("Dodatkowe 200 dolarow za zabojstwo", "0.1", "benio101");
register_event("DeathMsg", "DeathMsg", "a");
}
public DeathMsg(){
new killer=read_data(1);
if(is_user_connected(killer)){
cs_set_user_money(killer, cs_get_user_money(killer) + 200);
}
return PLUGIN_CONTINUE;
}
Tym samym, właśnie napisaliśmy swój pierwszy plugin, który daje dodatkowe 200 dolarów za zabójstwo.
Tutorial napisany, choć z drobnym opóźnieniem, z okazji Światowego Dnia Jakości.
Jeśli przypadnie on Wam do gustu, to mogę pokusić się w wolnym czasie o napisanie kolejnych
części, jako kontynuację, z rozwinięciem wątku i coraz bardziej zaawansowanymi przykładami Scriptingu.
#609892 Nie komplikująca się klasa COD
Napisane przez dasiek
w 27.01.2014 18:12
Poprawna sładnia nie jest Twoją mocną stroną. Przypominam o klamerkach
Spoiler
#include <amxmodx> #include <amxmisc> #include <codmod> #include <engine> #include <fakemeta> #include <hamsandwich> #include <cstrike> new const nazwa[] = "Kapitan(Premium)"; new const opis[] = "Apteczki,Multi jump ,1/1 AWP,1/1 PPM"; new const bronie = (1<<CSW_AWP)|(1<<CSW_M4A1)|(1<<CSW_DEAGLE); new const zdrowie = 30; new const kondycja = 50; new const inteligencja = 10; new const wytrzymalosc = 0; new sprite_white_apteczki; new ilosc_apteczek_gracza[33]; new skoki[33]; new ostatnio_prawym[33]; new ma_klase[33] new oneonone[33][31] public plugin_init() { register_plugin(nazwa, "1.0", "amxx.pl"); cod_register_class(nazwa, opis, bronie, zdrowie, kondycja, inteligencja, wytrzymalosc); register_forward(FM_PlayerPreThink, "fwPrethink_Niewidzialnosc", 1); register_think("medkit", "Think_Apteczki"); RegisterHam(Ham_Spawn, "player", "fwSpawn_Apteczki", 1); register_forward(FM_CmdStart, "fwCmdStart_MultiJump"); RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage_JedenCios"); RegisterHam(Ham_Weapon_PrimaryAttack, "weapon_knife", "fwPrimaryAttack_JedenCios"); RegisterHam(Ham_Weapon_SecondaryAttack, "weapon_knife", "fwSecondaryAttack_JedenCios"); RegisterHam(Ham_TakeDamage, "player", "TakeDamage"); register_event("CurWeapon", "ModelBroni_CurWeapon", "be", "1=1"); register_forward(FM_SetModel, "ModelBroni_fw_SetModel"); } public plugin_precache() { sprite_white_apteczki = precache_model("sprites/white.spr"); precache_model("models/w_medkit.mdl"); precache_model("models/cod/p_awpp.mdl"); precache_model("models/cod/v_awpp.mdl"); precache_model("models/cod/w_awpp.mdl"); } public client_disconnect(id) { new entApteczki = find_ent_by_class(0, "medkit"); while(entApteczki > 0) { if(entity_get_edict(entApteczki, EV_ENT_owner) == id) remove_entity(entApteczki); entApteczki = find_ent_by_class(entApteczki, "medkit"); } } public cod_class_enabled(id) { oneonone[id][CSW_AWP] = 2 oneonone[id][CSW_M4A1] = 4 ma_klase[id] = 1; if(!(get_user_flags(id) & ADMIN_LEVEL_A)) { client_print(id, print_chat, "[Kapitan(Premium)] Nie masz uprawnien, aby uzywac tej klasy.") return COD_STOP; } { ilosc_apteczek_gracza[id] = 5; ma_klase[id] = true; return COD_CONTINUE; } } public cod_class_disabled(id) { ma_klase[id] = 0; oneonone[id][CSW_AWP] = 0 oneonone[id][CSW_M4A1] = 0 set_rendering(id,kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 255); ma_klase[id] = false; } public cod_class_skill_used(id) { if (!ilosc_apteczek_gracza[id]) { client_print(id, print_center, "Masz tylko 5 apteczki na runde!"); } else { ilosc_apteczek_gracza[id]--; new Float:origin[3]; entity_get_vector(id, EV_VEC_origin, origin); new ent = create_entity("info_target"); entity_set_string(ent, EV_SZ_classname, "medkit"); entity_set_edict(ent, EV_ENT_owner, id); entity_set_int(ent, EV_INT_solid, SOLID_NOT); entity_set_vector(ent, EV_VEC_origin, origin); entity_set_float(ent, EV_FL_ltime, halflife_time() + 7 + 0.1); entity_set_model(ent, "models/w_medkit.mdl"); set_rendering ( ent, kRenderFxGlowShell, 255,0,0, kRenderFxNone, 255 ) ; drop_to_floor(ent); entity_set_float(ent, EV_FL_nextthink, halflife_time() + 0.1); } } //Przy kucaniu public fwPrethink_Niewidzialnosc(id) { if(!ma_klase[id]) return; new button = get_user_button(id); if( button & IN_DUCK && get_user_weapon(id) == CSW_KNIFE) { set_rendering(id,kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 1); } else { set_rendering(id,kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 255); } } public fwSpawn_Apteczki(id) { if(is_user_alive(id)) ilosc_apteczek_gracza[id] = 5; } public Think_Apteczki(ent) { if(!is_valid_ent(ent)) return PLUGIN_CONTINUE; new id = entity_get_edict(ent, EV_ENT_owner); new dist = 300; new heal = 5+floatround(cod_get_user_intelligence(id)*0.5); if (entity_get_edict(ent, EV_ENT_euser2) == 1) { new Float:forigin[3]; entity_get_vector(ent, EV_VEC_origin, forigin); new entlist[33]; new numfound = find_sphere_class(0,"player", float(dist),entlist, 32,forigin); for (new i=0; i < numfound; i++) { new pid = entlist[i]; if (get_user_team(pid) != get_user_team(id)) continue; new maksymalne_zdrowie = 100+cod_get_user_health(pid); new zdrowie = get_user_health(pid); new Float:nowe_zdrowie = (zdrowie+heal<maksymalne_zdrowie)?zdrowie+heal+0.0:maksymalne_zdrowie+0.0; if (is_user_alive(pid)) entity_set_float(pid, EV_FL_health, nowe_zdrowie); } entity_set_edict(ent, EV_ENT_euser2, 0); entity_set_float(ent, EV_FL_nextthink, halflife_time() + 1.5); return PLUGIN_CONTINUE; } if (entity_get_float(ent, EV_FL_ltime) < halflife_time() || !is_user_alive(id)) { remove_entity(ent); return PLUGIN_CONTINUE; } if (entity_get_float(ent, EV_FL_ltime)-2.0 < halflife_time()) set_rendering ( ent, kRenderFxNone, 255,255,255, kRenderTransAlpha, 100 ); new Float:forigin[3]; entity_get_vector(ent, EV_VEC_origin, forigin); new iOrigin[3]; for(new i=0;i<3;i++) iOrigin[i] = floatround(forigin[i]); message_begin( MSG_BROADCAST, SVC_TEMPENTITY, iOrigin ); write_byte( TE_BEAMCYLINDER ); write_coord( iOrigin[0] ); write_coord( iOrigin[1] ); write_coord( iOrigin[2] ); write_coord( iOrigin[0] ); write_coord( iOrigin[1] + dist ); write_coord( iOrigin[2] + dist ); write_short( sprite_white_apteczki ); write_byte( 0 ); // startframe write_byte( 0 ); // framerate write_byte( 10 ); // life write_byte( 10 ); // width write_byte( 255 ); // noise write_byte( 255 ); // r, g, b write_byte( 100 );// r, g, b write_byte( 100 ); // r, g, b write_byte( 128 ); // brightness write_byte( 0 ); // speed message_end(); entity_set_edict(ent, EV_ENT_euser2 ,1); entity_set_float(ent, EV_FL_nextthink, halflife_time() + 0.5); return PLUGIN_CONTINUE; } public fwCmdStart_MultiJump(id, uc_handle) { if(!is_user_alive(id) || !ma_klase[id]) return FMRES_IGNORED; new flags = pev(id, pev_flags); if((get_uc(uc_handle, UC_Buttons) & IN_JUMP) && !(flags & FL_ONGROUND) && !(pev(id, pev_oldbuttons) & IN_JUMP) && skoki[id]) { skoki[id]--; new Float:velocity[3]; pev(id, pev_velocity,velocity); velocity[2] = random_float(265.0,285.0); set_pev(id, pev_velocity,velocity); } else if(flags & FL_ONGROUND) skoki[id] = 3; return FMRES_IGNORED; } public fwTakeDamage_JedenCios(id, ent, attacker) { if(is_user_alive(attacker) && ma_klase[attacker] && get_user_weapon(attacker) == CSW_KNIFE && ostatnio_prawym[id]) { cs_set_user_armor(id, 0, CS_ARMOR_NONE); SetHamParamFloat(4, float(get_user_health(id) + 1)); return HAM_HANDLED; } return HAM_IGNORED; } public fwPrimaryAttack_JedenCios(ent) { new id = pev(ent, pev_owner); ostatnio_prawym[id] = 1; } public fwSecondaryAttack_JedenCios(ent) { new id = pev(ent, pev_owner); ostatnio_prawym[id] = 0; } public TakeDamage(this, idinflictor, idattacker, Float:damage, damagebits) { if(!is_user_connected(idattacker)) return HAM_IGNORED; if(!ma_klase[idattacker]) return HAM_IGNORED; if(!(damagebits & (1<<1))) return HAM_IGNORED; new hp_ofiary = get_user_health(this) new bron_atakujacego = get_user_weapon(idattacker) if (oneonone[idattacker][bron_atakujacego] > 0) { if (random_num(1,oneonone[idattacker][bron_atakujacego]) == 1) cod_inflict_damage(idattacker, this, float(hp_ofiary), 0.0, idinflictor, damagebits); } return HAM_IGNORED; } public ModelBroni_CurWeapon(id) { new weapon = read_data(2); if(ma_klase[id]) { if(weapon == CSW_AWP) { set_pev(id, pev_viewmodel2, "models/cod/v_awpp.mdl") set_pev(id, pev_weaponmodel2, "models/cod/p_awpp.mdl") } } } public ModelBroni_fw_SetModel(entity, model[]) { if(!pev_valid(entity)) return FMRES_IGNORED if(!equali(model, "models/w_awp.mdl")) return FMRES_IGNORED; new entityowner = pev(entity, pev_owner); if(!ma_klase[entityowner]) return FMRES_IGNORED; engfunc(EngFunc_SetModel, entity, "models/cod/w_awpp.mdl") return FMRES_SUPERCEDE }
#247866 Call of Duty by góruś
Napisane przez góruś
w 09.05.2011 18:21

Witam, prezentuje wam dzisiaj moją ekskluzywną edycje Call of Duty moda, była ona dostępna na pewnej sieci, jednak z racji iż ją opuściłem i przerzuciłem się na coda z natyvami, postanowiłam wam ją udostępnić! Wersja posiada wbudowanego vipa, 90 itemów, 23 klasy(w tym 4 premium), Killstreak od Cypisa, możliwość sprzedaży itemu, menu frakcji, ogólnie prawie 5k kawałku kodu.(w paczce znajduję się jedynie sam plugin + modele)
Podziękowania dla Misieq za wgranie Killstreak oraz dla Cypis'a za jego poprawienie.

/klasa - wybierz klase /klasy - opis klas /przedmiot - opis przedmiotu /item - opis przedmiotu /drop - wyrzuc przedmiot /wyrzuc - wyrzuc przedmiot /reset - resetuj punkty /sklep - sklep /pomoc - wyłącz pomoc /oddaj - oddaj przedmiot /sprzedaj - sprzedaj przedmiot /vips - wyświetla aktualnych vipów /vip - motd vipa cod_lvl "gracza" "lvl" - ustawianie lvl'a cod_dajitemek "nick" "id itemu"

cod_killxp 15 // exp za zabicie cod_bombxp 30 // exp za podlozenie/rozbrojenie paki cod_hsexp 20 // exp za hs'a cod_winxp 20 // exp za wygrana runde cod_revkit_time 3 // Jak długo ma wskrzeszać osobę. Standardowo: 3(sekundy) cod_revkit_health 75 // Ile ma dać graczowi hp po wskrzeszeniu. Standardowo: 75(hp) cod_revkit_distance 100 // Z jakiego maksymalnej odległość można wskrzeszać. Standardowo: 100(dystanse) cod_revkit_xpdefiling 10 // Ile expa ma dawać za 'zjedzenie' przeciwnika. Standardowo: 10(exp) cod_revkit_xpraise 20 // Ile expa ma dawać za wskrzeszenie osoby ze swojej drużyny. Standardowo: 20(exp) cod_revkit_hpdefiling 30 // Ile hp ma dawać za 'zjedzenie' przeciwnika. Standardowo: 30(hp) cod_revkit_ile 10 // Ile osób można wskrzesić na rundę. Standardowo: 10 money_per_damage 3 // ilosc $$ za obrazenie money_kill_bonus 500 // $$ za zabicie money_hs_bonus 300 // $$ za hs'a amx_vip_hp 15 // hp za killa amx_vip_hp_hs 30 // hp za hs'a amx_vip_max_hp 500 // max hp vipa vip_active 1 // vip aktywny menu_active 1 // menu broni aktywne

Standardowa
Klasy:
Snajper - Dostaje AWP, scout i deagle, 120hp bazowe, 1/3 szansy natychmiastowego zabicia noza, 110% biegu, 100 pancerza Komandos - Dostaje Deagle, 140hp bazowe, Natychmiastowe zabicie z noza (prawy przycisk myszy), 135% biegu, 100 pancerza Strzelec wyborowy - Dostaje AK i M4A1, 110hp bazowe, 80 % biegu, 100 pancerza Obronca - Dostaje M249 (Krowa), 120hp bazowe, 80% biegu 150 pancerza Policjant - Dostaje 120HP, MP5 + Deagle + Usp, 120% Biegu, 100% Kamizelki, Zestaw Granatow, 2 Rakiety, Noktowizor Wsparcie ogniowe - Dostaje MP5, 100 hp bazowe Saper - Dostaje P90, 100 hp bazowe, 100 pancerza Demolitions - Dostaje AUG, 110 hp bazowe, 100 pancerza, Ma wszystkie granaty Rusher - Dostaje szotgana M3, 100 hp bazowe, 130% biegu Rambo (Klasa Premium) - Dostaje m4a1, 130 hp bazowe, 120% biegu, za kazde zabojstwo +20 hp oraz pelen magazynek, podwojny skok Partyzant - Dostaje P90, flashbang, 100 hp bazowe + mniej widzialny Szpieg - Dostaje deagla, 70 hp bazowe, ma ubranie wroga Szturmowiec - Dostaje M4 + deagle + he, 140 hp bazowe + 150 kamizelki, wolniej biega Strzelec Wsparcia - Dostaje m4a1, 125 hp bazowe Lekki Zolnierz - Dostaje galil + p228, 100 hp bazowe, szybciej biega Rebeliant - Dostaje sg552 + 1 HE, 125 hp bazowe Terrorysta - Dostaje ak47, 80 hp bazowe, o wiele szybciej biega Terminator (Klasa Premium) - Dostaje Darmowe granaty, ak47, 150hp bazowe, Deagle szybko biega 150%. otrzymuje 45hp za zabicie kogos,dostaje 2 rakiety Profesjonalny Wojak - Dosatje 130hp bazowe, darmowe ak+deagle, darmowe granaty, szybciej biega 110% Samuraj - Dostaje 110 HP, Galil, 120% Biegu, 50% Widzialnosci z Nozem, 1/2 Natychmiastowe zabicie nozem Wolny Strzelec (Klasa Premium) - Dostaje 140 HP, M4 + USP, 130% Biegu, +10 HP oraz Pelny Magazynek Za Zabojstwo, kameleon Kapitan (klasa Premium) - Dostaje 120 HP, 250 pancerza, M4A1, AWP, HEGRENADE, ma 1/2 szansy na zabicie z HE i 1/1 z AWP Profesjonalny lekarz - Dostaje 110 HP,MP5, Deagle, posiada cztery apteczki, moze wskrzeszac badz likwidowac ciala przeciwnika przyciskiem E

http://www.gorus.pl/cstrike.rar - Pełna paczka

Update 9 maja, 23:05 - proszę o ściągniecie nowej paczki
Update 9 maja, 23:30 - dodanie dwóch nowych klas(zmienione również w paczce)
Update 12 maja, 19:15 - update
Update 14 maja, 16:18 - poprawienie błędów, apteczka nie działała/errory
Update 18 maja, 21:05 - poprawienie crashy
Update 30 maja, 21:44 - poprawienie błędów z logów, naprawienie buga z hp, finalna wersja pluginu
#530642 Problem z klasom od lvl'a COD
Napisane przez koong
w 01.04.2013 16:38
Łap poprawione
Załączone pliki
-
codclass_starszysaper.sma 26,71 KB 41 Ilość pobrań
codclass_starszysaper.amxx
- AMXX.pl: Support AMX Mod X i SourceMod
- → Przeglądanie profilu: Reputacja: Grundek
- Regulamin