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
 

silva - zdjęcie

silva

Rejestracja: 03.10.2013
Aktualnie: Nieaktywny
Poza forum Ostatnio: 09.12.2019 00:32
*****

#472792 Plugin + baza danych

Napisane przez GwynBleidD w 30.10.2012 01:39

Na wstępie zaznaczę, że NIE jest to poradnik o używaniu MySQL w AMX, ale o DOBRYM jego używaniu. Kto czytał mój poradnik o dobrych nawykach tworzenia menu, ten wie o co chodzi :)

Powstaje coraz więcej pluginów z użyciem MySQL, ale czy są to dobrze napisane pluginy? Na pewno nie wszystkie. O ile w większości przypadków do samych realizacji funkcji pluginu na serwerze nie można się przyczepić, o tyle komunikacja z bazą danych pozostawia wiele do życzenia. Pół biedy, gdy mamy serwer SQL na tej samej maszynie, albo na maszynie w jednej sieci... Albo gdy używamy SQLite. Ale większość serwerów posiada bazę SQL w zupełnie innej lokalizacji. Często serwer gry jest w Polsce, a SQL we Francji, Niemczech... Czym to owocuje?

Popatrzmy.. Sami wiemy, że serwery zagraniczne do grania mixów się nie nadają raczej, zbyt wysoki ping. Podobny ping do takiego serwera ma dowolny serwer gry postawiony w Polsce, potrafi się on wahać od 100 do 500 milisekund, czyli aż do pół sekundy! To już całkiem sporo jak na przetworzenie zapytania... O ile samo przetworzenie nie zajmuje dużo, przy dobrze skonfigurowanym serwerze nie jest to nawet 1 milisekunda, o tyle wysłanie go i odebranie wyniku już trochę trwa...

Popatrzmy na taki prosty przykład (przyjmijmy średni ping na 150 ms do zagranicznych serwerów), AmxBans, dowolna ich wersja... Gracz wchodzi na serwer, wykonywane są po kolei następujące zapytania:
  • Sprawdzenie, czy gracz nie posiada bana.
  • Jeśli ban został znaleziony:
    • Jest aktywny: zwiększenie ilości kicków w danych o banie (dotyczy GmBans), dalsze zapytania niewykonywane
    • Jeśli nie jest aktywny: przesunięcie go do archiwum
  • Sprawdzenie, czy gracz nie został oflagowany
  • Sprawdzenie, czy gracz nie posiadał wcześniej żadnych banów
  • Jeśli używamy bazy sql zamiast users.ini - sprawdzenie, czy gracz nie jest adminem
W pesymistycznym przypadku - 5 zapytań SQL, w optymistycznym (aktywny ban) 2. W normalnym (brak aktywnych banów): 4. Dosyć sporo. A wszystkie, prócz ostatniego można ograniczyć do TYLKO jednego zapytania. Jakby się postarać to i ostatnie można podłączyć do tego zapytania, ale nie ma to sensu bo nie dalibyśmy wtedy użytkownikowi wyboru czy chce używać users.ini czy bazy danych do przechowywania adminów.

Założyliśmy, że średni ping wynosi 150ms, czyli w uproszczeniu daje nam to 150ms na jedno zapytanie (w rzeczywistości trwa to jednak dłużej), więc 750ms przy pesymistycznej wersji będzie trwało ustalenie z kim mamy do czynienia, prawie sekunda! a graczy możemy mieć nawet 32, przy zmianie mapy te wszystkie zapytania się wykonują! W tym artykule pomogę Wam takich koszmarków unikać...


Projekt bazy danych.
Pierwszą rzeczą, którą musimy uczynić przy tworzeniu pluginu wykorzystującego bazę danych, jest odpowiedni projekt samej bazy danych. Najpierw musimy wiedzieć co zapisujemy. Czy chcemy stworzyć exp moda? Może jakieś statystyki dla graczy zapisywać? A może wszystkie serwery sieci zebrać w jednej bazie danych na potrzeby pluginu takiego, jak xRedirect?

Gdy to już wiemy, następna rzecz to to, co chcemy na dany temat w bazie umieścić. Przyjmijmy dla przykładu, że tworzymy plugin zliczający czas gry na naszym serwerze każdego gracza, który nań wejdzie. Dla uproszczenia przyjmijmy również, że serwer jest Steam Only (nie mam zamiaru igrać z prawem tutaj :D), dzięki czemu każdego gracza po SteamID można rozpoznać.

Więc co musimy w bazie zapisać? Na pewno jego SteamID oraz czas gry na serwerze. Czyli mamy już 2 kolumny w bazie danych, dopiszemy jeszcze trzecią, id. Czym będzie ID? Identyfikatorem ułatwiającym nam operację na bazie danych :) Szybciej w bazie jest wyszukiwać po liczbach, niż po napisach. Więc będziemy mieli 3 kolumny:
  • `id` INT(11) NOT NULL auto_increment
  • `sid` VARCHAR(24) NOT NULL
  • `time` INT(11) NOT NULL
Przy ID dodajemy auto_increment. Dzięki temu każdy id będzie większy o 1 od poprzedniego dodanego do bazy. Dalej mamy string `sid` długości 24 znaków. 20 znaków zajmuje najdłuższy spotkany przeze mnie Steam ID. Dajmy dodatkowe znaki, jakby w przyszłości się rozrosły. Time jest typu INT, czyli liczbą. Wszak czas możemy zapisać w formie ilości sekund przegranej na serwerze. Tak najprościej go jest przechować i przetwarzać (dodawać, odejmować...)

