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.
|
dog_1
Rejestracja: 09.02.2009Aktualnie: Nieaktywny
Poza forum Ostatnio: 06.01.2013 20:37





Statystyki
- Grupa: Użytkownik
- Całość postów: 150
- Odwiedzin: 6 610
- Tytuł: Profesjonalista
- Wiek: 33 lat
- Urodziny: Sierpień 2, 1991
-
Płeć
Mężczyzna
-
Lokalizacja
Gdańsk
Kontakt
#498210 Da się dodać taki napis do diablo
Napisane przez sebul
w 06.01.2013 12:47
#486600 Byty, istotne zdarzenia i studium pluginu
Napisane przez
Gość
w 03.12.2012 20:04
Byty, istotne zdarzenia i studium pluginu
Scripting AMXX
[kotwica=cel]Cel[/kotwica]
- Nauka o istocie bytów
- Przedstawienie istotnych zdarzeń
- Tworzenie optymalnych pluginów
- Znajomość podstawowych metod komunikacji gracza z serwerem
- Informacje wstępne
Spoiler- 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
- Zrozumienie istoty działania AMXX
- Znajomość podstawowych funkcji
- Umiejętność importowania bibliotek
- Zwracanie odpowiedniej wartości funkcji
- Odczytywanie argumentów wiadomości
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_connect
wywoływana w momencie rozpoczęcia łączenia się gracza z serwerem
- client_authorized
wywoływana w momencie uzyskania przez gracza flag uprawnień
- client_putinserver
wywoływana w momencie pobrania wszelkich wymaganych plików i wejścia do gry
- client_disconnect
wywoływana w momencie wyjścia gracza z serwera
- client_infochanged
wywoływana w momencie zmiany informacji klienta, np. nicku
- client_command
wywoływana w momencie wpisania jakiejkolwiek komendy do konsoli
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

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


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

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

[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>Zmienna globalna zostanie początkowo zainicjowana wartością zero, co nam odpowiada, gdyż runda się jeszcze nie rozpoczęła.
new runda;
public plugin_init(){
register_plugin("Liczenie rund", "0.1", "benio101");
}
Co rundę będziemy inkrementować zmienną runda, a zrobimy to w funkcji newRound eventu HLTV.
#include <amxmodx>Jednakże, ponieważ funkcja HLTV wykonywana jest tuż po starcie serwera,
new runda;
public plugin_init(){
register_plugin("Liczenie rund", "0.1", "benio101");
register_event("HLTV", "newRound", "a", "1=0", "2=0");
}
public newRound(){
++runda;
}
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>Zacznijmy od warunku. Najprostsza metoda:
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$
}
public roundStart(){Jednak niepotrzebnie się powtarzamy, stąd pomysł na
if(runda==2){
// dodanie losowemu graczowi 5000$
}
if(runda==5){
// dodanie losowemu graczowi 5000$
}
if(runda==10){
// dodanie losowemu graczowi 5000$
}
}
public roundStart(){to rozwiązanie jest dobre, ale nie najlepsze. Dlaczego?
if(runda==2 || runda==5 || runda==10){
// dodanie losowemu graczowi 5000$
}
}
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>Jednakże, maksymalna liczba graczy nie musi wynosić 32.
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;
}
}
}
}
}
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(){Jednakże, przy każdej iteracji pętli for, dokonujemy zapytania, poprzez MetaModa:P
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;
}
}
}
}
}
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

#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

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(){Podobną funkcją do random
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)];
}
}
}


która losuje liczbę z zakresu od pierwszego argumentu, do drugiego włącznie.
Funkcja random


random(x) ⇔ random_num(0, x-1)
Pomimo jednoznaczności, zawsze używanie funkcji random_num

jego prostszej wersji random

