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
 

dog_1 - zdjęcie

dog_1

Rejestracja: 09.02.2009
Aktualnie: Nieaktywny
Poza forum Ostatnio: 06.01.2013 20:37
-----

#498210 Da się dodać taki napis do diablo

Napisane przez sebul w 06.01.2013 12:47

Da się.
  • +
  • -
  • 1


#486600 Byty, istotne zdarzenia i studium pluginu

Napisane przez Gość w 03.12.2012 20:04

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


[kotwica=cel]Cel[/kotwica]
  • Nauka o istocie bytów
  • Przedstawienie istotnych zdarzeń
  • Tworzenie optymalnych pluginów
[kotwica=wymagania]Wymagania[/kotwica]
  • 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
[kotwica=forwardy_klienta]Forwardy klienta[/kotwica]
Poza poznanymi już funkcjami związanymi z samym pluginem,
istnieją także forwardy, wywoływane na podstawie czynności gracza.

Przykładowe funkcje to:[kotwica=client_ingame]client_ingame[/kotwica]
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ą.

[kotwica=client_cmd]client_cmd[/kotwica]
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);
}


[kotwica=HLTV_event]HLTV event[/kotwica]
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.

[kotwica=Spawn_graczy]Spawn graczy[/kotwica]
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.

[kotwica=Byty]Byty[/kotwica]
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.

[kotwica=Spawn_graczy_cd]Spawn graczy, c.d.[/kotwica]
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.

[kotwica=Start_rundy]Start rundy[/kotwica]
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"

[kotwica=Koniec_rundy]Koniec rundy[/kotwica]
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.

[kotwica=Reset_rundy]Reset rundy[/kotwica]
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.

[kotwica=Liczenie_rund]Liczenie rund[/kotwica]
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;
}


[kotwica=studium]Studium pluginu: Bonus pieniężny[/kotwica]
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.

[kotwica=switch]Switch[/kotwica]
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.

[kotwica=get_maxplayers]get_maxplayers[/kotwica]
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;
}
}
}
}
}


[kotwica-losowanie]Losowanie[/kotwica]
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.

[kotwica=nagroda]Nagroda[/kotwica]
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!");
}
}
}


[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
#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!");
}
}
}


[kotwica=limitacja_nagrod]Limitacja nagród[/kotwica]
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?

[kotwica=dzialanie_koniunkcji_i_alternatywy]Działanie koniunkcji i alternatywy[/kotwica]
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.

[kotwica=optymalizacja_warunkow_logicznych]Optymalizacja warunków logicznych[/kotwica]
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.

[kotwica=unikanie_zapytan_do_HLDS]Unikanie zapytań do HLDS[/kotwica]
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.

[kotwica=kolejne_warunki_studium]Kolejne warunki studium[/kotwica]
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;
}



#486597 Komunikacja z graczem

Napisane przez Gość w 03.12.2012 20:00

Tutorial dla początkujących
Komunikacja z graczem
Scripting AMXX


[kotwica='cel']Cel[/kotwica]
Nauka podstawowych metod komunikacji gracza z serwerem

[kotwica='wymagania']Wymagania[/kotwica]
  • Informacje wstępne
    Spoiler
  • Zrozumienie istoty działania AMXX
  • Znajomość podstawowych funkcji
  • Umiejętność imptowania bibliotek
  • Zwracanie odpowiedniej wartości funkcji
  • Odczytywanie argumentów wiadomości
[kotwica='logevents']Logevents[/kotwica]
Jak już wiemy z poprzedniego kursu, funkcja register_event pozwala nam zarejestrować dowolne zdarzenie silnika HLDS.

Jednakże, możemy rejestrować także wystąpienie pewnych wiadomości poprzez funkcję register_logevent
Funkcja register_logevent jednak, jako, że rejestruje jedynie wystąpienie wiadomości, będącej wynikiem
wywołania danej operacji, nie może na tę operację wpływać, a jedynie pozyskać informację o wykonaniu danej operacji.