Mamy 3 kolumny, ale to jeszcze nie wszystko. Dodamy klucze! Czym są klucze? Dają nam one unikalność danych w kolumnie, szybkość wyszukiwania i definiują również jaka kolumna jest indeksem w tabeli. Dodamy 2 klucze, ponieważ ID ma być indeksem tabeli (PRIMARY KEY), a sid musi być koniecznie unikalne. Możemy to pominąć, ale zobaczycie jak to ułatwi później budowę zapytania :) Więc indeksy:
  • PRIMARY KEY (`id`)
  • UNIQUE KEY `sid` (`sid`)
No dobrze, ale co gdy mamy sieć serwerów, a czas chcemy dla każdego serwera zapisywać osobno? Trzeba każdemu serwerowi nadać jakieś id (najlepiej w formie liczby i najlepiej też zapisać je po prostu w osobnej tabeli w bazie danych, w której będą dane odnośnie serwerów). Wtedy dodamy tylko kolumnę oznaczającą nasz serwer
`server` INT(11) NOT NULL
oraz zmodyfikujemy indeks `sid` na taki:
UNIQUE KEY `server_sid` (`server`, `sid`)
Jak ten indeks zadziała? Ano nie pozwoli on, aby w bazie znajdował się wpis z takim samym Steam ID oraz takim samym numerem serwera. Czyli gdy mamy 2 takie same Steam ID, ale inne serwery to wpisy te mogą istnieć, tak samo gdy 2 inne SteamID, a 2 takie same serwery.