[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(){Dlaczego jednak warunek w koniunkcji umieściłem po lewej stronie?
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!");
}
}
}
[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

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){Tworzenie zapytania if(x!=0) gdzie x to warunek jest niepotrzebne i wystarczy samo if(x)
new zwyciezca=gracze[random(liczbaGraczy)];
add_user_money(zwyciezca, 5000);
client_print(zwyciezca, print_chat, "Na zachete lepszej gry, wygrales 5000 dolarow!");
}
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

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
Komunikacja z graczem
Scripting AMXX
[kotwica='cel']Cel[/kotwica]
Nauka podstawowych metod komunikacji gracza z serwerem
[kotwica='wymagania']Wymagania[/kotwica]
- Informacje wstępne
Spoiler- 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
- Zrozumienie istoty działania AMXX
- Znajomość podstawowych funkcji
- Umiejętność imptowania bibliotek
- Zwracanie odpowiedniej wartości funkcji
- Odczytywanie argumentów wiadomości
Jak już wiemy z poprzedniego kursu, funkcja register_event

Jednakże, możemy rejestrować także wystąpienie pewnych wiadomości poprzez funkcję register_logevent

Funkcja register_logevent

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

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"
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>Rejestrujemy logevent i ograniczamy go jedynie do równości drugiego argumentu z "triggered".
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
}
}
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>Pobraliśmy tutaj zawartość pierwszego argumentu do zmiennej arg0, następnie pobraliśmy nick gracza za pomocą funkcji parse_loguser
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!");
}
}

by na końcu odnaleźć jego właściwe id za pomocą funkcji find_player

[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

#include <amxmodx>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.
public plugin_init(){
register_plugin("Komenda klienta", "0.1", "benio101");
register_clcmd("test", "test");
}
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

- 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ć)
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>Przejdziemy teraz do bardziej praktycznego zastosowania, czyli do ukrycia na chacie wpisania komendy,
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");
}
}
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
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

W razie pytan piszcie w tym temacie.


#356658 DiabloMod by Gh0st
Napisane przez Gh0st
w 01.02.2012 19:38
Przedstawiam wam mój diablo mod, zrobiony na potrzeby mojego serwera.
- Max 100Lv.
- Exp Raczej Slow
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.

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ć


