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
 

Byty, istotne zdarzenia i studium pluginuczyli Jak zacząć Scripting AMXX


  • Nie możesz napisać tematu
  • Zaloguj się, aby dodać odpowiedź
11 odpowiedzi w tym temacie

#1 Gość_21977_*

  • Gość

Reputacja: 0

Offline

Napisano 03.12.2012 20:04

*
Popularny

Tutorial dla początkujących
Byty, istotne zdarzenia i studium pluginu
Scripting AMXX


Cel
  • Nauka o istocie bytów
  • Przedstawienie istotnych zdarzeń
  • Tworzenie optymalnych pluginów
Wymagania
  • Znajomość podstawowych metod komunikacji gracza z serwerem
  • Informacje wstępne
    Spoiler
  • Zrozumienie istoty działania AMXX
  • Znajomość podstawowych funkcji
  • Umiejętność importowania bibliotek
  • Zwracanie odpowiedniej wartości funkcji
  • Odczytywanie argumentów wiadomości
Forwardy klienta
Poza poznanymi już funkcjami związanymi z samym pluginem,
istnieją także forwardy, wywoływane na podstawie czynności gracza.

Przykładowe funkcje to:client_ingame
Uwaga! Podczas, gdy client_connect jest pierwszą czynnością dokonywaną w momencie łączenia się gracza z serwerem,
nie można ustalić kolejności wykonywania funkcji client_authorized oraz client_putinserver, mogą być one wykonane w różnej kolejności.
Dlatego zaleca się dla niektórych instrukcji, sprawdzenie wywołania obydwu tych funkcji poprzez utworzenie prostej funkcji client_ingame

Warto znać parę tych podstawowych forwardów z biblioteki amxmodx, gdyż często się przydają.

client_cmd
Serwer może wykonać pewne komendy u klienta tak, jakby on sam je wykonał.
Służy ku temu funkcja client_cmd, która za pierwszy argument
przyjmuje numer identyfikacyjny gracza, a za drugi komendę do wykonania u klienta.
Pozostałe opcjonalne argumenty uzupełniają zmienne w ciągu polecenia z 2. argumentu.

Przykład zastosowania. Funkcja ustawia graczowi interp na 0.01 w momencie pełnego połączenia z serwerem:
public client_ingame(){
new Float:interp=0.01;
client_cmd(id, "ex_interp %d", interp);
}


HLTV event
Pierwszym, użytecznym zdarzeniem, jakie warto zanotować, to event HLTV.
register_event("HLTV", "newRound", "a", "1=0", "2=0");

Jest to zdarzenie, które wysyłane jest do HLTV, jednak można je wykorzystać,
by ustalić moment rozpoczęcia Freezetime, bądź, jak kto woli, początku rundy.

Wziąć należy jednak pod uwagę, że zdarzenie wykonywane jest, poza początkiem
rundy, także tuż po zakończeniu wykonywania się komend startowych serwera.

Uwaga! Podczas, gdy forwardy takie, jak client_authorized czy client_disconnect,
event HLTV ejst eventem globalnym, a więc wywoływany jest jednokrotnie i nie przyjmuje parametru gracza.
Oznacza to, że użycie newRound(id) jest nieprawidłowe, gdyż id nie jest identyfikatorem gracza.

Spawn graczy
Spawn, czyli pojawienie się gracza na mapie, jest zdarzeniem, które powinniśmy wykorzystać,
jeśli chcemy operować na graczu, zanim ten przystąpi do gry, ale po rozpoczęciu nowej rundy.
to tutaj dodajemy bonusowe bronie, lub ustawiamy dodatkowe życie dla danego gracza.
W celu kompleksowej rejestracji spawnu, skorzystamy z eventu Ham_Spawn funkcji RegisterHam z biblioteki HamSandwich.
RegisterHam(Ham_Spawn, "player", "spawned", 1);

Pierwszy parametr oznacza typ rejestrowanego zdarzenia, w tym przypadku spawn, drugi parametr to klasa bytu.