Cała struktura tabeli, w języku SQL będzie wyglądała tak:
CREATE TABLE IF NOT EXISTS `godziny` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `server` int(11) NOT NULL,
  `sid` varchar(24) NOT NULL,
  `time` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `server_sid` (`server`,`sid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;


Wstawianie i aktualizacja danych
Teraz przejdziemy do tego, co na serwerze. Pomyślmy co musimy zrobić w naszym przykładzie od strony serwera? Otóż wstawić nowy rekord w bazie z danymi gracza, lub go aktualizować jeśli już istnieje. Jak można to zrobić? Sprawdzić czy rekord istnieje, jeśli tak to zaktualizować, jeśli nie to wstawić nowy... czyli 2 zapytania dla każdego gracza by się musiały wykonać, ale czy muszą? Pomyślmy... A jakby zapytanie samo zdecydowało czy wstawić, czy zaktualizować? A da się tak? A da :D

Ale pozostaje jeszcze problem przy aktualizacji. Musimy odpowiednio zwiększyć starą wartość czasu, a nie wstawiać nową bezmyślnie, podmieniając starą... Możemy pobrać po prostu starą wartość, dodać i wpisać nową... NIE, tak nie zrobimy! Bo to też oznacza 2 zapytania (co prawda niekoniecznie w ciągu, jedno po drugim, ale dwa!).

Więc mamy do wyboru: Odpowiedni warunek używając SELECT, UPDATE oraz INSERT INTO w jednym zapytaniu... Długie ono niestety wyjdzie i ciężko jest je skonstruować. Drugim rozwiązaniem jest REPLACE INTO. Działa ono tak, że stary rekord usuwa, gdy taki istnieje, a następnie tworzy nowy. Tutaj niestety nie możemy się do starej wartości odwołać. Mamy jeszcze jakieś rozwiązania?

Tak, mamy. Dzięki odpowiednio skonstruowanym kluczom możemy po prostu użyć INSERT INTO. No nie tak po prostu, dopiszemy na końcu ON DUPLICATE KEY UPDATE, co spowoduje, że gdy zapytanie INSERT się nie powiedzie, z powodu istniejących już wartości w polach unikalnych, zostanie wykonane UPDATE. Niestety to UPDATE, jest z pewnych powodów trochę uproszczone w porównaniu do klasycznego.

Najpierw skonstruujmy samego INSERTa:
INSERT INTO `czasy` (`server`, `sid`, `time`)
VALUES (%d, '%s', %d)

Jak widać proste zapytanie :) Dla czytelności podzieliłem na 2 linie. Teraz nasze UPDATE:
INSERT INTO `czasy` (`server`, `sid`, `time`)
VALUES (%d, '%s', %d)
ON DUPLICATE KEY UPDATE
`time` = `time`+%d
Oto i nasz update. Tak, tak się da, serwer SQL wtedy ładnie zwiększy `time` o wartość przez nas podaną. Jednakże napiszemy to troszkę inaczej.
INSERT INTO `czasy` (`server`, `sid`, `time`)
VALUES (%d, '%s', %d)
ON DUPLICATE KEY UPDATE
`time` = `time`+VALUES(`time`)
Ta funkcja spowoduje pobranie wartości, którą podaliśmy przy INSERT. Niby wychodzi troszkę większa ilość znaków, ale za chwilę zobaczycie dlaczego tak.


Odpowiednie umiejscowienie w kodzie pluginu
Teraz rzecz na której ludzie najczęściej się potykają. Kiedy wysyłać dane na serwer? Najprościej by było gdy gracz się rozłączy i pod koniec mapy, co sprowadza się do jednego: client_disconnect. A to jest błąd, duży błąd... Gdyż oznacza to przy pełnym 32 slotowym serwerze wysłanie 32 zapytań pod koniec mapy. Może i niedużo, ale jednak coś. Pytania nie są wysyłane na raz, ale po kolei. Nie mam tu na myśli, że zakończy się jedno, a wyśle drugie. Wysyłane są po kolei, a odbierane w kolejności wysłania. Więc jeśli np 15 zapytanie utknie, to reszta musi czekać. Jeśli odpowiedź z 7 utknie to znów reszta na odbiór musi czekać. Przydałoby się to upchnąć w plugin_end w jednym zbiorczym, np tak:
INSERT INTO `czasy` (`server`, `sid`, `time`) VALUES
(%d, '%s', %d),
(%d, '%s', %d),
(%d, '%s', %d),
(%d, '%s', %d)
ON DUPLICATE KEY UPDATE
`time` = `time`+VALUES(`time`)
Wszak można wrzucić od razu wszystkich graczy w ten sposób (tu jest tylko 4). Ale hmm.. Najpierw się wykonują wszystkie client_disconnect, a dopiero później plugin_end. Więc trzeba jakoś to "przechwycić". Dodatkowym problemem jest to, że będzie potrzebna bardzo duża tablica, aby to wszystko zmieścić. Najpierw poradźmy sobie z 2 problemem, co nam częściowo rozwiąże 1. Zauważasz pewnie tutaj dlaczego wcześniej polecilem użyć tego "magicznego" VALUES. Otóż gdy dodajemy kilka rekordów to nie mamy już możliwości wpisania tam konkretnej wartości, a ta funkcja zadba o to, aby dla każdego wpisu była użyta wartość podana przy próbie jego zainsertowania ;)

Otóż AMX ma to do siebie (jak duża część języków programowania), że lepiej przyjmuje duże tablice, gdy są one tablicami globalnymi, niż lokalnymi. Czyli zdefiniujmy sobie query na początku pliku sma, a nie w samej funkcji tej tablicy używającej. Wielkość query sobie trzeba policzyć. Tutaj mamy na pierwszą linię 53 znaki (wraz z enterem). Na lnii z danymi graczy mamy wstawione zmienne. trzeba policzyć jaką długość każda z nich zajmie. Znaczy liczyć nie trzeba, mamy to w bazie danych: 11, 24 i 11. W sumie jest to 46. do tego 2 przecinki, 2 nawiasy, 2 spacje (dla optymalizacji można je usunąć), 2 apostrofy, przecinek na końcu i enter. 10 znaków, czyli łącznie z tymi wstawionymi ze zmiennych mamy 56. Przemnóżmy to razy 32, wychodzi 1792. Teraz 2 ostatnie linie, mają one odopwiednio 24 i 31 znaków (łącznie z enterem i nullem na ich końcach). Sumujemy i wychodzi: 1900 (o, jaka równa liczba :D). Taką właśnie tablicę musimy sobie zadeklarować. To jest oczywiście przypadek pesymistyczny, więc pewnie do końca jej nigdy nie zapełnimy :)

Teraz problem numer 1. Jak go rozwiązać? W bardzo prosty sposób, w client_disconnect zamiast wykonywać zapytania, będziemy dopisywać do głównego naszego zapytania odpowiednie linie dla każdego "wychodzącego" gracza i wyślemy to zapytanie w plugin_end. Dodatkowo co jakiś czas (proponuję 60 sekund) będzie wykonywany task, który sprawdzi, czy jakiś gracz nie rozłączył się w trakcie trwania mapy i jeśli się rozłaczył (i dopisał do głównego zapytania) to to zapytanie wyślemy :) Pamiętać trzeba o kilku rzeczach: zanim zaczniemy zbierać do zapytania wartości, należy dodać początek, czyli pierwszą linię. Druga rzecz, tuż przed wysłaniem zapytania musimy skasować przecinek z ostatnio wpisanej pozycji (nie przewidzimy przecież wcześniej, że więcej już pozycji nie będzie, a jeśli precinek zostawimy to zapytanie się nie wykona, gdyż będzie błędne!) i dopisanie końcówki (ON DUPLICATE....). Początek najlepiej wpisać przy plugin_init oraz po każdym wysłaniu zapytania (oczywiście nadpisać nim cały napis, a nie dopisywać). Końcówkę tuż przy wysyłaniu :) Dodatkowo jeszcze musimy zadbać o to, aby nie wysyłać zapytania bez wstawionego żadnego wiersza. W tym celu najlepiej utworzyć sobie licznik, inkrementować go przy każdym dodaniu do zapytania wiersza, sprawdzić go przed wysłaniem zapytania, czy nie wynosi zero, a po wysłaniu wyzerować.

Dodatkowo możemy w tasku przejechać się pętlą po wszystkich graczach na serwerze i też wysłać ich dane, dzięki czemu przy crashu nie stracą oni dorobku z całej mapy, ale tylko najwyżej z ostatniej minuty (jeśli co minutę task się wykonuje oczywiście).

Jest jeszcze jedna rzecz. Twórcy AMX, a ściślej biblioteki sqlx przestrzegają przed używaniem ThreadedQuery w plugin_end. Dlatego polecam użyć tutaj tzw trybu liniowego (synchronicznego). Nie spowoduje to "widocznego" laga na serwerze, gdyż gracze w tym momencie będą czekać na zmianę mapy, a czas trwania tej zmiany tak samo się przez to wydłuży, jak przy ThreadedQuery (serwer przed zmianą mapy czeka, aż wszystkie zapytania ThreadedQuery zostaną zakończone).

Druga część poradnika w #12 poście w tym temacie.
  • +
  • -
  • 23


#586252 HLDS VoiceTranscoder

Napisane przez `L3G1T. w 17.11.2013 17:37

Plugin powinien działać na wersjach HLDS od 4382 do 6153. 
Plugin wymaga dproto w wersji 0.9.356
Plugin nie dziala z kodekiem voice_miles.

Funkcje:

  • Konwerterowanie na żywo głosu z kodeku voice_speex do SLIK i na odwrót.
  • Zmienianie glośności głosu przy konwerterowaniu.
  • Ochrona przed floodem pakietów głosowych.

CVARy:

  • sv_voicevolume_speex - Zmienianie głośności przy konwerterowaniu Speex->SLIK
  • sv_voicevolume_silk - Zmienianie glośnościu przy konwerterowaniu SLIK->Speex
  • sv_voicefloodms -  Zapobieganie dużej ilości pakietow głosowych w małych odstępach spowodowanych np. przez SpeedHack'a (minimalny czas pomiędzy pakietami, 0 oznacza wyłączenie tej funkcji)

Obecna wersja : v80
Instalacja:

  • Wejdż do <gamedir> i skopiuj folder addons z paczki.
     
  • Gdy już to zrobisz udaj sie do folderu metamoda i dodaj po dproto w plugins.ini:
    • Windows:
      win32 addons\vtc\vtc.dll
    • Linux:
      linux addons/vtc/vtc.so

Znane problemy :

  • Moduł jest włączony ale gracze nie mogą mówić. Aby naprawić ten problem musisz usunąć te linijki w pliku liblist.gam :
  • gamedll "dlls\mp.dll"
    gamedll "dlls\hl.dll"
    gamedll_linux "dlls/cs_i386.so"
    gamedll_linux "dlls/hl_i386.so"
    gamedll_linux "dlls/cs.so"
  • Jeśli to nie pomoże lub masz jakiś inny problem napisz w temacie log z pluginu. (logs/vtc.log)

Changelog :

  • 79-80
    • Dodane dodatkowe logowanie (logs/vtc.log)
    • Ustawianie parametru sv_voicecodec na voice_speex.
    • Domyślna wartość cvar'u sv_voicefloodms wynosi teraz 0.
  • 78-79
    • Naprawiono bug z cvar'em sv_voicefloodms (gracze nie mogli mówić po zmianie mapy)

Download : http://www69.zippysh...50525/file.html
Źródło : http://cs.rin.ru/for...hp?f=10&t=63814


  • +
  • -
  • 12


#628109 de_nust2 by Wheatley

Napisane przez MieTeK_ w 25.03.2014 19:21

Cześć! Od pewnego czasu tworzyłem tą mapę próbując zachować jak najlepszą jakość/fps.

Dla ciekawskich powiem że jest to pewnym odbiciem lustrzanym dust2 :)

 