Pierwszym argumentem funkcji register_event jest nazwa funkcji, wykonywanej w momencie odnotowania danego zdarzenia.
Drugim parametrem jest liczba argumentów, które będziemy odczytywać. W kolejnych, opcjonalnych argumentach, możemy ograniczyć
notowane zdarzenia funkcji filtrami, operując na poszczególnych parametrach, licząc argumenty od 0. Liczba kolejnych
argumentów filtrujących jest dowolna, a niespełnienie choć jednego z nich, nie wywoła funkcji z pierwszego parametru.

[kotwica='filtry_logevents']Filtry logevents[/kotwica]
Do dyspozycji mamy następujące filtry:
  • Równość
    arg=val
    
    Argument nr arg musi być dokładnie taki, jak podana wartość val, np.
    "0=World triggered"
    
  • Nierówność
    arg!val
    
    Argument nr arg nie może zawierać podanej wartości val, np.
    "0!World triggered"
    
  • Większość
    arg>val
    
    Argument nr arg musi być większy, niż podana wartość val, np.
    "1>2"
    
  • Mniejszość
    arg<val
    
    Argument nr arg musi być mniejszy, niż podana wartość val, np.
    "3<4"
    
  • Zawieranie
    arg&val
    
    Argument nr arg musi zawierać wartość val, np.
    "1&spawn"
    
Przykład pełnej funkcji rejestrującej spawn gracza z bombą:
register_logevent("spawnedWithBomb", 3, "1=triggered", "2=Spawned_With_The_Bomb");

Jednakże, co w przypadku, gdy chcielibyśmy zarejestrować zarówno spawn z bombą,
jak i otrzymanie bomby (np. poprzez podniesienie z ziemi) za pomocą register_event?
Jak pamiętamy, funkcja zostanie wywołana, o ile koniunkcja warunków z argumentów opcjonalnych zostanie spełniona.
W przypadku chęci rejestracji otrzymania bomby (czy to przez podniesienie, czy otrzymanie wraz ze spawnem) bowiem,
potrzebujemy alternatywy tych warunków. I na to jest rozwiązanie! Z pomocą przychodzi nam funkcja read_logargv.

[kotwica='read_logargv']read_logargv[/kotwica]
Funkcja ta odczytuje zawartość zadanego w pierwszym argumencie, parametru zdarzenia logowanego (licząc od zera)
i zapisuje do tablicy o nazwie z drugiego argumentu o maksymalnym rozmiarze z trzeciego argumentu funkcji read_logargv.
Zobaczmy to na przykładzie:
#include <amxmodx>

public plugin_init(){
register_plugin("Bomb get detect", "0.1", "benio101");

register_logevent("playerTriggered", 3, "1=triggered");
}

public playerTriggered(){
new akcja[64];
read_logargv(2, akcja, 64);

if(
equali(akcja, "Spawned_With_The_Bomb") ||
equali(akcja, "Got_The_Bomb")
){
// Jakis gracz otrzymal bombe
}
}
Rejestrujemy logevent i ograniczamy go jedynie do równości drugiego argumentu z "triggered".
Następnie, w funkcji playerTriggered, pobieramy zawartość trzeciego argumentu do zmiennej akcja.
Jeśli akcją jest otrzymanie bomby lub spawn z bombą, co sprawdzamy w warunku połączonym alternatywą,
to oznacza, że Jakiś gracz otrzymał bombę. Teraz pozostanie nam odczytać jego id i napiszemy mu to.
#include <amxmodx>

public plugin_init(){
register_plugin("Bomb get detect", "0.1", "benio101");

register_logevent("playerTriggered", 3, "1=triggered");
}

public playerTriggered(){
new akcja[64];
read_logargv(2, akcja, 64);

if(
equali(akcja, "Spawned_With_The_Bomb") ||
equali(akcja, "Got_The_Bomb")
){
// Jakis gracz otrzymal bombe

new arg0[64], name[64], argid, id;
read_logargv(0, arg0, 64);

parse_loguser(arg0, name, 64, argid);
id=find_player("k", argid);

client_print(id, print_chat, "Otrzymales bombe!");
}
}
Pobraliśmy tutaj zawartość pierwszego argumentu do zmiennej arg0, następnie pobraliśmy nick gracza za pomocą funkcji parse_loguser,
by na końcu odnaleźć jego właściwe id za pomocą funkcji find_player i wyświetlić mu komunikat o otrzymaniu bomby.