Byty
I tutaj warto wspomnieć o bytach. Otóż niemal każdy obiekt na mapie to byt, czyli istota wirtualna.
Ponadto, każdy byt ma swój unikalny numer identyfikacyjny, klasę i pewne właściwości, jak np. model.
Specjanymi bytami są gracze o numerach identyfikacyjnych od 1 do maksymalnej liczby graczy,
których maksymalną liczbą może być 32. Każdy byt posiada pewną klasę, klasą gracza jest "player".

Ponadto, każdy byt posiada pewne dane prywatne, jak np. model, życie, czy czas następnego procesu myślenia.
Proces myślenia to zdarzenie cykliczne wykonywane co pewien czas, który może być modyfikowany.
Przykładowo, granat wybuchowy posiada proces myślenia, który dokonuje jego eksplozji.
Modyfikacja czasu procesu myślenia tego bytu, czyli wpływanie na dane prywatne bytu,
pozwoli na szybszy, bądź wolniejszy wybuch granatu, lub całkowitą blokadę wybuchu.

Pobieranie danych prywatnych z bytu możliwe jest dzięki następującym funkcjom.
Na forum znajdziemy listę niektórych danych prywatnych bytów w temacie R3Xa, Offsety pdata.

Większość funkcji tak naprawdę operuje na bytach, jak np. funkcja cs_get_user_money,
która pobiera jedynie wartość prywatną od określonego gracza.

Spawn graczy, c.d.
Trzecim argumentem użytej funkcji RegisterHam jest nazwa funkcji, która zostanie wywołana po spawnie,
a ostatni argument ustawiony na 1, odpowiada za wykonanie funkcji po skończonym procesie ożywiania gracza.

W przeciwieństwie do zdarzenia HLTV, funkcja spawned przyjmie za argument id gracza ożywianego.
Jednakże, funkcja spawnu wykonywana jest także podczas wchodzenia gracza na serwer, będącego
jeszcze martwym, dlatego chcąc operować na właśnie ożywionym graczu, należy sprawdzić, czy żyje.
Funkcja Ham_Spawned dla każdego gracza wykonywana jest zawsze po evencie HLTV, ale przed startem rundy.

Start rundy
Po ożywieniu wszystkich graczy i zakończeniu czasu zamrożenia (freezetime), następuje event globalny Round_Start.
register_logevent("roundStart", 2, "1=Round_Start");

Jest to zdarzenie notowane, więc użyjemy funkcji register_logevent, filtrując drugi parametr do równego "Round_Start"

Koniec rundy
Alternatywnie do początku rundy, koniec rundy rejestrujemy dzięki informacji logowanej.
register_logevent("roundEnd", 2, "1=Round_End");

Koniec rundy może nastąpić na wskutek wielu innych czynników, co należy mieć na uwadze.
Ponadto, koniec rundy nie musi nastąpić nigdy, lub nastąpić rzadziej, niż początek rundy.

Reset rundy
register_logevent("GameCommencing", 2, "1=Game_Commencing");

Każdorazowo, w momencie dołączenia do gry pierwszego gracza do drużyny, której przeciwna posiada już wrogów,
dokonywany jest reset gry poprzez wywołanie eventu GameCommencing. Należy to wziąć pod uwagę przy liczeniu rund.

Liczenie rund
W celu policzenia rundy, potrzebować będziemy zmiennej globalnej, którą zainicjujemy tuż po imporcie bibliotek.
#include <amxmodx>

new runda;

public plugin_init(){
register_plugin("Liczenie rund", "0.1", "benio101");
}
Zmienna globalna zostanie początkowo zainicjowana wartością zero, co nam odpowiada, gdyż runda się jeszcze nie rozpoczęła.
Co rundę będziemy inkrementować zmienną runda, a zrobimy to w funkcji newRound eventu HLTV.
#include <amxmodx>

new runda;

public plugin_init(){
register_plugin("Liczenie rund", "0.1", "benio101");
register_event("HLTV", "newRound", "a", "1=0", "2=0");
}