Screeny :

5331c7d99681c.jpg

5330a1e561274.jpg

5330a1960f7f8.jpg

5331c7df93c79.jpg

5331c7f492152.jpg

 

Download : http://cs.gamebanana.com/maps/179754


  • +
  • -
  • 7


#458862 Piłka do JailBreak by Cypis

Napisane przez Cypis' w 16.09.2012 21:39

Plugin nie jest w pełni mojego autorstwa autorem głównym jest xPaw, plugin przerobiłem tak, aby dodawał piłkę automatycznie na mapę jeżeli jest już na mapie "standardowa piłka"

Model piłki:
Dołączona grafika

Komendy:

jail_pilka - pokazuje menu do stworzenia piłki


say /ball - to samo co jail_pilka
say /reset - resetuje piłke na swoją pozycje

Załączone pliki


  • +
  • -
  • 21


#5907 Jak zainstalować PodBot'y do Amx Mod X

Napisane przez baku w 17.05.2008 16:16

A więc najpierw sciągasz PodBoty :
http://www.sendspace.pl/file/acJqww7E/

Wrzucasz je do cstrike/addons

Następnie w addons/metamod/plugins.ini dopisujesz linike :
;; PodBot
win32 addons/podbot/podbot_mm.dll
linux addons/podbot/podbot_mm_i386.so
Wchodzimy do: /cstrike/addons/podbot i otwieramy notatnikiem podbot.cfg. Szukamy linijki pb_password "pomiędzy cudzysłowami wpisz twoje hasło"

Teraz załączasz cs'a i w konsoli wpisujesz :
setinfo _pbadminpw "tutaj wpisz hasło ktore wpisałeś w podbot.cfg"
A tu zrób sobie binda na menu :
bind "=" "pb menu"
Pod przyciskiem = masz podbota

I to wszystko ;]


Tutorial wykonany dla www.amxx.pl
Copyright � 2008 baku. Kopiowanie zabronione.

  • +
  • -
  • 114


#611579 Amnestia

Napisane przez DarkGL w 01.02.2014 09:59

Związku ze zmianą własciciela forum o raz administracji postanowiliśmy ( w sumie już zgodnie z tradycją ) dać możliwość osobom zbanowanym poprawy się i powrotu na forum.

 

Osoby które zgłoszą się do mnie zostaną odbanowane lub dostaną możliwość stworzenia nowego konta.

 

Użytkownicy którzy posiadają kilka kont proszeni są o korzystanie tylko z jednego konta i zgłoszenie tego administracji. Konta z które należą do różnych osób a korzysta się z nich na tym samym komputerze np. rodzeństwo też należy zgłaszać.


  • +
  • -
  • 16


#625943 FunPoints

Napisane przez MAGNET w 16.03.2014 18:41

opis

Plugin wprowadza na serwer tzw. FunPoints'y, dzięki którym możemy rozwinąć swoje statystyki

Do wyboru mamy:

- Multijump

- Gravy

- Niewidka

- DMG

- Pancerz

 

Każdą statystykę można rozwinąć do maksymalnie 3-ego poziomu, a do rozdania mamy 5 punktów (wyjątkiem jest multijump - aby mieć podwójny skok, trzeba władować 3 punkty w ową statystykę). Plugin nie polega na tym, że rozwijamy statystyki za zabójstwa, monety, czy coś w tym stylu - pointy może ładować każdy. [ Polecam plugin na serwery 4FUN ]

 

 

