(...) tylko właśnie mogłem dodać zmienne consty.
Ale wtedy nie były bo to już zmienne tylko stałe

I nie przypisał byś już do stałej IP pobranego funkcją get_user_ip

To równanie zostało stworzone przy pomocy kodu LaTeX:
Edytor LaTeX online: CodeCogs.com/latex/eqneditor.php
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.
|
Napisane przez Knopers
w 26.09.2010 15:24
Napisane przez Owner123
w 05.09.2010 09:49
stock get_velocity_from_origin( ent, Float:fOrigin[3], Float:fSpeed, Float:fVelocity[3] )
{
new Float:fEntOrigin[3];
entity_get_vector( ent, EV_VEC_origin, fEntOrigin );
// Velocity = Distance / Time
new Float:fDistance[3];
fDistance[0] = fEntOrigin[0] - fOrigin[0];
fDistance[1] = fEntOrigin[1] - fOrigin[1];
fDistance[2] = fEntOrigin[2] - fOrigin[2];
new Float:fTime = ( vector_distance( fEntOrigin,fOrigin ) / fSpeed );
fVelocity[0] = fDistance[0] / fTime;
fVelocity[1] = fDistance[1] / fTime;
fVelocity[2] = fDistance[2] / fTime;
return ( fVelocity[0] && fVelocity[1] && fVelocity[2] );
}
// Sets velocity of an entity (ent) away from origin with speed (speed)
stock set_velocity_from_origin( ent, Float:fOrigin[3], Float:fSpeed )
{
new Float:fVelocity[3];
get_velocity_from_origin( ent, fOrigin, fSpeed, fVelocity )
entity_set_vector( ent, EV_VEC_velocity, fVelocity );
return ( 1 );
}
Napisane przez R3X
w 21.08.2010 13:25
Death(ofiara){ new zabojca = get_user_attacker(id); // nie zawsze się zgadza :/ }
Death(){ new ofiara = read_data(2); new zabojca = read_data(1); // zasze się zgadza }jeśli gracz zginie bez globalnej informacji (np. user_silentkill() czy wybuch bomby) to śmierć gracza nie jest odnotowywana; nie jest także łapana w przypadku message_begin(MSG_ALL, get_user_msgid("DeathMsg")) -> trzeba użyć emessage_*
Napisane przez Owner123
w 17.06.2010 14:31
Witam.
Na wstępnie chciałbym powiedzieć, że nie będę opisywał tu zapytań MySQL ponieważ to mija się z celem. Jeśli ktoś chce się pouczyć zapytań MySQL zapraszam na uw-team.org (nie wiem czy taka reklama jest dozwolona, jeśli tak to prosiłbym o nie wlepianie mi warna). Szczerze polecam Wideotutorial Unknow'a na temat MySQL.
Życzę miłej lekturki.
MySQL, cóż to takiego ?
Edit. Thx 4 R3X
SQL - Structured Query Language (pl. strukturalny język zapytań), jest to nowoczesny język, dzięki któremu można posługiwać się bazami danych. MySQL to popularna odmiana serwera, które potrafi przetwarzać zapytania w tym języku.
Przejdźmy do sedna.
Aby móc zacząć pracować, musimy dołączyć do swojego pluginu dyrektywą #include odpowiednią biblioteke:
#include <sqlx>
native Handle:SQL_MakeDbTuple(const host[], const user[], const pass[], const db[], timeout=0);
new Handle:Tuple = SQL_MakeDbTuple("127.0.0.1", "root", "", "nauka")
native SQL_ThreadQuery(Handle:db_tuple, const handler[], const query[], const data[]="", dataSize=0);
data to jakby tablica parametrow a dataSize to ich ilosc tak jak parametry w set_task o czym jest osobny poradnik
Przykładowe użycie:
new Handle:gTuple, bool:gConnected
[...]
//Tworzymy "pojemnik" i ustawiamy zmienną gConnected na true jeśli wszystko obeszło się bez przeszkód.
SaveData(id)
{
if(!gConnected) return
new Data[1]
Data[0] = id
new qCommand[512], szName[32]
get_user_name(id, szName, charsmax(szName))
format(qCommand, sizeof qCommand-1, "INSERT INTO nauka VALUES(%s, %i, %i);", szName, iPlayerXP[id], iPlayerLvl[id])
SQL_ThreadQuery(gTuple, "SaveHandler", qCommand, Data, 1)
}
public SaveHandler(FailState, Handle:Query, Error[], Errorcode, Data[], DataSize)
{
new id = Data[0]
if(Errorcode)
log_amx("Blad w zapytaniu: %s [SaveData]", Error)
if(FailState == TQUERY_CONNECT_FAILED)
{
log_amx("Nie mozna podlaczyc sie do bazy danych.")
return PLUGIN_CONTINUE
}
else if(FailState == TQUERY_QUERY_FAILED)
{
log_amx("Zapytanie anulowane [SaveData]")
return PLUGIN_CONTINUE
}
return PLUGIN_CONTINUE
}
new Handle:gTuple, bool:gConnected
[...]
//Tworzymy "pojemnik" i ustawiamy zmienną gConnected na true jeśli wszystko obeszło się bez przeszkód.
CheckData(id)
{
if(!gConnected) return
new Data[1]
Data[0] = id
new qCommand[512], szName[32]
get_user_name(id, szName, charsmax(szName))
format(qCommand, sizeof qCommand-1, "SELECT * FROM `nauka` WHERE `nick` = '%s'", szName)
SQL_ThreadQuery(gTuple, "CheckHandler", qCommand, Data, 1)
}
public CheckHandler(FailState, Handle:Query, Error[], Errorcode, Data[], DataSize)
{
new id = Data[0]
if(Errorcode)
log_amx("Blad w zapytaniu: %s [CheckData]", Error)
if(FailState == TQUERY_CONNECT_FAILED)
{
log_amx("Nie mozna podlaczyc sie do bazy danych.")
return PLUGIN_CONTINUE
}
else if(FailState == TQUERY_QUERY_FAILED)
{
log_amx("Zapytanie anulowane [CheckData]")
return PLUGIN_CONTINUE
}
if(!SQL_MoreResults(Query)) // Nie znaleziono wpisów w bazie danych. Możemy spokojnie utworzyć.
DodajWpis(id)
else // A jednak coś znalazł ! Żeby nie robić kolejnej funkcji od razu odczytujemy.
{
iPlayerXp[id] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query, "exp")) // Ponieważ funkcja SQL_ReadResult wymaga ID pola, a my go nie mamy musimy posłużyć się funkcją SQL_FieldNameToNum.
iPlayerLvl[id] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query, "lvl")) // j/w
}
return PLUGIN_CONTINUE
}
while(SQL_MoreResults(Query))
{
new i = SQL_ReadResult(Query, SQL_FieldNameToNum(Query, "klasa"))
srv_avg[i] = SQL_ReadResult(Query, SQL_FieldNameToNum(Query, "AVG"))
SQL_NextRow(Query)
}
while(SQL_MoreResults(Query))
{
//kod
SQL_NextRow(Query)
}
Handle:SQL_Connect(Handle:sqlTuple, &error, szError[], len);
I tutaj strzeżcie się! Pamiętajcie aby ZAWSZE użyc SQL_FreeHandle(Handle:db) jak skończycie majstrować z bazą ! Jak tego nie będziecie robić, serwer będzie crashować bez żadnych error logów. Przykładowe połączenie z bazą wygląda następująco:
public client_authorized(id)
{
new Handle:hConnection, iError, szError[256];
if((hConnection = SQL_Connect(g_hSqlTuple, iError, szError, 255)))
{
// operacje na bazie danych
}
else
{
log_error(AMX_ERR_GENERAL, "Brak polaczenia z baza danych !");
log_error(AMX_ERR_GENERAL, "Kod bledu: %i", iError);
log_error(AMX_ERR_GENERAL, "Tresc bledu: %s", szError);
}
SQL_FreeHandle(hConnection); // PAMIETAJ O TYM BO INACZEJ CZEKA CIE ZGUBA !!!
}
Handle:SQL_PrepareQuery(Handle:connection, fmt[], any:...); bool:SQL_Execute(Handle:query);
Dla ścisłości: funkcja SQL_Execute naprawdę nie zwraca typu bool tylko typ int. Jednak napisałem bool aby uświadomić Tobie, Drogi czytelniku, aby ta funkcja zwraca tylko wartości 1 i 0 aby nas poinformować o tym czy wykonanie zapytania SQL przebiegło poprawnie.
Przejdźmy do małego opisu parametrów:
SQL_PrepareQuery:
Pierwszy parametr: Uchwyt zwrócony przez funkcje SQL_Connect. Tak, właśnie dlatego było nam potrzebne ręczne połączenie się z bazą!
Drugi i reszta parametrów: Treść zapytania. Jest to w miarę elastyczne ponieważ możemy używać znacznikow %d, %s itd. Uwaga! Nie zalecam używanie tu zapytań typu UPDATE ! Zamiast tego polecam użycie zapytań REPLACE, jednak aby działały one poprawnie wymagane jest utworzenie klucza PRIMARY, UNIQUE lub INDEX. Dlaczego? Nawet jeśli kod jest w pełni zoptymalizowany i baza danych stoi na localhoscie, przy dużej ilości rekordów (100k+, czasem 50k+) powodowane są ścinki i lagi serwera.
Rezultat: Uchwyt do wykonania zapytania. Ta funkcja tylko przygotowuje zapytanie !!! Zapytanie jest wykonywane dopiero przy użyciu funkcji SQL_Execute()! I niech was ręka boska broni! Tutaj też uzywajcie funkcji SQL_FreeHandle()!!! Tak samo jak w przypadku SQL_Connect nie użycie tego powoduje crashe serwera bez żadnych logów!
SQL_Execute:
Jest tutaj tylko jeden parametr: Uchwyt zwrócony przez funkcje SQL_PrepareQuery. Wykonanie tej funkcji jest równoznaczne z wywołaniem zapytania, wcześniej przygotowanego przez funkcje SQL_PrepareQuery.
Dobra koniec teorii, czas na podanie przykładowego kodu:
public client_authorized(id)
{
new Handle:hConnection, iError, szError[256];
if((hConnection = SQL_Connect(g_hSqlTuple, iError, szError, 255)))
{
new szNick[32];
get_user_name(id, szNick, 31);
new Handle:hQuery = SQL_PrepareQuery(hConnection, "SELECT * FROM tabela WHERE `nick` = '%s'", szNick);
if(SQL_Execute(hQuery))
{
new num = 0;
while(SQL_MoreResults(hQuery))
{
num = SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "klasa"));
g_iPlayerLvl[id][num] = SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "lvl"));
g_iPlayerExp[id][num] = SQL_ReadResult(hQuery, SQL_FieldNameToNum(hQuery, "exp"));
SQL_NextRow(hQuery)
}
}
else
{
SQL_QueryError(hQuery, szError, 255);
log_error(AMX_ERR_GENERAL, "Blad w zapytaniu !");
log_error(AMX_ERR_GENERAL, "Kod bledu: %i", iError);
log_error(AMX_ERR_GENERAL, "Tresc bledu: %s", szError);
}
SQL_FreeHandle(hQuery); // Niech was reka boska broni, przed zapomnieniem o tym
}
else
{
log_error(AMX_ERR_GENERAL, "Brak polaczenia z baza danych !");
log_error(AMX_ERR_GENERAL, "Kod bledu: %i", iError);
log_error(AMX_ERR_GENERAL, "Tresc bledu: %s", szError);
}
SQL_FreeHandle(hConnection);
}
Napisane przez grankee
w 11.06.2010 15:21
public SaveData(id)
{
if(!zaladowalo[id]) return PLUGIN_HANDLED;// zmienna informujaca czy dany gracz byl zaladowany, ale jesli go nie zaladowalo to czemu go nie zapiszesz? Tworzenie konto robisz ręcznie? Jesli ma być automatycznie zapisywane dla nowych graczy to wywal tę linijkę
if(is_user_bot(id)) return PLUGIN_HANDLED;
if(player_xp[id]<=player_xp_old[id] || player_xp[id]==99999999999) return PLUGIN_HANDLED;//nie do konca rozumiem co to, jakby byl caly kod..
new nick[35]//32 wystarczy
new vaultkey[64],vaultdata[256]// po co Ci taka wielka tablica vaultdata? vaultkey w zasadzie powinien byc samym nickiem, po co ten dopisek -xpmod?
format(vaultkey,63,"%s-xpmod",nick)//czyli jak to wyzej poprawisz to ta linijka do usuniecia
format(vaultdata,255,"%i#%i#%i#", player_lvl[id], player_xp[id], player_dead[id])/* Po co wstawiasz #? Zrób to tak:
format(vaultdata,255,"%i %i %i", player_lvl[id], player_xp[id], player_dead[id])
skoro to liczby to nie zawierają spacji, więc później bez problemu podzielisz to parse'm*/
nvault_set(g_vault,vaultkey,vaultdata)
return PLUGIN_CONTINUE
}
public LoadData(id)
{
if(is_user_bot(id) || !is_user_connected(id)) return PLUGIN_HANDLED;
new nick[35] //wystarczy 32
get_user_name(id, nick, 34);//analogicznie 31
replace_all(nick, 34, "#", "");//po co to ?
new vaultkey[64],vaultdata[256]//po co Ci takie duze tablice? przeczytaj co pisalem wyzej
format(vaultkey,63,"%s-xpmod",nick)// jak wyżej pisałem, wywal "-xpmod", bo to zbędne
format(vaultdata,255,"%i#%i#%i#",player_lvl[id], player_xp[id], player_dead[id])//po co formatujesz string do którego za chwile i tak zapiszesz co innego?(zapiszesz tu wartosc z vaulta)
nvault_get(g_vault,vaultkey,vaultdata,255)//uzyj nvault_lookup, który od razu zwróci Ci, czy taki klucz został odnaleziony w bazie vault, po czym mozesz to zawarunkować i w razie niepowodzenia dasz return, żeby dalej nie wykonywać funkcji
replace_all(vaultdata, 255, "#", " ")//wywal to
new tmp[3][32];
parse(vaultdata, tmp[0], 31, tmp[1], 31, tmp[2], 31)//chyba takich długich wartości expa nie będzie, 31 znaków to grubo ponad bilion :D
player_lvl[id] = str_to_num(tmp[0]);
player_xp[id] = str_to_num(tmp[1]);
player_dead[id] = str_to_num(tmp[2]);
zaladowalo[id] = 1;//jesli to co wyzej ma byc automatycznie to ta zmienna jest zbedna
return PLUGIN_CONTINUE
}
Napisane przez Szyfrant
w 27.05.2010 16:17
'Szósteczka'
Wersja poradnika: v0.1
WERSJA W FORMACIE .PDF :
AMXBANS - Jak i Co 2 - AMXX - By Szyfrant.pdf 1,16 MB 2272 Ilość pobrań
Kolejna (już druga) odsłona poradnika "Jak i Co?" Nowy AMXBans ... Nowe funkcje... Nowy design... Ehh .
W miarę możliwości i czasu poradnik ten będzie aktualizowany.
Dobra bez gadania, lecimy z KONKRETAMI
Poradnik "Jak i Co? 'Szósteczka'" został stworzony dla AMXX.pl , KarczmaPodKepa.pl oraz Ciebie drogi użytkowniku.
By Szyfrant @ Al rajt rizerwt
Jak chcecie kopiować, proszę bardzo, ale nie zapomnijcie o stopce i autorze
Młody Admin: "KU***!!! Czitujesz !!! Masz PERMA CW**U!!
5 minut później
Młody Admin: KU*** !!! RASZUJESZ MASZ PERMA !!!
------------------------------------------------------
Poradnik "Jak i Co? 'Szósteczka'" został stworzony dla AMXX.pl , KarczmaPodKepa.pl oraz Ciebie drogi użytkowniku.
By Szyfrant @ Al rajt rizerwt
Jak chcecie kopiować, proszę bardzo, ale nie zapomnijcie o stopce i autorze
Napisane przez QTM. Peyote
w 27.02.2010 23:03
#include <amxmodx> #include <engine> new Float:przyciaganie[3] public plugin_init() { register_plugin("Przyciaganie", "0.0", "Peyote") register_clcmd("say /przyciaganie", "zaznacz") } public client_PreThink(id) { new Float:origin[3] new Float:velocity[3] entity_get_vector(id, EV_VEC_origin, origin) new Float:distance = get_distance_f(origin,przyciaganie) entity_get_vector(id, EV_VEC_velocity, velocity) if(distance < 900.0) { for(new i=0;i<=2;i++) { velocity[i] += (origin[i] > przyciaganie[i])?-7.0:7.0 } entity_set_vector(id, EV_VEC_velocity, velocity) } } public zaznacz(id) { entity_get_vector(id, EV_VEC_origin, przyciaganie) }
#include <amxmodx> #include <engine> new Float:przyciaganie[3] public plugin_init() { register_plugin("Przyciaganie", "0.0", "Peyote") register_clcmd("say /przyciaganie", "zaznacz") } public client_PreThink(id) { new Float:origin[3] new Float:velocity[3] entity_get_vector(id, EV_VEC_origin, origin) new Float:distance = get_distance_f(origin,przyciaganie) entity_get_vector(id, EV_VEC_velocity, velocity) for(new i=0;i<=2;i++) { velocity[i] += ((origin[i] > przyciaganie[i])?-1000.0:1000.0) / distance } entity_set_vector(id, EV_VEC_velocity, velocity) } public zaznacz(id) { entity_get_vector(id, EV_VEC_origin, przyciaganie) }
Napisane przez naven
w 16.01.2010 21:56
I znowu zaczyna się zrzynanie pomysłów. Napisz sobieczłowieku tego bunny hopa to ja mam ale potrzebuje, zeby plugin byl wlaczony, a jak gracz wpisze jakas komende np /bh lub /autobh plugin dla niego wylaczy sie a jak ponownie to wpisze to plugin sie wlacza, ale dzięki za chec pomocy, ale to nie to.