public newRound(){
++runda;
}
Jednakże, ponieważ funkcja HLTV wykonywana jest tuż po starcie serwera,
a po dołączeniu zazwyczaj drugiego gracza, wykonywany jest reset, przez co ponownie
wywoływany będzie event HLTV, rozpoczęlibyśmy grę właściwą ze zmienną runda równą 2 zamiast 0.
Dlatego też zarejestrujemy event Game_Commencing i w momencie jego wystąpienia, zresetujemy licznik rund.

I tym samym sposobem, uzyskamy zmienną runda, która przechowuje numer aktualnej rundy:
#include <amxmodx>

new runda;

public plugin_init(){
register_plugin("Liczenie rund", "0.1", "benio101");
register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}


Studium pluginu: Bonus pieniężny
Teraz, w ramach praktyki, napiszemy prosty plugin, który w 2., 5. i 10. rundzie,
jednemu, losowemu graczowi przyzna 5000 dolarów na zachętę lepszej gry.
Ponadto, postaramy się, by jeden gracz nie uzyskał nagrody kilkukrotnie.
Zaczniemy od powyższej bazy, liczącej rundy, będzie to nam potrzebne.
Dodamy event nowej rundy i kod będzie wyglądał następująco:
#include <amxmodx>

new runda;

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
// dodanie w 2., 5. i 10. rundzie losowemu graczowi 5000$
}
Zacznijmy od warunku. Najprostsza metoda:
public roundStart(){
if(runda==2){
// dodanie losowemu graczowi 5000$
}
if(runda==5){
// dodanie losowemu graczowi 5000$
}
if(runda==10){
// dodanie losowemu graczowi 5000$
}
}
Jednak niepotrzebnie się powtarzamy, stąd pomysł na
public roundStart(){
if(runda==2 || runda==5 || runda==10){
// dodanie losowemu graczowi 5000$
}
}
to rozwiązanie jest dobre, ale nie najlepsze. Dlaczego?
Dokonujemy tak naprawdę trzech porównań, choć zawsze porównujemy zmienną runda.

Switch
Do porównywania jednej zmiennych do kolejno wielu różnych, nadaje się idealnie funkcja switch.
Dzięki zastosowaniu funkcji switch, zaoszczędzimy zasoby sprzętowe i skrócimy czas wykonywania skryptu. Poprawne rozwiązanie:
public roundStart(){
switch(runda){
case 2,5,10:{
// dodanie losowemu graczowi 5000$
}
}
}

Teraz przejdziemy do losowania gracza. w tym celu będziemy musieli poszukać wśród żywych graczy na serwerze poprzez funkcję for.
W tym celu utworzymy sobie tablicę gracze i w niej będziemy przechowywać numery identyfikacyjne osób, kwalifikujących się do losowania.
Dodatkowo, utworzymy zmienną liczbaGraczy, która będzie przechowywać liczbę kandydatów do nagrody, czyli, de facto, żywych graczy.
każdy gracz, który jest żywy, zostanie dodany to tablicy gracze, a następnie liczbaGraczy ulegnie inkrementacji.
#include <amxmodx>

new runda;

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=32; ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
}
}
}
Jednakże, maksymalna liczba graczy nie musi wynosić 32.
Maksymalna liczba graczy (czy też liczba slotów), może być inna.

get_maxplayers
Aby pobrać liczbę slotów, użyjemy funkcji get_maxplayers.
public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=get_maxplayers(); ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
}
}
}
Jednakże, przy każdej iteracji pętli for, dokonujemy zapytania, poprzez MetaModa:P
aż do silnika gry, co jest istotnym błędem i powinniśmy to zoptymalizować.
W tym celu, zainicjujemy zmienną globalną maxPlayers i uzupełnimy ją
w funkcji plugin_cfg i nie będziemy musieli więcej zmiennej pobierać.