[kotwica='lkomunikacja_serwera_z_graczem']Komunikacja serwera z graczem[/kotwica]
Rozgrywka multiplayer na serwerze możliwa jest dzięki komunikowaniu się klientów gry oraz serwera HLDS.
Każde kliknięcie myszy, nachylenie się, czy zmiana pozycji u gracza, a także wywołania jakiejś komendy,
wpływają na informacje przesyłane od klienta do serwera gry. Z drugiej strony, serwer także systematycznie
komunikuje się z nami, przesyłając informacje o naszej pozycji, punktach zdrowia, czy pojawiającym się nowym granacie dymnym i jego lokalizacji.

Podczas, gdy większość operacji wykonywana jest po stronie serwera (jak spawny graczy, ruch zakładników, czy tykanie bomby),
to część wykonywana jest po stronie gracza i serwer nie ma na nie wpływu, jak np. ruch gracza, czy ustalanie odrzutu broni przy strzale.

[kotwica='Iiformacje_nieosiagalne']Informacje nieosiągalne[/kotwica]
Poza operacjami, których charakterystyka, dokładny opis, bądź których informacja o wykonaniu, są przesyłane pomiędzy serwerem HLDS, a klientami,
istnieją także operacje, które nie zostają ujawnione dla drugiej strony, zarówno po stronie serwera, jak i u klienta.
Przykładem tych drugich jest np. wywołanie komendy zmiany slotu bądź łączenia się z określonym serwerem.

Warto więc zapamiętać, że nie na wszystkie operacje mamy wpływ, a niektóre czynności gracza mogą nie być dla nas dostępne nawet do odczytania.
Jak już wspomniałem, m.in. informacja o wywołaniu niektórych komend, czyli wpisaniu ich w konsolę, są przesyłane do serwera, a więc możemy je odnotować.

[kotwica='komendy_gracza']Komendy gracza[/kotwica]
Tutaj z pomocą przychodzi nam funkcja register_clcmd, która rejestruje daną komendę u gracza i pozwala na wykonanie danych operacji.
#include <amxmodx>

public plugin_init(){
register_plugin("Komenda klienta", "0.1", "benio101");

register_clcmd("test", "test");
}
W powyższym kodzie widzimy zarejestrowaną komendę test (pierwszy parametr), która zostanie wysłana do AMXX i wywołana zostanie funkcja test (za nazwę funkcji do wywołania odpowiada drugi parametr). Nic nie stoi na przeszkodzie, by nazwa rejestrowanej komendy oraz funkcji, były takie same.

Dodamy zatem funkcję, która zostanie wywołana po wpisaniu przez klienta, polecenia "test" i wyświetlimy na chacie ogólnym temu graczowi, słowo "test".
#include <amxmodx>

public plugin_init(){
register_plugin("Komenda klienta", "0.1", "benio101");

register_clcmd("test", "test");
}

public test(id){
if(is_user_connected(id)){
client_print(id, print_chat, "test");
}
}

W praktyce jednak, najczęściej korzysta się z komendy say, która zbindowana jest u większości graczy pod klawiszami y oraz u.
Chat czy team_chat, to nic innego, jak komenda say z danym parametrem, który podajemy w trakcie gry bez potrzeby otwierania konsoli.

[kotwica='client_print']client_print[/kotwica]
Funkcja client_print wysyła dla gracza o id podanym w pierwszym parametrze, tekst z trzeciego argumentu w określone miejsce drugim parametrem.
  • print_notify (alternatywnie 1) wyśle wiadomość do konsoli gracza, o ile jest w trybie deweloperskim (rzadko używane)
  • print_console (alternatywnie 2) wyśle wiadomość do konsoli gracza bez względu na to, czy jest w trybie deweloperkim, czy nie
  • print_chat (alternatywnie 3) wyśle wiadomość na chat gracza, widoczny w grze (najczęściej używana opcja)
  • print_center (alternatywnie 4) wyśle wiadomość na samym środku ekranu gracza (trudno ją przegapić)