@EDIT

Dodałem również wersję z większą ilością punktów dla gracza z określoną flagą [nie testowane]:

#define ADMIN_FLAG ADMIN_LEVEL_A /// flaga potrzebna do przydzielenia wiekszej ilosci pointow
#define ILOSC 5 /// ilosc pointow dla zwyklego gracza bez flagi
#define ILOSC_VIP 8 /// ilosc pointow dla gracza z flaga ADMIN_FLAG

inne informacje

Dziękuję za pomoc z menu 9579 

 

download

Załączone pliki


  • +
  • -
  • 5


#257586 Awanse klas

Napisane przez Goliath w 10.06.2011 19:48

Na prośbę jednego z użytkowników zrobiłem system awansowania klas. Doszedłem do tego drogą prób i błędów, więc kod może nie być w pełni optymalny, ale przynajmniej działa Dołączona grafika.

Uwaga! Wymagana znajomość pojęcia "kompilacja lokalna". Jeżeli nie wiesz, co to jest, odwiedź ten temat - http://amxx.pl/topic...ilowac-pluginy/

1. Otwieramy plik QTM_CodMod.sma.
2. Do zmiennych globalnych dodajemy:
new awanse[MAX_ILOSC_KLAS+1][3], awansuje_do[MAX_ILOSC_KLAS+1], awansuje_z[MAX_ILOSC_KLAS+1];
new ilosc_awansow;

3. Na koniec pliku dopisujemy:
public ZarejestrujAwans(plugin, params)
{
if(params != 9)
return PLUGIN_CONTINUE;

if(++ilosc_klas > MAX_ILOSC_KLAS)
return -1;

pluginy_klas[ilosc_klas] = plugin;

new awans_z = get_param(1);
awansuje_do[awans_z] = ilosc_klas;
awansuje_z[ilosc_klas] = awans_z;
ilosc_awansow++;
awanse[ilosc_awansow][1] = ilosc_klas;
awanse[ilosc_awansow][0] = awans_z;
awanse[ilosc_awansow][2] = get_param(2);
get_string(3, nazwy_klas[ilosc_klas], MAX_WIELKOSC_NAZWY);
get_string(4, opisy_klas[ilosc_klas], MAX_WIELKOSC_OPISU);

bronie_klasy[ilosc_klas] = get_param(5);
zdrowie_klas[ilosc_klas] = get_param(6);
kondycja_klas[ilosc_klas] = get_param(7);
inteligencja_klas[ilosc_klas] = get_param(8);
wytrzymalosc_klas[ilosc_klas] = get_param(9);

return ilosc_klas;
}

public ZnajdzAwans(Z, Do)
{
new Return;
for(new i=1; i<=ilosc_awansow; i++)
{
if(awanse[i][0] == Z && awanse[i][1] == Do)
{
Return = i;
break;
}
}
return Return;
}

public JestAwansem(klasa)
{
new bool:jest;
for(new i=1; i<=ilosc_awansow; i++)
{
if(awanse[i][1] == klasa)
{
jest = true;
break;
}
}
return jest;
}

4. Do publica plugin_natives dodajemy:
register_native("cod_register_advance", "ZarejestrujAwans");

5. Zmieniamy public WybierzKlase na:
public WybierzKlase(id)
{
new menu = menu_create("Wybierz klase:", "WybierzKlase_Handle");

new klasa[50], dana_klasa, numer[10];
for(new i=1; i <= ilosc_klas; i++)
{
if(JestAwansem(i))
continue;
WczytajDane(id, i);
dana_klasa = i;

for(; ;)
{
if(awansuje_do[dana_klasa] && poziom_gracza[id] >= awanse[ZnajdzAwans(dana_klasa, awansuje_do[dana_klasa])][2])
{
dana_klasa = awansuje_do[dana_klasa];
WczytajDane(id, dana_klasa);
}
else break;
}
formatex(klasa, charsmax(klasa), "%s \yPoziom: %i", nazwy_klas[dana_klasa], poziom_gracza[id]);
num_to_str(dana_klasa, numer, 9);
menu_additem(menu, klasa, numer);
}

WczytajDane(id, klasa_gracza[id]);

menu_setprop(menu, MPROP_EXITNAME, "Wyjdz");
menu_setprop(menu, MPROP_BACKNAME, "Poprzednia strona");
menu_setprop(menu, MPROP_NEXTNAME, "Nastepna strona");
menu_display(id, menu);

client_cmd(id, "spk QTM_CodMod/select");
}

6. Zmieniamy public WybierzKlase_Handle na:
public WybierzKlase_Handle(id, menu, item)
{
client_cmd(id, "spk QTM_CodMod/select");

if(item == MENU_EXIT)
{
menu_destroy(menu);
return PLUGIN_CONTINUE;
}

new data[65], name[65], acces, callback
menu_item_getinfo(menu, item, acces, data, 64, name, 64, callback)
item = str_to_num(data);

if(item == klasa_gracza[id] && !nowa_klasa_gracza[id])
return PLUGIN_CONTINUE;

nowa_klasa_gracza[id] = item;

if(klasa_gracza[id])
client_print(id, print_chat, "[COD:MW] Klasa zostanie zmieniona w nastepnej rundzie.");
else
{
UstawNowaKlase(id);
DajBronie(id);
ZastosujAtrybuty(id);
}

return PLUGIN_CONTINUE;
}