Jest to rozwiązanie na tyle dobre, że funkcja plugin_cfg wykonywana jest tylko jednokrotnie
i dzięki pobraniu liczby slotów do zmiennej globalnej, oszczędzimy kolejnych, identycznych
zapytań, do silnika gry. Oczywiście, w naszej pętli, zastąpimy funkcję get_maxplayers zmienną maxPlayers.
#include <amxmodx>

new runda, maxPlayers;

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public plugin_cfg(){
maxPlayers=get_maxplayers();
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
}
}
}


Losowanie
Teraz przejdziemy do losowania zwycięzcy.
W tym celu, użyjemy funkcji random, która dla jedynego argumentu x,
przyjmuje pseudo-losową liczbę naturalną z zakresu [0;x)
Funkcja jest świetnie przystosowana do naszej tablicy gracze,
przyjęwszy za argument zmienną liczbaGraczy, od razu wyłoni nam zwycięzcę.
public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
new zwyciezca=gracze[random(liczbaGraczy)];
}
}
}
Podobną funkcją do random, jest funkcja random_num,
która losuje liczbę z zakresu od pierwszego argumentu, do drugiego włącznie.
Funkcja random jest zatem szczególnym przypadkiem funkcji random_num.
random(x) ⇔ random_num(0, x-1)

Pomimo jednoznaczności, zawsze używanie funkcji random_num z pierwszym argumentem równym zero zamiast
jego prostszej wersji random, jest irracjonalne, gdyż trwa dłużej i zużywa więcej zasobów sprzętowych.

Nagroda
Mając wyłonionego zwycięzcę, dodamy mu 5000$ i poinformujemy o tym jedynie zwycięzcę, by innym nie było smutno.
W tym celu, będziemy tak naprawdę modyfikować jedną z informacji prywatnych pdata zwycięskiego gracza, co można
byłoby zrobić funkcją set_pdata_int i get_pdata_int, jednak skorzystamy z prostszych natywów biblioteki cstrike.
#include <amxmodx>
#include <cstrike>

new runda, maxPlayers;

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public plugin_cfg(){
maxPlayers=get_maxplayers();
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
new zwyciezca=gracze[random(liczbaGraczy)];
cs_set_user_money(zwyciezca, cs_get_user_money(zwyciezca)+5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
}
}
}


#define
Zamiast pisać długą linijkę
cs_set_user_money(zwyciezca, cs_get_user_money(zwyciezca)+5000);
zwłaszcza, jeśli wykorzystywalibyśmy ją wielokrotnie,
warto stworzyć sobie definicję preprocesora, udającą funkcję dodawania pieniędzy.
Zaimplementujemy zatem funkcję add_user_money(id, ammount). W tym celu,
stworzymy pod importowanymi bibliotekami, definicję preprocesora:
#define add_user_money(%1,%2) cs_set_user_money(%1,cs_get_user_money(%1)+%2)

I w miejsce starej, długiej linijki, wstawimy nowo utworzoną funkcję preprocesora add_user_money
#include <amxmodx>
#include <cstrike>

#define add_user_money(%1,%2) cs_set_user_money(%1,cs_get_user_money(%1)+%2)

new runda, maxPlayers;

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public plugin_cfg(){
maxPlayers=get_maxplayers();
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
new zwyciezca=gracze[random(liczbaGraczy)];
add_user_money(zwyciezca, 5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
}
}
}


Limitacja nagród
Teraz dodamy ostatnią rzecz, czyli ograniczymy możliwość wygrania kilkukrotnie przez tę samą osobę.
W tym celu utworzymy sobie tablicę globalną typu logicznego i będziemy przechowywać informację o tym,
który gracz wygrał już swoją nagrodę. Łącznie, nasz plugin ma teraz dwie zmienne i jedną tablicę logiczną:
new runda, maxPlayers, bool:nagrodzeni[33];

W momencie sprawdzania danego gracza w pętli, dodamy warunek na brak bycia nagrodzonym:
public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(!nagrodzeni[id] && is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
new zwyciezca=gracze[random(liczbaGraczy)];
add_user_money(zwyciezca, 5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
}
}
}
Dlaczego jednak warunek w koniunkcji umieściłem po lewej stronie?