Używanie nazw print_[notify|console|chat|center] zamiast cyfer jest możliwe, dzięki zastosowaniu struktury typu enum.
Podanie w pierwszym argumencie zera zamiast numeru gracza, wiadomość zostanie wysłana do wszystkich graczy na serwerze.

[kotwica='chat_i_team_chat']Chat i TeamChat[/kotwica]
Tak więc, zarejestrowanie wydania komendy na chacie jest możliwe, poprzez dodanie prostego "say " lub "say_team " przed
komendą, gdyż docelowo, klient wysyła właśnie komendę poprzedzoną tymi poleceniami do serwera.
Zarejestrujemy teraz przykładową komendę "test" powiedzianą na chacie oraz na team_chacie.
#include <amxmodx>

public plugin_init(){
register_plugin("Komenda klienta", "0.1", "benio101");

register_clcmd("say test", "test");
register_clcmd("say_team test", "test");
}

public test(id){
if(is_user_connected(id)){
client_print(id, print_chat, "Powiedziales test");
}
}
Przejdziemy teraz do bardziej praktycznego zastosowania, czyli do ukrycia na chacie wpisania komendy,
rozpoczynającej się slashem, które zwyczajowo oznaczają specjalną komendę, jak /me czy /hp, wyświetlającą obrażenia.

[kotwica='ukrycie_wpisanych_komend']Ukrycie wpisanych komend[/kotwica]
Poza ujrzeniem zadanych, czy otrzymanych obrażeń, nie chcemy, by wszyscy widzieli ten wpis na chacie.
W tym celu zarejestrujemy funkcję say oraz say_team i będziemy blokować wysyłanie komendy do silnika gry,
o ile pierwszym znakiem będzie slash, za pomocą zwrócenia PLUGIN_HANDLED_MAIN. Main, ponieważ nie chcemy
blokować dalszego przepływu informacji innym pluginom, wpisanym niżej w pliku konfiguracyjnym serwera, plugins.ini
#include <amxmodx>

public plugin_init(){
register_plugin("Niewyswietlanie komend ze slashem", "0.1", "benio101");

register_clcmd("say", "say");
register_clcmd("say_team", "say");
}

public say(id){
new txt[192];
read_args(txt,192);
remove_quotes(txt);

if(equali(txt[0],"/")){
return PLUGIN_HANDLED_MAIN;
}

return PLUGIN_CONTINUE;
}


[kotwica='blokada_kupowania_broni']Blokada kupowania broni[/kotwica]
Teraz przejdziemy do bardzie praktycznego przykładu, mianowicie
postaramy się zablokować możliwość kupowania broni, granatów i tarczy.

W tym celu będziemy rejestrować daną komendę na kupowanie,
a następnie blokować jej wysyłanie do silnika gry HLDS.

Najpierw jednak, musimy zadać sobie pytanie, w jaki sposób dokonywany jest zakup?
Otóż, standardowo, można korzystać z 2 rodzai menu, bądź poprzez komendę na kupno.
Ostatecznie, komenda w menu, docelowo i tak wysyła do serwera komendę na kupno broni.
Tak więc, pozostaje nam jedynie, wszelkie takie komendy zablokować i kupowanie nie będzie możliwe.

Tutaj odsyłam do podstawowych informacji o broniach: CS Weapons Information
Nazwy komend do blokowania widnieją w kolumnach BUYNAME oraz BUYNAME2.
Druga Kolumna komend na kupowanie, zawiera nazwy ze starszych wersji CSa,
które wciąż są dostępne, by zachować kompatybilność skryptów bindujących.

Nie uwzględnienie tych komend w procesie blokowania, pozwoli nam na kupowanie broni
poprzez wpisanie alternatywnych komend w konsolę, a funkcja, która działa częściowo,
działa źle, gdyż dalej pozostaje możliwość zakupu broni, czego nie chcielibyśmy.