7. W publicu SprawdzPoziom, po ZapiszDane(id), dopisujemy:
	if(awansuje_do[klasa_gracza[id]])
{
if(poziom_gracza[id] >= awanse[ZnajdzAwans(klasa_gracza[id], awansuje_do[klasa_gracza[id]])][2])
{
set_hudmessage(212, 255, 85, 0.31, 0.32, 0, 6.0, 5.0);
ShowSyncHudMsg(id, SyncHudObj2,"Osiagajac poziom %i, awansowales do klasy %s!", poziom_gracza[id], nazwy_klas[awansuje_do[klasa_gracza[id]]]);
nowa_klasa_gracza[id] = awansuje_do[klasa_gracza[id]];
UstawNowaKlase(id);
DajBronie(id);
ZastosujAtrybuty(id);
ZapiszDane(id);
}
}

Jeżeli chcesz, aby na nową klasę przechodził poziom, exp, statystyki itd., zastąp w/w funkcję tą:
		if(awansuje_do[klasa_gracza[id]])
{
if(poziom_gracza[id] >= awanse[ZnajdzAwans(klasa_gracza[id], awansuje_do[klasa_gracza[id]])][2])
{
set_hudmessage(212, 255, 85, 0.31, 0.32, 0, 6.0, 5.0);
ShowSyncHudMsg(id, SyncHudObj2,"Osiagajac poziom %i, awansowales do klasy %s!", poziom_gracza[id], nazwy_klas[awansuje_do[klasa_gracza[id]]]);
new temp_int = inteligencja_gracza[id], temp_zdr = zdrowie_gracza[id], temp_kon = kondycja_gracza[id], temp_wyt = wytrzymalosc_gracza[id], temp_exp = doswiadczenie_gracza[id], temp_lvl = poziom_gracza[id];
nowa_klasa_gracza[id] = awansuje_do[klasa_gracza[id]];
UstawNowaKlase(id);
poziom_gracza[id] = temp_lvl;
doswiadczenie_gracza[id] = temp_exp;
wytrzymalosc_gracza[id] = temp_wyt;
zdrowie_gracza[id] = temp_zdr;
kondycja_gracza[id] = temp_kon;
inteligencja_gracza[id] = temp_int;
punkty_gracza[id] = (poziom_gracza[id]-1)*2-inteligencja_gracza[id]-zdrowie_gracza[id]-wytrzymalosc_gracza[id]-kondycja_gracza[id];
DajBronie(id);
ZastosujAtrybuty(id);
ZapiszDane(id);
}
}

8. Zapisujemy i kompilujemy plik. Otwieramy plik include/codmod.inc. Dopisujemy na koniec tego pliku to, a następnie go zapisujemy:
native cod_register_advance(z_klasy, od_levela, const nazwa[], const opis[], bronie, punkty_zdrowia, punkty_kondycji, punkty_inteligencji, punkty_wytrzymalosci);

9. Wszystko jest już gotowe, ale nie mamy zdefiniowanych żadnych awansów. Teraz się tym zajmiemy. Zacznę od omówienia parametrów natywu cod_register_advance.
z_klasy - id klasy, kt&#243;ra ma awansować w tą klasę,
od_levela - wymagany level do awansu,
Reszta parametr&#243;w nie r&#243;żni się od tych z cod_register_class
10. Klasę, w którą będzie się awansować tworzymy praktycznie tak samo, jak zwykłą. Musimy tylko użyć natywu cod_register_advance, zamiast cod_register_class. Użycie natywu wygląda tak:
cod_register_advance(cod_get_classid("Snajper"), 60, nazwa, opis, bronie, zdrowie, kondycja, inteligencja, wytrzymalosc);

I teraz w stworzoną przez nas klasę, będzie awansować inna klasa - Snajper, po osiągnięciu 60 poziomu. A to plik .sma przykładowej klasy - Elitarnego Snajpera:
Załączony plik  codawans_elitesnajper.sma   1,4 KB  1765 Ilość pobrań
  codawans_elitesnajper.amxx

Gotowiec:
Załączony plik  awanse.sma   41,62 KB  1652 Ilość pobrań
  awanse.amxx

Dodatki/alternatywne wersje:
- Wersja kompatybilna z frakcjami DarkGL'a - http://amxx.pl/topic...post__p__262120
- Klasy nie awansują, ale odblokowywują się po osiągnięciu danego poziomu na danej klasie - http://amxx.pl/topic...post__p__259522
- Klasy nie awansują, ale odblokowywują się po osiągnięciu danego poziomu na danej klasie (jeżeli mamy wgrane frakcje) - http://amxx.pl/topic...post__p__262954
- Informacje o awansach w menu /klasy - http://amxx.pl/topic...post__p__263164

Mam nadzieję, że coś zrozumieliście i nie będziecie mieli problemów ze zrobieniem tego na swoim CoD'zie Dołączona grafika.
  • +
  • -
  • 75


#448734 Game Score 0.2

Napisane przez Misiaczek ;c w 19.08.2012 20:53

Game Score 0.2
by MisieQ

opis

Plugin Dodaje pod radarem statystyki gry, czyli: ilość żyjących ludzi, ilośc żyjących zobimbie, ilość rund wygranych przez ludzi, ilość rund wygranych przez zombie, ilość rund zremisowanych, i ogolną ilośc rund jaką zagrano

wymagane moduly
Cstrike
HamSandWich
ZombiePlague 4.3 bądź 5.0.x

screenshot
Dołączona grafika

instalacja
Lista Zmian:
0.2
* Porawienie funkcji zliczania Zombie i Ludzi
* Nowy sposób wyświetlania HUD'a
0.1
*Pierwsze Wydanie

download

Załączone pliki


  • +
  • -
  • 6


#195217 [Tutorial dla początkujących] Ruletka

Napisane przez dasiek w 10.12.2010 15:44

Siemanko :)