Działanie koniunkcji i alternatywy
Koniunkcja działa w taki sposób, że spełniona jest, gdy wszystkie warunki są spełnione.
Gdy choć jeden z nich nie jest spełniony, to cała koniunkcja nie jest spełniona i
nie ma potrzeby sprawdzać kolejnych warunków. Podobnie jest z alternatywą, jeśli
choć jeden z warunków zostanie spełniony, nie ma potrzeby sprawdzać kolejnych.

Optymalizacja warunków logicznych
Tak samo działa nasz AMXX, jeśli jeden z warunków koniunkcji nie zostanie spełniony,
to kolejne nie są sprawdzane. Istotne uwagi jest, że warunki sprawdzane są kolejno od lewej strony.
Wiedząc to, powinniśmy najbardziej prawdopodobne warunki koniunkcji ustalać możliwie najbardziej po prawej stronie,
a te mniej prawdopodobne po lewej, a dla alternatywy zaś odwrotnie, warunki najbardziej prawdopodobne winny być po lewej stronie.

Unikanie zapytań do HLDS
Dlaczego więc umieściłem nasz warunek !nagrodzeni[id] po lewej stronie, gdy wydaje się, że jest on bardziej prawdopodobny,
niż to, że gracz jest martwy? Ponieważ staram się możliwie unikać mocno obciążających maszynę i długich zapytań do
silnika HLDS poprzez Metamoda:P, a funkcja is_user_alive, niewątpliwie do takich należy, dlatego zawsze należy
wszelkie warunki nie wykonujące zapytań do silnika, umieszczać możliwie po lewej stronie koniunkcji czy alternatyw.