Do spisu komend broni, dodamy kupowanie amunicji (priamammo i secammo), kamizelki (vest i vesthelm),
noktowizora (nvgs), zestawu rozbrajającego (defuser) oraz komend kupowania autobuy i rebuy.
Profilaktycznie, zablokujemy także komendy cl_[set](auto|re)buy oraz komendę buy.

Mając pełen spis komend, wystarczy zarejestrować je wszystkie i następnie zablokować.
Żeby nie tworzyć niepotrzebnie mnóstwa podobnych komend (czyli stosując zasadę DRY),
wpiszemy te wszystkie komendy w tablicę i zarejestrujemy te komendy przy użyciu pętli.
#include <amxmodx>

new static weaponsBuyNames[][]={
"p228", "shield", "scout", "hegren", "xm1014", "mac10", "aug", "sgren", "elites", "fn57",
"ump45", "sg550", "galil", "famas", "usp", "glock", "awp", "mp5", "m249", "m3", "m4a1",
"tmp", "g3sg1", "flash", "deagle", "sg552", "ak47", "p90", "228compact", "autoshotgun",
"bullpup", "fiveseven", "krieg550", "defender", "clarion", "km45", "9x19mm", "magnum",
"smg", "12gauge", "mp", "d3au1", "nighthawk", "krieg552", "cv47", "c90", "primammo",
"secammo", "vest", "vesthelm", "nvgs", "defuser", "autobuy", "rebuy",
"cl_autobuy", "cl_setautobuy", "cl_setrebuy", "cl_rebuy", "buy"
}

public plugin_init(){
register_plugin("Blokada kupowania", "0.1", "benio101");

for(new i=0; i<sizeof weaponsBuyNames; ++i){
register_clcmd(weaponsBuyNames[i], "block");
}
}

public block(){
return PLUGIN_HANDLED_MAIN;
}



#418568 Diablo Mod by Stachu

Napisane przez Stachuu :D ?? w 07.06.2012 14:11

Witam was bardzo serdecznie postanowilem zamiescic dzis moje Diablo.
Na wstepie powiem ze jest to odkopany plik sma (ostatnio edytowany okolo 4 miechy temu)
wiec nie mam do niego modeli plikow .txt .
mysle ze bedzie on sluzyl jako pomoc przy robieniu wlasnych Dm

Moze troche o tym co jest w tym calym pliku sma

1.Gildie (by me)
2.Artefakty
3.Wlasny system questow
4.27 klas
5.Przynajmniej 5 calkiem nowych mocy (licze tylko te ktorych odpowiednikow nie spotkalem na innych serwerach/lub wyszlyodemnie)

Nie mam glowy aby rozpisywac all wiec zamieszczam plik i zycze powodzenia w przeszukiwaniu moda :P

W razie pytan piszcie w tym temacie.


Załączony plik  newdiablo.sma   348,53 KB  3720 Ilość pobrań
  newdiablo.amxx
  • +
  • -
  • 56


#356658 DiabloMod by Gh0st

Napisane przez Gh0st w 01.02.2012 19:38

Diablo Mod Edited Gh0st
Przedstawiam wam mój diablo mod, zrobiony na potrzeby mojego serwera.
  • Max 100Lv.
  • Exp Raczej Slow
Informacje:
Link do orginalnego DiabloModa, gdzie znajdują się modele oraz wszystko potrzebne do jego wgrania na serwer ( cvary ... itp )
http://amxx.pl/topic/8621-diablo-mod-59l-sql/
To co mogę powiedzieć o mojej jakże skromnej i moim zdaniem dobrej przeróbce można powiedzieć to:
  • Punkty Mana ( mojego autorstwa )
  • Rozbudowany sklep za Punkty powyżej
  • Możliwość Kupna klasy Diablo, za uzbierane punkty mana
  • Klasa premium ( ADMIN_LEVEL_H - T )
  • Frakcje
  • Podział opisów klas na frakcje
  • 2 Nowe statystyki. ( Niewidzialność od 35 Poziomu / Kasa )
  • Usprawniona baza danych
  • Łatwa możliwość edycji sklepu za punkty mana, poprzez tablice.
  • Sklep z dodatkowymi skilami, za Mane.