Załączone pliki
-
SMA I AMXX.rar 267,03 KB 838 Ilość pobrań
-
dbmod_5.9l.amxx 221,3 KB 48 Ilość pobrań
-
dbmod_5.9l.sma 237,31 KB 752 Ilość pobrań
dbmod_5.9l.amxx
#414118 Optymalizacja bazy i podstrona klas.
Napisane przez fexus
w 25.05.2012 12:47
#301007 [ROZWIĄZANE] Limity klas
Napisane przez KariiO
w 27.09.2011 16:53
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
#363510 Item "Piorun Zeusa"
Napisane przez
Angel of Death
w 12.02.2012 20:36
Masz losową szansę na to że trafisz wroga piorunem.
Wymagany moduł: hamsandwich
Wygląda to tak:

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
#231911 Prosta edycja, usunięcie say'u
Napisane przez DarkGL
w 31.03.2011 19:25
#303418 Nowe questy a stare funkcje oraz tablice.
Napisane przez sebul
w 05.10.2011 18:57
#299428 Nowe questy a stare funkcje oraz tablice.
Napisane przez sebul
w 23.09.2011 22:37
#296314 Zapytania do bazy
Napisane przez R3X
w 14.09.2011 23:42
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; COMMITraczej nic się nie zmieni w tabeli klient
#295222 Nowe questy a stare funkcje oraz tablice.
Napisane przez sebul
w 11.09.2011 20:31
#286613 [5.9l] Fireball - wybuchanie na respie, itp.
Napisane przez sebul
w 28.08.2011 11:47
Znajdź całą funckję
public pfn_touch ( ptr, ptd )
{
if (ptd == 0)
return PLUGIN_CONTINUE
new szClassName[32]
if(pev_valid(ptd)){
entity_get_string(ptd, EV_SZ_classname, szClassName, 31)
}
else return PLUGIN_HANDLED
if(equal(szClassName, "fireball"))
{
new owner = pev(ptd,pev_owner)
//Touch
if (get_user_team(owner) != get_user_team(ptr))
{
new Float:origin[3]
pev(ptd,pev_origin,origin)
Explode_Origin(owner,origin,55+player_intelligence[owner],150)
remove_entity(ptd)
}
}
if (ptr != 0 && pev_valid(ptr))
{
new szClassNameOther[32]
entity_get_string(ptr, EV_SZ_classname, szClassNameOther, 31)
if(equal(szClassName, "PowerUp") && equal(szClassNameOther, "player"))
{
entity_set_int(ptd,EV_INT_iuser2,1)
}
if(equal(szClassName, "Mine") && equal(szClassNameOther, "player"))
{
new owner = pev(ptd,pev_owner)
//Touch
if (get_user_team(owner) != get_user_team(ptr))
{
new Float:origin[3]
pev(ptd,pev_origin,origin)
Explode_Origin(owner,origin,55+player_intelligence[owner],150)
remove_entity(ptd)
}
}
if(equal(szClassName, "grenade") && equal(szClassNameOther, "player"))
{
new greModel[64]
entity_get_string(ptd, EV_SZ_model, greModel, 63)
if(equali(greModel, "models/w_smokegrenade.mdl" ))
{
new id = entity_get_edict(ptd,EV_ENT_owner)
if (is_user_connected(id)
&& is_user_connected(ptr)
&& is_user_alive(ptr)
&& player_b_smokehit[id] > 0
&& get_user_team(id) != get_user_team(ptr))
UTIL_Kill(id,ptr,"grenade")
}
}
}
/*if(equal(szClassName, "fireball"))
{
new Float:origin[3]
pev(ptd,pev_origin,origin)
new id = pev(ptd,pev_owner)
Explode_Origin(id,origin,100,player_b_fireball[id] + player_intelligence[id])
remove_entity(ptd)
}*/
return PLUGIN_CONTINUE
}
zamień na
public pfn_touch(ptr, ptd) {
if(!ptd)
return PLUGIN_CONTINUE;
if(!pev_valid(ptd))
return PLUGIN_HANDLED;
new szClassName[32], szClassNameOther[32];
entity_get_string(ptd, EV_SZ_classname, szClassName, 31);
if(ptr && pev_valid(ptr)) {
if(pev(ptr, pev_solid) == SOLID_TRIGGER)
return PLUGIN_CONTINUE;
entity_get_string(ptr, EV_SZ_classname, szClassNameOther, 31);
}
if(equal(szClassName, "fireball"))
{
new owner = pev(ptd,pev_owner)
//Touch
if(get_user_team(owner) != get_user_team(ptr)) {
new Float:origin[3]
pev(ptd,pev_origin,origin)
Explode_Origin(owner,origin,55+player_intelligence[owner],150);
remove_entity(ptd)
}
}
if(equal(szClassNameOther, "player")) {
if(equal(szClassName, "Mine")) {
new owner = pev(ptd, pev_owner);
//Touch
if(get_user_team(owner) != get_user_team(ptr)) {
new Float:origin[3];
pev(ptd, pev_origin, origin);
Explode_Origin(owner,origin,55+player_intelligence[owner],150);
remove_entity(ptd);
}
}
else if(equal(szClassName, "grenade")) {
new greModel[64];
entity_get_string(ptd, EV_SZ_model, greModel, 63);
if(equali(greModel, "models/w_smokegrenade.mdl")) {
new id = entity_get_edict(ptd, EV_ENT_owner);
if(is_user_connected(id) && is_user_alive(ptr)
&& player_b_smokehit[id] > 0 && get_user_team(id) != get_user_team(ptr))
UTIL_Kill(id, ptr, "grenade");
}
}
}
return PLUGIN_CONTINUE;
}
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.
- AMXX.pl: Support AMX Mod X i SourceMod
- → Przeglądanie profilu: Reputacja: dog_1
- Regulamin