Kolejne warunki studium
W przypadku braku odpowiednich kandydatów, nie dodajemy losujemy zwycięzcy, nie dajemy pieniędzy ani nie informujemy gracza o zwycięstwie.
W tym celu, musimy te 3 instrukcje wykonać warunkowo, o ile zmienna liczbaGraczy jest niezerowa.
if(liczbaGraczy){
new zwyciezca=gracze[random(liczbaGraczy)];
add_user_money(zwyciezca, 5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
}
Tworzenie zapytania if(x!=0) gdzie x to warunek jest niepotrzebne i wystarczy samo if(x)
Ostatecznie, funkcja if i tak zwraca prawdę lub fałsz, jedynkę lub zero.

Zwycięzcę trzeba oznaczyć jako wygranego, więc wewnątrz warunku, dopisujemy
nagrodzeni[zwyciezca]=true;

Od teraz, do końca mapy, gracz nie będzie miał szansy wygrać 5000 dolarów.

Jednakże, zwycięski gracz mógł w międzyczasie wyjść z serwera, a w miejsce jego numeru identyfikacyjnego mógł wejść inny gracz.
Dlatego, w momencie wchodzenia gracza na serwer, ustawimy mu wartość zwycięstwa na false, by miał szansę brać udział w losowaniu.
Możliwość reconnecta zwycięzcy nie przeraża nas pomimo otrzymania kolejnej szansy na zwycięstwo, gdyż całą gotówkę w
momencie opuszczenia serwera straci, a jeśli serwer korzysta z pluginu, zapisującego stan gracza, jak np. pieniędzy,
można dodać prosty natyw do tego pluginu, który zapisywałby także i tę, zerojedynkową informację o graczu.

W tym celu, skorzystamy z forwardu client_putinserver, ustawiając zmienną nagrodzeni na fałsz
public client_putinserver(id){
nagrodzeni[id]=false;
}


Gotowy kod z naszego studium, plugin na bonus 5000$ dla losowego gracza z limitem 1 wygranej na mapę w 2., 5. i 10. rundzie:
#include <amxmodx>
#include <cstrike>

#define add_user_money(%1,%2) cs_set_user_money(%1,cs_get_user_money(%1)+%2)

new runda, maxPlayers, bool:nagrodzeni[33];

public plugin_init(){
register_plugin("Bonus pieniezny", "0.1", "benio101");

register_event("HLTV", "newRound", "a", "1=0", "2=0");
register_logevent("roundStart", 2, "1=Round_Start");
register_logevent("GameCommencing", 2, "1=Game_Commencing");
}

public plugin_cfg(){
maxPlayers=get_maxplayers();
}

public newRound(){
++runda;
}

public GameCommencing(){
runda=0;
}

public roundStart(){
switch(runda){
case 2,5,10:{
new gracze[32];
new liczbaGraczy;
for(new id=1; id<=maxPlayers; ++id){
if(!nagrodzeni[id] && is_user_alive(id)){
gracze[liczbaGraczy]=id;
++liczbaGraczy;
}
}
if(liczbaGraczy){
new zwyciezca=gracze[random(liczbaGraczy)];
add_user_money(zwyciezca, 5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
nagrodzeni[zwyciezca]=true;
}
}
}
}

public client_putinserver(id){
nagrodzeni[id]=false;
}

Użytkownik benio101 edytował ten post 09.12.2012 02:59
+kot.


#2 Droso

    Dawniej HubertTM

  • Support Team

Reputacja: 1 291
Godlike

  • Postów:2 371
  • Steam:steam
  • Imię:Hubert
  • Lokalizacja:Wrocław
Offline

Napisano 03.12.2012 20:08

Pytanie dla mnie i może innych osób, jeszcze kiedy się wywołuje client_infochanged? Często w pluginach robię tak, że tam wczytuje dane jeszcze raz, bo gracz zmienił nick (porównuje stary i nowy nick i jeśli true to wywołane wczytanie :P)
speedkill (03.12.2012 20:59):

when any information is changed, for example team or name.


  • +
  • -
  • 0

Piszę pluginy pod: AMX MOD X oraz SOURCE MOD!

Na zlecenie i bez zlecenia zresztą też!


#3 Gość_21977_*

  • Autor tematu
  • Gość

Reputacja: 0

Offline

Napisano 03.12.2012 20:14

Forward client_infochanged jest wywoływany, gdy jakiekolwiek informacje o strukturze gracza ulegną zmianie.
Najczęściej korzysta się z tej funkcji, by odnotować zmianę nicku, jednak wywoływany jest zawsze, gdy zmianie
ulegają jakiekolwiek dane klienta, które można wyciągnąć za pomocą funkcji get_user_info.

#4 K!113r

    Teraz to chyba Sławek kek

  • Power User

Reputacja: 387
Wszechpomocny

  • Postów:868
  • GG:
  • Steam:steam
  • Imię:Mateusz
  • Lokalizacja:Piotrków Tryb.
Offline

Napisano 03.12.2012 20:45

Kolejny świetny poradnik.

Pomimo jednoznaczności, zawsze używanie funkcji random_num z pierwszym argumentem równym zero zamiast
jego prostszej wersji random, jest irracjonalne, gdyż trwa dłużej i zużywa więcej zasobów sprzętowych.


Moim zdaniem powinno się nie używać random_num(), ponieważ funkcją random() możemy uzyskać każdy przedział liczb np. new liczba = random(51) +100 i mamy przedział domknięty od 100 do 150 (wydaje mi się że random() + dodawanie i tak będzie działało szybciej niż random_num() :D )

Jedyna literówka chyba to: utalić
  • +
  • -
  • 1

DarkGL to mój autorytet.

skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować


#5 Fili:P

    Godlike

  • Power User

Reputacja: 754
Guru

  • Postów:1 679
  • Imię:Darek
  • Lokalizacja:Warszawa
Offline

Napisano 03.12.2012 20:49

Nigdy tego nie rozumiałem, nareszcie mam szanse się tego nauczyć !
Świetne, dzięki !
  • +
  • -
  • 0

#6 sNH.

    Czy MisieQ ukradł ciasteczko?

  • Power User

Reputacja: 299
Wszechwidzący

  • Postów:1 070
  • Steam:steam
  • Imię:Bartek
  • Lokalizacja:Ełk
Offline

Napisano 03.12.2012 20:50

Gj
  • +
  • -
  • 0

#7 Nestea****Lemon

    Herbata ?!

  • Użytkownik

Reputacja: 81
Zaawansowany

  • Postów:313
  • GG:
  • Imię:Dawid
  • Lokalizacja:Radzyń Podlaski
Offline

Napisano 04.12.2012 16:41

Gdzie był ten poradnik jak męczyłem się z bytami ? ^D^ , świetna robota !
  • +
  • -
  • 0

cY2lZ.gif

http://nestea-tdm.cba.pl <---- Nestea****Lemon Blog


Aktualnie tworzę moda do Minecrafta ^D^


#8 blakk

    Zaawansowany

  • Użytkownik

Reputacja: 66
Pomocny

  • Postów:124
Offline

Napisano 15.12.2012 17:28

Świetny poradnik, + . :)
  • +
  • -
  • 0

#9 GT Team

    Ten lepszy xD

  • Zbanowany

Reputacja: 321
Wszechpomocny

  • Postów:1 435
  • GG:
  • Imię:Tomasz i Grzegorz
  • Lokalizacja:Wojkowice
Offline

Napisano 23.12.2012 14:42

Poradnik genialny, bardzo przydatny, leci +:)