Ta edycja diablo moda, za czasów jak miałem serwer nie sprawiała dla mnie żadnych problemów, nie było żadnych błędów dotyczących Diablo, Mogę powiedzieć że jestem zadowolony bo po ilości zgłaszanych bugów / errorów osiągniecie czegoś takiego nie było łatwe :)

Nie będę go rozwijał gdyż wstawiłem go tylko dlatego, że marnował mi się na dysku. Jedyne o co proszę to... nie podszywajcie się pod autora tej edycji, nie tak jak było z Diablomod by Onyke, 100 wiadomości na gg miałem, czy nie chce kupić :o, choć wątpię żeby było takie zainteresowanie :)

Załączone pliki


  • +
  • -
  • 17


#414118 Optymalizacja bazy i podstrona klas.

Napisane przez fexus w 25.05.2012 12:47

zamiast
for(i=1; i<12; i++)

daj
for(i=1; i<9; i++)


Miałem ten sam błąd - teraz wyświetla mi poprawnie menu. Mam nadzieję że pomogłem :P
  • +
  • -
  • 1


#301007 [ROZWIĄZANE] Limity klas

Napisane przez KariiO w 27.09.2011 16:53

na górę:
new ograczenie_magow[33]
przykład:
case 0:
		{
			new maksymalna_ilosc
			sprawdz_ograniczenie(id)  
	   	 if (ograniczenie_magow[id]<maksymalna_ilosc) player_class[id] = Mag
			else {
			hudmsg(id,2.0,"Nie mozna bylo wybrac tej klasy gdyz za duzo osob ja aktualnie posiada !")
			select_class_query(id)
		    return PLUGIN_HANDLED
		   }
		}
dół:
public sprawdz_ograniczenie(id)
{
	new players[32], num;
	get_players(players, num,"a")
 
		for(new i=0; i<num; i++){
			new id_graczy = players[i];
		if (player_class[id_graczy]==Mag) ograniczenie_magow[id]++
}
}
gdyby był warning to na na dół funkcji od wyboru klasy daj return PLUGIN_CONTINUE
  • +
  • -
  • 2


#363510 Item "Piorun Zeusa"

Napisane przez Angel of Death w 12.02.2012 20:36

Opis Itemu:
Masz losową szansę na to że trafisz wroga piorunem.

Wymagany moduł: hamsandwich

Wygląda to tak:
Dołączona grafika

No to do dzieła:

1. Dodajemy zmienną globalną:
new piorun_zeusa[33] = 1


2. W public "reset_item_skills" dodajemy
piorun_zeusa[id] = 0

3. W public "iteminfo(id)" dodajemy:
if (piorun_zeusa[id] &--#62; 0)
{
num_to_str(piorun_zeusa[id],TempSkill,10)
add(itemEffect,699,"Masz 1/")
add(itemEffect,699,TempSkill)
add(itemEffect,699,"szans ,zeby uderzyc we wroga piorunem&--#60;br&--#62;")
}


4. W public "award_item(id, itemnum)" dodajemy kolejny Item'ek, na początku podmieniamy:
new rannum = random_num(1,xxx)
xxx - nasza ilość itemow musimy zwiększyć o jedno aby losowanie odbyło się prawidłowo
case xxx:
za xxx wstawiamy kolejny numer itemu

Dalej...

{
player_item_name[id] = "Piorun Zeusa"
player_item_id[id] = rannum
piorun_zeusa[id] = random_num(8,15)
show_hudmessage(id, "Znalazles przedmiot: %s :: Masz 1/%i szans ,ze trafisz wroga piorunem",player_item_name[id],piorun_zeusa[id])
}
W public damage(id) dodajemy
add_bonus_piorun(attacker_id,id)

5. I na końcu dodajemy:

public add_bonus_piorun(attacker_id,id)
{
if (piorun_zeusa[attacker_id] &--#62;0 && (random_num(1, piorun_zeusa[attacker_id]) == 1))
{
		new Float:fl_Origin[3]
		pev(id, pev_origin, fl_Origin)	
if(cs_get_user_team(attacker_id) == cs_get_user_team(id))
return HAM_IGNORED

set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
set_pev(id, pev_maxspeed, 5.0) // prevent from moving

thunder_effects(fl_Origin)
ExecuteHam(Ham_TakeDamage, id, attacker_id, attacker_id, 40.0, 1);
}
return PLUGIN_HANDLED
}
thunder_effects(Float:fl_Origin[3])
{
	new Float:fX = fl_Origin[0], Float:fY = fl_Origin[1], Float:fZ = fl_Origin[2]



	// Beam effect between two points
	engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, fl_Origin, 0)
	write_byte(TE_BEAMPOINTS)		// 0
	engfunc(EngFunc_WriteCoord, fX + 150.0)	// start position
	engfunc(EngFunc_WriteCoord, fY + 150.0)
	engfunc(EngFunc_WriteCoord, fZ + 800.0)
	engfunc(EngFunc_WriteCoord, fX)	// end position
	engfunc(EngFunc_WriteCoord, fY)
	engfunc(EngFunc_WriteCoord, fZ)
	write_short(sprite_lgt)	// sprite index
	write_byte(1)					// starting frame
	write_byte(15)					// frame rate in 0.1's
	write_byte(10)					// life in 0.1's
	write_byte(80)					// line width in 0.1's
	write_byte(30)					// noise amplitude in 0.01's
	write_byte(255)					// red
	write_byte(255)					// green
	write_byte(255)					// blue
	write_byte(255)					// brightness
	write_byte(200)					// scroll speed in 0.1's
	message_end()

	// Sparks
	message_begin(MSG_PVS, SVC_TEMPENTITY)
	write_byte(TE_SPARKS)			// 9
	engfunc(EngFunc_WriteCoord, fX)	// position
	engfunc(EngFunc_WriteCoord, fY)
	engfunc(EngFunc_WriteCoord, fZ + 10.0)
	message_end()

	// Smoke
	engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, fl_Origin, 0)
	write_byte(TE_SMOKE)			// 5
	engfunc(EngFunc_WriteCoord, fX)	// position
	engfunc(EngFunc_WriteCoord, fY)
	engfunc(EngFunc_WriteCoord, fZ + 10.0)
	write_short(sprite_smoke)		// sprite index
	write_byte(10)					// scale in 0.1's
	write_byte(10)					// framerate
	message_end()
	
	// Blood
	engfunc(EngFunc_MessageBegin, MSG_BROADCAST, SVC_TEMPENTITY, fl_Origin, 0)
	write_byte(TE_LAVASPLASH)		// 10
	engfunc(EngFunc_WriteCoord, fX)	// position
	engfunc(EngFunc_WriteCoord, fY)
	engfunc(EngFunc_WriteCoord, fZ + 12.0)
	message_end()


}

Autorem tak jak w poprzednim przypadku nie jestem ja lecz "M@nkovsky"
Koniec, Enjoy ;)

Dalej...

{
player_item_name[id] = "Piorun Zeusa"
player_item_id[id] = rannum
piorun_zeusa[id] = random_num(8,15)
show_hudmessage(id, "Znalazles przedmiot: %s :: Masz 1/%i szans ,ze trafisz wroga piorunem",player_item_name[id],piorun_zeusa[id])
}
W public damage(id) dodajemy
add_bonus_piorun(attacker_id,id)


Powinno być:
Dalej...
{
player_item_name[id] = "Piorun Zeusa"
player_item_id[id] = rannum
piorun_zeusa[id] = random_num(8,15)
show_hudmessage(id, "Znalazles przedmiot: %s :: Masz 1/%i szans ,ze trafisz wroga piorunem",player_item_name[id],piorun_zeusa[id])
}

A później:
* W public "damage(id)" dodajemy:
add_bonus_piorun(attacker_id,id)

Dodatkowo chcę wspomnieć, że linijką :

ExecuteHam(Ham_TakeDamage, id, 0 , id, 40.0, 1);




.. można edytować obrażenia zadawane przez piorun, zamiast 40.0 dajemy własną liczbę rzeczywistą, np 66.0 - rzeczywistą, czyli koniecznie z np .0 na końcu. Można to też przerobić dodając do tego np +floatround(player_intelligence[id]/5) - czyli przy 100 inteligencji będziecie zadawać SWOJE USTAWIONE + 20 ;]




#372338 Item "Piorun Zeusa"

Napisane przez Nakupenda. w 27.02.2012 23:34

@Tiger_pl: dodaj po ExecuteHam
set_user_frags(attacker_id, get_user_frags(attacker_id) + 1)

  • +
  • -
  • 3


#231911 Prosta edycja, usunięcie say'u

Napisane przez DarkGL w 31.03.2011 19:25

kompiluje sie ? kompiluje , wiec ?
jak masz amx studio to tools->indenter albo w notepad++
TextFX->TextFX Edit->Reindent c++ code
  • +
  • -
  • 2


#303418 Nowe questy a stare funkcje oraz tablice.

Napisane przez sebul w 05.10.2011 18:57

Tak się stanie, najlepiej zrób to w innej funkcji i wykonuj ją podczas gdy paka została rozbrojona/podłożona.
  • +
  • -
  • 1


#299428 Nowe questy a stare funkcje oraz tablice.

Napisane przez sebul w 23.09.2011 22:37

Tam jest jakieś enum? Do tablicy questów zapisz tylko ile trzeba zadać dmg, żeby wykonać questa, a potem sprawdzaj czy jakaś globalna zmienna jest większa bądź równa od wymaganej wartości.
  • +
  • -
  • 1


#296314 Zapytania do bazy

Napisane przez R3X w 14.09.2011 23:42

Wygląda mi to na pracę domową, a może nawet ściągę na egzamin (Miałem coś takiego na zaliczenie przedmiotu z Baz Danych).

Nie zdecydowałeś się zdradzić rodziny języka SQL, więc piszę w tym spod MySQL

1
SELECT koszt/waga
AS "koszt za kg" FROM towar WHERE
waga != 0
ORDER BY "koszt za kg" ASC

2
INSERT INTO tymcz
SELECT opis, koszt/waga
FROM towar
WHERE waga != 0

3.
UPDATE klient
SET wiek=18 WHERE wiek IS NULL
średnia może się zmienić, jeśli średnia przed aktualizacją jest różna od 18

4.
SELECT * FROM TOWAR
WHERE nr NOT
IN(SELECT DISTINCT(towar_nr) FROM zapas)

5.
SELECT MIN(cena), AVG(cena), MAX(cena)
FROM towar, zapas
WHERE towar_nr = nr

6.
BEGIN WORK;
SELECT 1 FROM klient FOR UPDATE;
COMMIT
raczej nic się nie zmieni w tabeli klient
  • +
  • -
  • 1


#295222 Nowe questy a stare funkcje oraz tablice.

Napisane przez sebul w 11.09.2011 20:31

Nie ten public, patrz ten drugi do zapisywania i odczytywania, do tego jak chcesz dodać tylko nowe questy to nie trzeba dodawać nowych zmiennych, wystarczą te dwie co już są w questach darka.
  • +
  • -
  • 1


#286613 [5.9l] Fireball - wybuchanie na respie, itp.

Napisane przez sebul w 28.08.2011 11:47

W standardzie fb ma to do siebie, że wybucha na respie, moście (na aztecu) czy też na bsie. W temacie dowiecie się jak temu zaradzić ;]

Znajdź całą funckję
Spoiler

zamień na
Spoiler

Przy okazji możecie też usunąć linijkę z
register_think("PowerUp","Think_PowerUp")

bo nie zauważyłem, żeby ona do czegoś służyła...

Kod poprawiony, teraz fb nie wybucha przy zwłokach.
  • +
  • -
  • 13