Chciałbym wam pokazać jak w łatwy sposób każdy może napisać własną Rultekę na serwer.;)
Więc na początku :
Definiujemy biblioteki z których mają być pobierane komenty. W amxx studio z automatu jest to
#include <amxmodx>
#include <amxmisc>

jednak nie wystarczą nam one więc dodamy jeszcze :D
Polecam:

#include <fun> <-Sprawy związane z graczem (jego życiem,kamizelką,grawitacją,szybkością itp)
#include <cstrike> <-Podobne co wyżej tylko "Trudniejsze" xd




początek Pluginu (dla tych co korzystają z notatnika w amxx studio jest z automatu to) :


#include <amxmodx>
#include <amxmisc>
#include <fun>
#include <cstrike>
#include <fakemeta>
#include <engine>

#define PLUGIN "Ruletka_Tutek" //<-Nazwa Pluginu
#define VERSION "1.28" //<-Wersja (tak dla szpanu dodany że niby zpachowana itp)
#define AUTHOR "CheQ" //<- Autro pluginu


public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR); // <- To jest po to by 2 raz nie wprwoadzac Danych o Pluginie
}


Bez public_init plugin nam nie będzie działał więc nie usuwamy go xD

Zaczynamy główne pisanie :D

w public_init() dodajemy linijke która będzie nam przywoływać ruletke gdy gracz wpisze w
say'u np /rulecia
Dodajemy:

register_clcmd("say /rulecia","rulecia");


W pierwszych cudzysłowiach określamy co dany gracz musi wpisać W KONSOLI żeby uruchomić rulecie
(dlatego piszemy say /rulecia gdyż mamy ten sam efekt jakbyśmy pisali w czacie)
dla lepszego działania określimy to żeby odpalało naszą rulecie jak gracz będzie pisał do teamu

register_clcmd("say_team /rulecia","rulecia");


i oto jakieś 10 % roboty xD

czas na pisanie głównego programu
zamykającej klamerze ("}") dajemy ENTER żeby nasz plugin ładniej wyglądał
i piszemy funkcje rulecia

public rulecia(id)
{
//Tu będzie kod naszej funkcji rulecia
}

Gdybyśmy Tego nie zrobili nie zapisalibyśmy bo ponieważ nie znalazłoby funkcji "rulecia" którą zadeklarowaliśmy
gdy gracz wpisze w czacie /rulecia.

dopisaliśmy (id) po to, by ruletka była losowana dla pojedyńczego gracza a nie dla całego serwera.
Teraz element Losowania. Służy do tego komenda:

switch(random_num(1, 4)) // swich()-wybierz, Random_num()-spomiędzy
{
//kod
}

w ten oto sposób nasza ruletka będzie miała 4 elementy
aby dodać więcej elementów piszemy np dla 500 elementów:

switch(random_num(1, 500))
{
//kod
}

czas opisać co ma losować.

po klamerkach otwierających piszemy numer i dalej co ma robić jeśli go wylosuje.

switch(random_num(1, 4))
{
case 1 :
{
//Kod
}
}

Opiszemy Teraz że jedną z naszych atrakcji na ruletce jest ustawienie HP do 1 :)

switch(random_num(1, 4))
{
case 1 :
{
client_print(id,print_chat,"Masz 1 HP"); // Client print i print chat ustawia nam że
graczowi zostaje (w tym przypadku) wypisanie
Masz 1 HP
set_user_health(id,1); // ustawia graczowi HP na 1 (pierwsza wartość-konkretny gracz a nie
cały serwer a druga to ilość HP

}


Jak nie ma błędów przy zapisywaniu jest dobrze :D

teraz coś o Dodawaniu czegoś. Robimy to za pomocą komendy

give_item(id,"przedmiot");


np przy wyborze numeru 2 gracz dostanie m4 :)

Kod:

c
ase 2:
{
client_print(id,print_chat,"Dostajesz M4");
give_item(id,"weapon_m4a1");
//dodajmy tez magazynek xd
give_item(id, "ammo_556nato");
}


i gracz po wylosowaniu dostanie M4.
Gdy napiszemy
case 3:
{
client_print(id,print_chat,"Masz Pecha");

}

gracz nie dostanie nic. Wyskoczy mu na chacie że ma pecha. :)

na 4 rzecz wpadniecie sami :)
Teraz zakończymy losowanie klamrą


switch(random_num(1, 4))
{
case 1 :
{
client_print(id,print_chat,"Masz 1 HP"); // Client print i print chat ustawia nam że
graczowi zostaje (w tym przypadku) wypisanie
Masz 1 HP
set_user_health(id,1); // ustawia graczowi HP na 1 (pierwsza wartość-konkretny gracz a nie
cały serwer a druga to ilość HP

}
case 2:
{
client_print(id,print_chat,"Dostajesz M4");
give_item(id,"weapon_m4a1");
//dodajmy tez magazynek xd
give_item(id, "ammo_556nato");
}
case 3:
{
client_print(id,print_chat,"Masz Pecha");

}
} // <-o Ta!


i cały public rulecia też. Nasz plugin wygląda tak :)

#include <amxmodx>
#include <amxmisc>
#include <fun>
#include <cstrike>
#include <fakemeta>
#include <engine>

#define PLUGIN "Ruletka_Tutek"
#define VERSION "1.28"
#define AUTHOR "CheQ"


public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR);
register_clcmd("say /rulecia","rulecia");
register_clcmd("say_team /rulecia","rulecia");
}
public rulecia(id)
{
switch(random_num(1, 4))
{
case 1 :
{
client_print(id,print_chat,"Masz 1 HP");
set_user_health(id,1);


}
case 2:
{
client_print(id,print_chat,"Dostajesz M4");
give_item(id,"weapon_m4a1");

give_item(id, "ammo_556nato");
}
case 3:
{
client_print(id,print_chat,"Masz Pecha");

}
case 4:
{
client_print(id,print_chat,"Masz 100 HP");
set_user_health(id,100);

}
}
}


Nie wiem jak wam ale mi się Skompilowało bez błędów.
aby ruletke rozbudować polecam poczytać o operacjach na graczu naprawde jest z Tym fajna zabawa. :)

Tutorial Wykonany przez CheQ. (Hakuna Matata xD)
Kopiowanie i rozpewszechnianie dozwolane jedynie z podpisem autora.

Jest to mój pierwszy tutorial więc proszę nie pisać rzeczy w stylu "po co to i dlaczego" czy coś. Komuś to się może przydać ;)
  • +
  • -
  • 25


#624570 Perk Dający Premium

Napisane przez dasiek w 10.03.2014 14:00


#include <amxmodx>
#include <amxmisc>
#include <codmod>
 
#define PLUGIN "Premiium"
#define VERSION "1.0"
#define AUTHOR "CheQo CheQo Lada!"
 
#define FLAGA_PREMIUM ADMIN_LEVEL_H
 
new bool:ma_flage[33];
 
 
public plugin_init() {
	register_plugin(PLUGIN, VERSION, AUTHOR)
	
	cod_register_perk(PLUGIN,"Dodaje Premium");
}
public cod_perk_enabled(id)
{
	if(ma_flage[id])
		return COD_STOP;
		
	set_user_flags(id,FLAGA_PREMIUM);
	return COD_CONTINUE;
}
public cod_perk_disabled(id)
{
	if(ma_flage[id])
		return COD_CONTINUE;
		
	remove_user_flags(id,FLAGA_PREMIUM);
	return COD_CONTINUE;
}
public client_authorized(id)
{
	ma_flage[id] = false;
	if(get_user_flags(id) & FLAGA_PREMIUM)
		ma_flage[id] = true;
}
public client_disconnect(id)
	ma_flage[id] = false;
 

Było kilka tematów z prośbą o takowy perk.  U mnie działa. Instalacja Standardowa - Do pliku - kompilujemy , do plugins , wpisujemy w plugins-codmod.ini i działa. 

jako że w codzie standardowo Premium to ADMIN_LEVEL_H tak właśnie ustawiłem. Jeśli macie inaczej zmiencie flagę o tu

#define FLAGA_PREMIUM ADMIN_LEVEL_H

  • +
  • -
  • 17


#400266 Auto demo-recorder (Nagrywanie dema)

Napisane przez Drzanas w 22.04.2012 15:13

A po tygodniu gry folder cstrike_polish 5 GB :D
  • +
  • -
  • 2


#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
  • 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
[kotwica='wstep']Wstęp[/kotwica]
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)
Tym samym, poszczególne pluginy mogą być od siebie zależne, a ich kolejność ma znaczenie.
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>

public plugin_init(){
register_plugin("Nauka AMXX", "0.1", "benio101");
}
Przypomnijmy, w pierwszej linijce zaimportowaliśmy wymaganą zawsze dla AMXX, bibliotekę amxmodx.
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 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)
#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, 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!)

public DeathMsg(){
new killer=read_data(1);
if(is_user_connected(killer)){
// Dodawanie pieniedzy
}
}
Teraz skorzystamy z natywów biblioteki cstrike i dodamy zabójcy 200 dolarów.
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 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:
#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.


#590861 [Zapowiedz] AMXX Editor Online

Napisane przez DarkGL w 06.12.2013 17:24

Zrzut ekranu z 2013-12-02 13:10:31.png

 

Cel to wpełni działające środowisko programistyczne w przeglądarce ( wraz z znanymi ułatwieniami tzn. generatory ) oraz możliwość przenoszenia kodu między różnymi komputerami itp.

 

Mam nadzieję że projekt uda się ukończyć jednak jest mnóstwo problemów z obsługą w różnych przeglądarkach oraz problemów wydajnościowych.


  • +
  • -
  • 63


#1804 Włączenie/Wyłączenie pluginów na danej mapie

Napisane przez bicek w 02.03.2008 06:26

Włączenie/Wyłączenie pluginów na danej mapie jest bardzo proste, wystarczy w addons/amxmodx/configs zrobić nowy folder o nazwie maps a w nim plik o nazwie plugins-nazwa_mapy.ini, otwieramy go i dopisujemy pluginy w taki sam sposób jak do plugins.ini. Oprócz tego możemy także wyłączyć pluginy które są już włączone w plugins.ini na danej mapie, w pliku plugins-nazwa_mapy.ini dopisujemy:
plugin_którego_nie_chcemy.amxx disabled

Przykład:
Załóżmy, że na mapie de_dust chcemy mieć włączone warcraft3.amxx i csdm.amxx a nie chcemy atac.2.5.5.5.amxx, amxx_atac_cfg.1.1.09.amxx i server_rules.amxx
W addons/amxmodx/configs/maps robimy plik o nazwie plugins-de_dust.ini i dopisujemy do niego:
warcraft3.amxx
csdm.amxx
atac.2.5.5.5.amxx disabled
amxx_atac_cfg.1.1.09.amxx disabled
server_rules.amxx disabled

Możemy też ustawić pluginy dla danych grup map wystarczy, ze zamiast plugins-de_dust.ini nazwiesz plik plugins-de.ini i od tej pory na wszystkich mapach zaczynających się na de_ będą te pluginy (wymagany AMXX 1.8.0 lub nowszy).