Nowa wersja Tower Defense 0.2 Alpha | Inne Mody -> Nowości

 


#10 Lacostii

    Profesjonalista

  • Użytkownik

Reputacja: 40
Pomocny

  • Postów:172
  • Lokalizacja:Poland
Offline

Napisano 14.07.2013 19:54

[kotwica=define]#define[/kotwica]
Zamiast pisać długą linijkę
cs_set_user_money(zwyciezca, cs_get_user_money(zwyciezca)+5000);
zwłaszcza, jeśli wykorzystywalibyśmy ją wielokrotnie,
warto stworzyć sobie definicję preprocesora, udającą funkcję dodawania pieniędzy.
Zaimplementujemy zatem funkcję add_user_money(id, ammount). W tym celu,
stworzymy pod importowanymi bibliotekami, definicję preprocesora:
#define add_user_money(%1,%2) cs_set_user_money(%1,cs_get_user_money(%1)+%2)

I w miejsce starej, długiej linijki, wstawimy nowo utworzoną funkcję preprocesora add_user_money

 

 

Dlaczego warto tak robić, oprócz może lepszego wyglądu kodu są jakieś techniczne zalety i czy w każdym przypadku warto tak robić?

PS: Benio, świetne poradniki robisz ;)


  • +
  • -
  • 0

Zapraszam na forum Classic-Zone.pl . ;)


#11 K!113r

    Teraz to chyba Sławek kek

  • Power User

Reputacja: 387
Wszechpomocny

  • Postów:868
  • GG:
  • Steam:steam
  • Imię:Mateusz
  • Lokalizacja:Piotrków Tryb.
Offline

Napisano 14.07.2013 20:06

Zaletą jest szybsze pisanie kodu jeżeli używasz takiej kombinacji funkcji bardzo często, co zostało napisane.


  • +
  • -
  • 0

DarkGL to mój autorytet.

skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować skomplikować


#12 Lacostii

    Profesjonalista

  • Użytkownik

Reputacja: 40
Pomocny

  • Postów:172
  • Lokalizacja:Poland
Offline

Napisano 14.07.2013 20:48

Pisząc o technicznych zaletach miałem na myśli czy takie postępowanie dla serwera ma jakieś zalety, plugin mniej waży, szybciej się wykonuje, mniej obciąża i podobne? Jak Ty K!113r mi odpisałeś to przy okazji spytam czy Twój sposób z random(x) + y ciągle uważasz za lepszy? Tak dociekam, bo wtedy już zawsze bym tak robił, więc wolę się upewnić.


  • +
  • -
  • 0

Zapraszam na forum Classic-Zone.pl . ;)





Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych