Skocz do zawartości

Ranking użytkowników


Popularna zawartość

Zawartość, która uzyskała najwyższe oceny od 19.04.2018 uwzględniając wszystkie miejsca

  1. 21 punktów
    Opis Jest to oczywiście znany Cod Mod napisany w 100% przeze mnie. Myślę, że jest on optymalniejszy niż pozostałe modyfikacje jakie można znaleźć. Rozwijanie paczki zostało zawieszone, gdyż serwer po prostu upadł, dlatego też kod nie zawsze jest najlepszy, jednak postanowiłem podzielić się z Wami tym, co udało mi się do tej pory napisać. Więcej niżej: - 20 klas zwykłych, 5 klas premium (kliknij, aby zobaczyć ich opis) - 56 perków (kliknij, aby zobaczyć ich opis) - klasy oraz perki poukładane są w menu wg. alfabetu, aby ułatwić poruszanie się w nim - system monet wstawiony w miejsce dolarów - umiejętności klas i perków napisane osobno, co pozwala na łatwą edycję oraz zmniejszenie ilości błędów wynikających z nakładających się umiejętności - standardowo użycie umiejętności klas pod E, umiejętności perków pod G - free level - prosty system cooldownów dla umiejętności wraz z efektem dźwiękowym przy ich odblokowaniu - system misji, 20 zadań podzielonych na 4 rozdziały - system klanów wraz z rangami, statystykami, wojnami oraz topką klanów - sklepik serwerowy z doświadczeniem, statystykami, extra itemami, trailami, sprayami - skrzynki wypadające z graczy - losowy kod do przepisania na czacie - daj/wymień perk wraz z blokadami - rynek z perkami - blokada perków dla danych klas - nocny exp - gotowy VIP (flaga custom 1) wraz z opisem - rozbudowane menu pomocy dla początkujących - nagroda dla TOP 3 graczy co mapę Wymagania - baza danych MySQL Komendy gracza sm_binds, sm_bindy - pomoc w bindach umiejętności sm_d, sm_drop - wyrzucenie perku sm_k, sm_klasa - wybór klasy sm_klasy - opis wszystkich klas sm_p, sm_perk - opis perku sm_perki - opis wszystkich perków sm_ranklvl - ranking poziomu sm_resetstat, sm_resetstats - reset statystyki sm_stats, sm_staty - menu rozdawania statystyk sm_top15lvl - top 15 poziomów sm_useitem, sm_useperk - użycie perku sm_useskill - użycie umiejętności klasy sm_sklep - otwiera sklepik sm_misje - otwiera menu misji sm_klan - otwiera menu klanów sm_daj - menu dawania perka sm_wymien - menu wymiany perka sm_bwymiane - blokada wymiany perkiem sm_rynek - rynek perków sm_vip - opis VIP'a sm_pomoc - menu pomocy Komendy admina cod_givecoins <nick> <amount> - dodaje monety graczowi cod_givelvl <nick> <amount> - dodaje poziom do aktualnej klasy gracza cod_givexp <nick> <amount> - dodaje doświadczenie do aktualnej klasy gracza cod_setcoins <nick> <amount> - ustawia monety graczowi cod_setlvl <nick> <amount> - ustawia poziom aktualnej klasy gracza cod_setperk <nick> <perk name> [perk value] - ustawia perk graczowi cod_setxp <nick> <amount> - ustawia doświadczenie aktualnej klasy gracza Galeria Download https://github.com/d0naciak/SM-Call-Of-Duty-Mod/releases Instrukcję instalacji można znaleźć w środku
  2. 15 punktów
    Nową wersję pluginu znajdziesz tutaj: O Pluginie: Wprowadza na serwer system rang. Wprowadza na serwer walutę jaką są złote naboje. Wszystko konfiguruje się poprzez 3 różne pliki. Komendy: !ap - Panel administracyjny !adminpanel - Panel administracyjny !reloadcfg - Przeładowanie configów !ranks - Główne menu rang !rank - Główne menu rang !ranga - Główne menu rang !rangi - Główne menu rang Instalacja: Standardowa Zrzuty ekranu: Podłączenie do bazy danych: Dodatkowe informacje: Plugin nie był testowany na żadnym serwerze z graczmi, więc każdy błąd proszę o zgłaszanie w tym temacie 😉 . Do pliku admin_overrides.cfg należy dodać: "sm_oVip" "flagi vipa" Download: yRanks_Go-Code.rar Pliki na Mega.nz
  3. 14 punktów
    Tak jakoś mi się nudziło, więc napisałem dr`a i stwierdziłem, że czemu by go nie udostępnić. Znajdują tu się 4 pluginy z czego 1 to cfg do bh a pozostałe 2 to są freeruny. Zależy komu jaki freerun się spodoba ? Główny plugin ADPET_Deathrun.sp Blokuje komendy samobójcze, blokuje zmianę teamu, wybiera losowego ttka ADEPT_Deathrun_Bhop.sp zwykły cfg na bh w pluginie ADEPT_Freerun.sp po wpisaniu /fre /free /freerun /fr włącz freeruna i blokuje użycie przycisku E w odległości 130 unitów od guzika ADEPT_Freerun_MenuVersion.sp Po wybraniu ttka wyskakuje mu menu z wybraniem Freerun bądź normalna runda do czasu wybrania nie może chodzić. /fr /free jeżeli menu zniknęło Plik konfiguracyjny wrzucamy do folderu configs ( addons/sourcemod/configs) Zabraniam kopiowania powyższych pluginów na inne fora niż go-code.pl bez mojej zgody. ADEPT_Deathrun_Bhop.sp Starsza wersja: ADEPT_Deathrun.sp ADEPT_Freerun.sp ADEPT_Freerun_MenuVersion.sp ADEPT_Freerun.txt deathrun.inc
  4. 14 punktów
    Co to są KeyValues? KeyValues to prosta struktura bazująca na organizacji "drzewkowej" która zawiera zagnieżdżone w sobie sekcje które to zawierają klucze i wartości. Dla wzrokowców i objaśnienia sprawy, najprostsza struktura KeyValues wygląda w ten sposób: "sekcja" { "klucz" "wartosc" } Jak napisałem na samym początku, sekcje mogą być w sobie zagnieżdżone, czyli do sekcji możemy dopisać kolejną sekcję, do niej kolejną, itd. Przykład: "sekcja1" { "sekcja2" { "klucz" "wartosc" } } Przy budowaniu struktury KeyValues warto zaznaczyć, że nazwy sekcji i kluczy nie mogą się powtarzać w obrębie danej sekcji. Trochę zagmatwane, ale mówiąc prościej tworząc sekcję "admin" nie możemy później wewnątrz tej sekcji stworzyć np. 2 razy sekcję "Kowalski", czy 2 razy klucza "Kowalski", nie powinniśmy też tworzyć klucza "Kowalski" a potem sekcji "Kowalski" czy też odwrotnie - myślę, że zrozumiałe. Dodatkowo do KeyValues możemy swobodnie dodawać komentarze. Komentarze pozwalają Nam dodawać tekst, który zostanie pominięty przy wczytywaniu KeyValues poprzez plugin. Dodajemy je poprzez użycie dwóch slashy (//) oraz wypisaniu za nimi jakiegoś tekstu. Komentarz jest jednolinijkowy, czyli od kolejnego wiersza będziemy mogli dalej budować naszą strukturę. "sekcja" { "klucz1" "wartosc1" //To jest komentarz. Tekst ten zostanie pominiety przy wczytywaniu KeyValues przez plugin SourceMod "klucz2" "wartosc2" } Z KeyValues mogłeś(aś) się już spotkać wcześniej, np. przy konfigurowaniu połączenia z bazą danych w pliku addons/sourcemod/configs/databases.cfg. Dla przypomnienia taki plik wygląda mniej więcej tak: "Databases" { "driver_default" "mysql" // When specifying "host", you may use an IP address, a hostname, or a socket file path "default" { "driver" "mysql" "host" "localhost" "database" "db" "user" "root" "pass" "" //"timeout" "0" //"port" "0" } "storage-local" { "driver" "sqlite" "database" "sourcemod-local" } } Jak pracować z KeyValues w pluginie SourceMod? Na początku przyjmijmy pewne założenia. Mianowicie napiszemy sobie plugin, który będzie tworzył główne menu serwera. Plugin ten będzie wywoływał komendę w konsoli gracza po naciśnięciu konkretnej opcji w menu. Nasz plik KeyValues będzie w addons/sourcemod/configs, nazwiemy go main_server_menu.ini. Jego struktura będzie wyglądała w ten sposób (wiem, można by to zrobić lepiej): "MainServerMenu" { "sm_vip" { "name" "Sprawdź opis VIP'a" "command" "sm_vip" } "res" { "name" "Menu RoundSoundów" "command" "res" } "rs" { "name" "Resetuj statystyki" "command" "rs" } } Na początku zadeklarujmy zmienną globalną która będzie uchwytem dla naszego menu głównego oraz od razu dodajmy RegConsoleCmd do OnPluginStart: Menu g_mainServerMenu; public void OnPluginStart() { RegConsoleCmd("sm_menu", cmd_MainServerMenu); } public Action cmd_MainServerMenu(int client, int args) { g_mainServerMenu.Display(client, MENU_TIME_FOREVER); return Plugin_Handled; } Następnie zbudujmy funkcję, która będzie odpowiedzialna za stworzenie menu na podstawie naszych KeyValues. Niech to będzie funkcja BuildMenu void BuildMenu() { // kodzik... } Na samym jej początku stworzymy nasze menu: //tworzymy menu g_mainServerMenu = new Menu(MainServerMenu_Handler); g_mainServerMenu.SetTitle("Główne menu serwera", MENU_ACTIONS_ALL); Następnie stworzymy uchwyt do KeyValues oraz wczytamy jego strukturę z naszego pliku konfiguracyjnego: //budujemy sciezke do pliku addons/sourcemod/configs/main_server_menu.ini char path[256]; BuildPath(Path_SM, path, sizeof(path), "configs/main_server_menu.ini"); //tworzymy KeyValues oraz importujemy strukture z pliku KeyValues keyValues = new KeyValues("MainServerMenu"); keyValues.ImportFromFile(path); Warto powiedzieć. że KeyValues wcale nie muszą wykorzystywać żadnego pliku. Można operować chociażby na strukturze podanej jako ciąg znaków wczytanej z zewnętrznego źródła (np. zawartość zewnętrznej strony WWW). Jednak najczęściej oczywiście struktura jest wczytywana z pliku, tak jak w przykładzie wyżej. Co jeszcze jest istotne, to przy deklaracji new KeyValues jako paramtetr podajemy nazwę pierwszej sekcji w naszym pliku, znaną również jako sekcja główna czy węzeł główny (więcej niżej). Mamy już wczytany pliczek do uchwytu, teraz trzeba by się odpowiednio po tej całej strukturze poruszać, a potem wczytać odpowiednie wartości do menu. Przy poruszaniu się po pliku należy wiedzieć, że: Sekcja to też w pewnym sensie klucz, o czym warto pamiętać przy poruszaniu się po strukturze. Sekcja to taka oddzielna nazwa dla kluczy, które posiadają w sobie jeszcze inne klucze. Poruszając się po pliku mamy do czynienia z pozycją. Pozycja określa nam na którym poziomie podsekcji jesteśmy (inaczej poziom zagnieżdżenia) oraz na którym kluczu w danej sekcji jesteśmy. Mówiąc o pozycji mamy zatem do czynienia z dwoma wartościami. Jak to wygląda praktyce? A no tak: "MainServerMenu" //sekcja główna (węzeł główny) { "sm_vip" //pierwszy klucz w pierwszym poziomie zagnieżdżenia { "name" "Sprawdź opis VIP'a" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "sm_vip" //drugi klucz w drugim poziomie zagnieżdżenia } "res" //drugi klucz w pierwszym poziomie zagnieżdżenia { "name" "Menu RoundSoundów" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "res" //drugi klucz w drugim poziomie zagnieżdżenia } "rs" //trzeci klucz w pierwszym poziomie zagnieżdżenia { "name" "Resetuj statystyki" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "rs" //drugi klucz w drugim poziomie zagnieżdżenia } } Podstawowe funkcje do poruszania się po KeyValues: GotoFirstSubKey(); // Przesuwa pozycje do pierwszej podsekcji (poziom zagniezdzenia nizej) // Zwraca false w przypadku nieznalezienia podsekcji GotoNextKey(); // Przesuwa pozycje do kolejnego klucza/sekcji w danej sekcji // Zwraca false w przypadku nieznalezienia kolejnego klucza GoBack(); // Przesuwa pozycje o poziom zagniezdzenia wyzej. // Zwraca false, kiedy nie da sie juz wyzej przesunac (np. jestesmy w wezle glownym) Rewind(); // Ustawia pozycje wezla glownego. Podobny cel mozna osiagnac poprzez // uzywanie GoBack dopoki nie zwroci false, jednak ta funkcja jest optymalniejsza. JumpToKey(const char[] key, bool create=false); // Przenosi nas do klucza w danej sekcji o podanej nazwie w parametrze "key" // W przypadku create=true oraz jezeli dany klucz nie zostanie znaleziony, funkcja ten klucz stworzy. // Zwraca true w przypadku znalezienia klucza, false jezeli klucza nie znaleziono Pominąłem parametry które mogły by być trudne do zrozumienia a mają one swoje domyślne wartości. Dla ciekawskich wszystkie i w pełni opisane funkcje można znaleźć w dokumentacji. Okejj, więc co dalej po otwarciu pliku? Musimy przejść o jedno zagnieżdżenie niżej, a więc kolejny skrawek kodu będzie wyglądać tak: //nie znaleziono zadnej podsekcji? Plik jest nieprawidłowy, koniec :/ if (!keyValues.GotoFirstSubKey()) { PrintToServer("*** I had a problem while building a menu :/ Check main_server_menu.ini"); delete keyValues; return; } Po prawidłowym przejściu niżej, Nasza pozycja wygląda teraz tak: "MainServerMenu" //przed GotoFirstSubKey bylismy tutaj { "sm_vip" //po GotoFirstSubKey jestesmy tutaj { "name" "Sprawdź opis VIP'a" "command" "sm_vip" } "sm_res" { "name" "Menu RoundSoundów" "command" "sm_res" } "sm_rs" { "name" "Resetuj statystyki" "command" "sm_rs" } } Co teraz? Musimy wczytać dane z danej sekcji, dodać opcję do menu i przejść do kolejnego klucza (w Naszym wypadku kolejnej sekcji). Skorzystamy z pętli do while: char command[64], itemName[64]; do { //wczytujemy dane z danej sekcji keyValues.GetString("command", command, sizeof(command)); keyValues.GetString("name", itemName, sizeof(itemName)); //dodajemy opcje do menu g_mainServerMenu.AddItem(command, itemName); } while (keyValues.GotoNextKey()); //przechodzimy do kolejnej sekcji, dopoki te sekcje nie skoncza sie I to by było na tyle z wczytywanie, nasze menu jest już zbudowane ^^ Nie zapomnijmy o zamknięciu uchwytu no iii dajmy odpowiednie info serwerowi: //info dla serwera oraz oproznianie zmiennej kv delete keyValues; PrintToServer("*** Main server menu has been built"); Funkcję BuildMenu możemy zamknąć, a pod nią dodajmy funkcję Handler do naszego menu. Będziemy tam w momencie wybrania opcji wpisywać do konsoli gracza daną komendę zapisaną pod "info" tej właśnie opcji: //obsluga menu public int MainServerMenu_Handler(Menu menu, MenuAction action, int param1, int param2) { switch (action) { case MenuAction_Select: { int client = param1; //wczytujemy komende z pola "info" z danej opcji w menu oraz wywolujemy komende w konsoli char info[64]; menu.GetItem(param2, info, sizeof(info)); ClientCommand(client, info); } } } W OnPluginStart należy jeszcze wywołać funkcję od budowania menu: public void OnPluginStart() { RegConsoleCmd("sm_menu", cmd_MainServerMenu); BuildMenu(); } Nasz plugin jest gotowy 😄 Kod *.sp oraz plik *.ini podaję w załącznikach -> main_server_menu.ini server_menu.sp Co jeszcze warto wiedzieć? Do wczytywania wartości z klucza mamy kilka funkcji, które odpowiadają danemu typowi wartości. Możemy np. wartość wczytać od razu w type int, słuzy do tego funkcja GetNum która zwraca wartość klucza. Jest wiele innych ciekawych funkcji jak GetFloat, GetColor, itd. - więcej w dokumentacji Strukturę można zmieniać, a zmiany potem zapisać poprzez funkcję ExportToFile. Są odpowiednie funkcje do usuwania kluczy, ustawiania ich wartości, itd. Jak wyżej - więcej info na ten temat można znaleźć w dokumentacji KeyValues nie powinny być zbyt wielkie. Niedopuszczalne jest skorzystanie z KeyValues w celu zapisywania ilości zabójstw graczy. Przy tak dużej ilości danych zdecydowanie lepszym rozwiązaniem jest baza danych. Wyjątkiem może być plik w którym tych graczy jest mniej, np. plik z graczami którzy dostają specjalny bonus. Plików KeyValues staraj się nie otwierać zbyt często, najlepiej zrobić to maks. raz na mapę bądź też poprzez komendę do której dostęp ma tylko opiekun serwera. Zadanie domowe! Usuń klucz "command" i zamiast wczytywania go wykorzystaj funkcję GetSectionName dzięki której wczytasz nazwę sekcji, a co za tym idzie od teraz komendę będziesz podawać właśnie w nazwie sekcji. Rozwiązaniem możesz się pochwalić w tym temacie 😄
  5. 13 punktów
    Witajcie, przedstawiam wam trochu odświeżonego starszego mojego vipa który posiada kilka nowych przydatnych funkcji. Stary plugin: Kliknij tutaj! Plugin posiada kilka fixów i poprawek w kodzie. Lista Funkcji Dodatkowe HP na start rundy. Dodatkowe HP za zabójstwo. Dodatkowe HP za headshota. Zwiększona prędkość ruchu. Można zmienić grawitacje. Darmowa kamizelka + hełm. Darmowe granaty na start rundy(Wszystkie typy) Dodatkowe pieniądze na start rundy. Dodatkowe pieniądze za zabójstwo/headshot. Dodatkowe pieniądze za podłożenie/rozbrojenie bomby. Dodatkowe pieniądze za wygranie rundy. Podwójny skok. Tag [VIP] w tabeli. Menu broni od danej rundy. Darmowy VIP od x do x godziny. Lista vipów online pod komendą !vipy / !vips Przywitanie oraz pożegnanie vipa gdy wchodzi/wychodzi na serwer. Pisanie w HUD raz na 120 sekund pod komendą: !vipsay Wiadomość Pieniądze dla vipa za zabójstwo z noża. [Nowość] Nieskończoność amunicji dla VIPA domyślnie wyłączone. Instalacja Plik H2K_Vip.smx dodaj do /csgo/addons/sourcemod/plugins. Plik H2K_Vip.sp dodaj do /csgo/addons/sourcemod/scripting (Opcjonalne). Plik h2k-vip.phrases.txt dodaj do /csgo/addons/sourcemod/translations (WYMAGANE) Wszystkie pliki potrzebne będą w załączniku. UWAGA: By ustawić vipa na daną flagę musimy: W cvarach macie domyślnie flagę "o" Zmienić sobie tam możecie wszystko Wymagania: Sourcemod 1.10.0+ ( Jak chcesz by ci działało na SM 1.9 proszę o skompilowanie pluginu na tej właśnie wersji.) Konfiguracja Plik konfiguracyjny utworzy się po załadowaniu pluginu na serwer. Przyszłość! Plugin będzie stale rozwijany z czasem, dodanie nowych nowości, możliwe że dodanie systemu MySQL oraz przepiszę go kiedyś na KeyValues z niesamowitymi opcjami Jednak aktualnie mnie czas ogranicza. Miłego korzystania ❤️. Wersja 1.9 aktualna. STARE WERSJE: H2K_Vip.sp H2K_Vip.smx 1.4 H2K_Vip.sp H2K_Vip.smx 1.5 NOWE WERSJE: 12/12/2019 1.9 H2K_Vip.sp H2K_Vip.smx h2k-vip.phrases.txt H2K_Vip.smx H2K_Vip.sp
  6. 13 punktów
    Siemanko! Przez ostatni tydzień pracowałem z moimi kolegami nad stroną, która umożliwia szybkie tworzenie paczek serwerowych. Strona jest praktycznie ukończona, a rezultat możecie obejrzeć tutaj: >LINK< Od teraz każdy będzie mógł stworzyć spersonalizowaną paczkę samodzielnie. Wystarczy kilka kliknięć. Działanie jest bardzo proste - zaznacz z listy pluginy, które chciałbyś mieć na serwerze i naciśnij "Wygeneruj" - po chwili paczka będzie gotowa do pobrania. Link, który pojawi się na stronie można użyć do podzielenia się wybranymi przez siebie pluginami z innymi. Obecnie na liście znajduje się ponad 20 modyfikacji, jednak chciałbym, aby było ich dużo więcej, dlatego szukam osób, które chciałyby pomóc w poszerzaniu bazy pluginów. Tworzenie paczki na stronę nie jest skomplikowane, jednak wymaga trzymania się pewnych reguł w celu zapewnienia kompatybilności. Każdy, kto stworzy przynajmniej trzy paczki zostanie umieszczony na stronie pod adresem http://138.68.97.196/authors Informacje o tym jak tworzyć paczki umieszczę w osobnym poście Dajcie koniecznie znać co sądzicie o stronce, a wszystkie opinie i propozycje dawajcie w komentarzach poniżej Pozdrawiam 🙂
  7. 13 punktów
    Trochę się rozkręciłęm 🙂. Stworzyłem plugin, którego idea jest bardzo prosta - podobnie jak przy użyciu [email protected], możemy składać raporty u admina przy użyciu przedrostka '$' Zasadę działania obrazuje poniższy film: Plugin napisałem z multilangiem, bo będę wrzucał go na alliedy. Dostępny w wersji anglo- i polskojęzycznej. Bierzcie z tego wszyscy! ConVary cvCapacity = CreateConVar("rg_capacity", "25", "Capacity of available reports"); cvReportDelay = CreateConVar("rg_report_delay", "180", "The interval in which player can send reports (in seconds)"); Download ReportGO.zip
  8. 12 punktów
    Cześć, Tworzę ten poradnik, z tego powodu, że na internecie ciężko znaleźć cokolwiek o overlay'ach, nie mówiąc już o poradniku jak wszystko stworzyć i skonfigurować, a dla mnie było to piekielnie ciężkie i męczyłem się z tym naprawdę długo. Skoro już ogarnąłem jak to wszystko działa dziś pokażę Wam od zera jak zrobić i skonfigurować overlay'e na serwer. Napiszemy bardzo prosty plugin, który po zabójstwie headshot'em będzie wyświetlał overlay'a "Headshot" przez 2 sekundy, a także w tym momencie będzie efekt dźwiękowy "Headshot". 1. PRZYGOTOWANIE WŁASNEGO OVERLAY'A 1. Zaczniemy od przygotowania overlay'a takiego, jakiego chcemy. Do tego celu będziemy potrzebować jakiś program do obróbki zdjęć: najlepiej Gimp. Moim overlay'em będzie napis, więc zaopatrzam się w ładną czcionkę [https://fonts.google.com/] 2. Tworzę nowy plik w Gimpie, według mnie najlepsze wymiary są takie jak na zdjęciu, bo wszystko jest wyraźne (im większa rozdzielczość tym więcej plik końcowy będzie ważył) 3. Jeśli naszym overlay'em jest napis - piszemy coś na pustej stronie, jeśli obrazek - wklejamy go na nowo utworzony plik [Otwórz -> wybieramy obrazek] 4. Usuwamy warstwę "Tło" 1. PPM na "tło" 2. Usuń warstwę 5. Powinniśmy otrzymać taki efekt: 6. [BARDZO WAŻNE] Plik eksportujemy jako plik *.tga 7. Graficznie nasz overlay jest zrobiony, pozostało umożliwić serwerowi odczyt i wyświetlenie tego pliku. Do tego potrzebny jest nam edytor tekstur przeznaczony m.in. do CS:GO - jest to VTFEdit (Valve Texture File Editor). Gdy już pobierzemy oprogramowanie, otwieramy nasz plik *.tga za pomocą VTFEdit. Możemy to zrobić na 2 sposoby: • Otwórz VTFEdit -> CTRL + I -> Wybierz plik do zaimportowania • Kliknij PPM na plik *.tga, który przedtem utworzyłeś -> Otwórz za pomocą -> VTFEdit Wyświetli się kontrolka odnośnie ustawień. Można otworzyć na fabrycznych ustawieniach, natomiast ja używam tych Ważne jest też to, żeby nie panikować, gdy w pliku *.vtf będzie wszystko czarne (w miejscu zdjęcia). Tło jest czarne więc jeśli napis jest czarny to zlewają się ze sobą, bo edytor ten w czasie gdy nie ma tła wstawia czarne pole. Finalnie pojawi się czarny napis, a nie czarny kwadrat 8. Zapisujemy plik jako *.vtf 9. Tworzymy plik *.vmt i zapisujemy go najlepiej w tym samym miejscu co *.vtf [BARDZO WAŻNE] ustawienia pliku *.vmt MUSZĄ być takie same jak na screenie drugim 10. Tworzymy folder o nazwie "overlays" (można dać inną nazwę, ale ta jest najłatwiejsza i najłatwiej się odnaleźć) -> Oba pliki (*.vtf i *.vmt) wrzucamy do tego folderu -> Folder razem z plikami w środku przerzucamy do "materials" w plikach serwerowych -> PPM na plik *.vmt -> otwieramy za pomocą notatnika, lub innego edytora tekstowego -> wpisujemy odpowiednią ścieżkę: 11. Zapisujemy zmiany. Zrobiliśmy właśnie własnego overlay'a i poprawnie go skonfigurowaliśmy. Najtrudniejsze za nami 2. NAPISANIE PLUGINU Napiszemy teraz plugin, który opisałem na samym początku. Niezbędna do tego będzie odpowiednia biblioteka: overlays.inc, którą pobierzemy stąd: https://github.com/shanapu/overlays.inc Najpierw jednak przygotuję odpowiedni efekt dźwiękowy, który będzie towarzyszył mojemu overlay'owi. Wpisuję "Headshot Sound Effect" w Google i ściągam odpowiedni dźwięk (najlepiej w *.mp3); nazywam go "Headshot" i wrzucam do plików serwerowych: /csgo/sound/ [można utworzyć dodatkowy folder, żeby nie zrobił się bałagan w folderze sounds] A więc możemy przejść do napisania pluginu: #include <sourcemod> #include <overlays> #include <sdktools> #define HEADSHOTPATH "overlays/Headshot" //bez rozszerzeń #define HEADSHOTSOUNDPATH "*/ServerSounds/Headshot.mp3" //ścieżka do dźwięku z //poziomu folderu "sound" #define HEADSHOTSOUNDPATH2 "sound/ServerSounds/Headshot.mp3" //ścieżka do dźwięku z //poziomu folderu "materials" public void OnPluginStart() { HookEvent("player_death", OnHeadshot, EventHookMode_Post); } public void OnMapStart() { PrecacheSound(HEADSHOTSOUNDPATH, true); //te 3 linijki to pobieranie AddFileToDownloadsTable(HEADSHOTSOUNDPATH2); //materiałów z plików PrecacheDecalAnyDownload(HEADSHOTPATH); //serwera } public Action OnHeadshot(Event e, const char[] n, bool b) { int attacker = GetClientOfUserId(e.GetInt("attacker")); bool hs = GetEventBool(e, "headshot"); if(hs) { EmitSoundToClient(attacker, HEADSHOTSOUNDPATH); ShowOverlay(attacker, HEADSHOTPATH, 2.0); } } I OTO KONIEC!!! Tak to się prezentuje: Mam nadzieję, że pomogłem komuś z Was kto miał taki sam problem jak ja. Zajęło mi to naprawdę dużo czasu i włożyłem w to serce. Liczę na dobre opinie. W razie pytań zapraszam do komentarzy.
  9. 12 punktów
    Opis: Plugin dodaje niestandardowy status, który sami ustawicie. KOD: Wymagania: PTaH - Najnowsza wersja( https://ptah.zizt.ru/ ). INSTALACJA Kompilujemy plik ADEPT_Status.sp następnie wrzucamy go do folderu /addons/sourcemod/plugins Następnie wrzucamy plik konfiguracyjny ADEPT_Status.txt do folderu /addons/sourcemod/configs ADEPT_Status.sp ADEPT_Status.txt ADEPT_Status.inc
  10. 12 punktów
    Opis: Dodaje komendę !models / !modele po wpisaniu pojawia się menu z wyborem "grupy" z której ma wybrać dany model. Grupy dodaje się w pliku konfiguracyjnym oraz ustawia na flagę (można zostawić puste miejsce wtedy będzie dla każdego). Plugin posiada swój downloader. Plugin jest alternatywą tego pluginu -> https://forums.alliedmods.net/showthread.php?t=87597 KOD: Przykładowy plik konfiguracyjny: Przykładowy plik downloadera: Jeżeli masz jakąś propozycję co można dodać pisz śmiało 😄 Natomiast jeżeli widzisz, że kod można napisać lepiej napisz mi co konkretnie i jak mogę to napisać lepiej 😉 Z góry dziękuję. Starsze wersje: Zabraniam kopiowania powyższego pluginu na inne fora niż go-code.pl bez mojej zgody. ADEPT_Models.sp ADEPT_Models.txt ADEPT_Models_Download.txt
  11. 12 punktów
    W tym poradniku omówię tzw. ciasteczka, które zapisują nam np. Wybrany TAG w tabeli. Dla przykładu napiszemy plugin w którym będziemy ustawiać swój TAG w tabeli. Na początku musimy dodać odpowiednie include'y oraz zdefiniować nasz Handle(uchwyt) do którego będziemy się odwoływać. *wymagane* #include <cstrike> #include <clientprefs> Handle g_hClientTag; Teraz musimy "zarejestrować" nasze ciasteczko w OnPluginStart używając funkcji RegClientCookie, który jako argumenty przyjmuje: - Nazwa naszego ciasteczka. - Opis naszego ciasteczka. - Dostęp naszego ciasteczka. CookieAccess_Public Jest ciasteczkiem publicznym i każdy gracz może je zmienić za pomocą komeny sm_cookies <nazwa ciasteczka> < wartość> CookieAccess_Protected Jest ciasteczkiem możliwym tylko do odczytania dla gracza. Gracz nie może go zmienić przy użyciu komendy. CookieAccess_Private Jest ciasteczkiem ukrytym. Gracz nie może go ani odczytać ani zmienić (nasz plugin oczywiście może :D). g_hClientTAG = RegClientCookie("sm_selected_tag", "Zapisuje wybrany przez nas tag", CookieAccess_Protected); W momencie kiedy zreloadujemy plugin, a nie mamy dodanego ponownego wczytania ciasteczek gracz, który wybrał dany TAG musi wybrać go ponownie. Dlatego zrobimy opcję gdzie w OnPluginStart załadujemy ciasteczka ponownie graczom, którzy są w grze oraz nie są botami for (int i = 1; i <= MaxClients; i++) { if (IsClientInGame(i) && !IsFakeClient(i)) OnClientCookiesCached(i); } *wymagane* *nie wymagane* Ostatnią rzeczą, którą zrobimy w OnPluginStart to SetCookieMenuItem, ustawienie tego dodaje nam pod komendę !settings . Przyjmuje on 3 argumenty: - Callback do naszego handlera(uchwytu) - Info - Tekst pokazany w menu. SetCookieMenuItem(TagChangeHandler, 0, "[TAG] Wybierz swój TAG w tabeli"); Po ustawieniu nazwy naszego callbacka oraz nazwy menu możemy robić callbacka Tego typu callback przyjmuje 5 argumentów: - Client ( slot gracza ) - CookieMenuAction czyli po prostu akcja jaka zostanie podjęta. CookieMenuAction_SelectOption po wybraniu opcji CookieMenuAction_DisplayOption po wyświetleniu opcji - Info - Buffer - maxlength public void TagChangeHandler(int client, CookieMenuAction action, any info, const char[] buffer, int maxlength) { if (action == CookieMenuAction_SelectOption)ShowTagMenu(client); } Od teraz po wpisaniu !settings pojawi nam się również opcja zmienienia ciastekcza i w moim przypadku TAG'u. *nie wymagane* *wymagane* Teraz musimy zrobić tak aby przy każdym połączeniu gracza ustawiać mu ciasteczko, które miał wybrane wcześniej czyli musimy użyć forwarda OnClientCookiesCached, przyjmuje on tylko 1 argument czyli slot gracza ( int client ). To teraz musimy pobrać ciasteczko, które miał ustawione gracz wcześniej. Użyjemy do tego funkcji GetClientCookie przyjmuje ona 4 argumenty: - Client ( slot gracza ) - Nasz handle(uchwyt) do którego "zapisywana" jest o tym informacja. - buffer do którego zapiszemy to co nam zwróci funkcja - maxlength ( maksymalna wielkość naszego buffer'a ) Po pobraniu ciasteczka ustawiamy graczowi na tą wartość. public void OnClientCookiesCached(int client) { char value[16]; GetClientCookie(client, g_hClientTag, value, sizeof(value)); g_iClientTag[client] = StringToInt(value); } Mamy już nasze ciasteczko wiemy jak je "zarejestrować", pobrać i ustawić teraz czas na zapisywanie. Aby zapisać nasze ciasteczko użyjemy funkcji SetClientCookie, przyjmuje ona 3 argumenty: - Client ( slot gracza ) - Nasz handle(uchwyt) - Wartość Wartość ta nie jest INT'em tylko stringiem, dlatego zanim przekażemy INT'a musimy zamienić go na string używając funkcji IntToString, która przyjmuje 3 argument: - Liczbę, którą chcemy dać do stringa - Buffer w którym będzie się znajdować nasza liczba - Wielkość naszego buffer'u char value[16]; IntToString(2,value,sizeof(value)); W moim przypadku nie będzie to nie potrzebne, ponieważ pobieram wartość z menu gdzie jest już jako string. SetClientCookie(client, g_hClientTag, info); *wymagane* Plugin, który powstał przy poradniku:
  12. 11 punktów
    Z dniem dzisiejszym (anno domini 16.10.2019r.) obywatel @Yamakashi zostaje Supportem! Gratulejszyn i powodzenia w dalszym rozwoju 😄
  13. 11 punktów
    Witam wszystkich bardzo serdecznie! Razem z @Bioły otwieramy pierwszą edycję MyGO MMA! W pierwszej edycji MyGO MMA odbędzie się 7 walk. Codziennie przez 7 dni będzie ujawniana kolejna walka. Walki odbędą się w czasie nieokreślonym, ale się odbędą! Pierwszą walkę, którą wam ujawnimy jest... KARTA WALK
  14. 11 punktów
    O pluginie Jeżeli gracz jest w danej grupie Steam może on aktywować darmowego vipa na daną ilość czasu, wszystko konfigurujemy poprzez cvary. Cvary iIDGrupy = SteamIDGroup (Możesz go znaleźć tutaj) LinkDoGrupy = Link do twojej grupy steam CzasVipa = Czas vipa, podany w minutach np. 120,60,240 Wymagania Rozszerzenie SteamWorks - KLIKNIJ BY POBRAĆ Dodatkowe informacje Plugin generuje plik DarmowyVip.txt w folderze csgo, informując kto użył DarmowegoVipa (data wraz z dokładnym czasem aktywacji, nick, SteamID, ilość minut) Również przepraszam za ten mierny kod, pisałem ten plugin rok temu i kompletnie nie miałem potrzeby go zmieniać, za niedługo mam zamiar wrzucić wersję pod MYSQL oraz rozbudowana ilość cvarów, aktualnie czas nie pozwala mi na żadną z tych rzeczy Kod źródłowy H2K_DarmowyVIP.sp H2K_DarmowyVIP.smx
  15. 10 punktów
    Witajcie, plugin który prezentuję dzisiaj był prywatny przez długi okres czasu, jednak przez nieposzanowanie projektu przez osoby trzecie i ludzi którzy odsprzedawali moją prace lub udostępniali dalej, po necie lata 1000 wersji tego pluginu, który jak mówiłem powinien pozostać prywatny. W tych czasach jest bardzo mało ludzi którzy potrafią być uczciwi. Tym co zakupili oficjalną wersję ode mnie i nie udostępnili dalej, z góry dziękuje, takich ludzi doceniam. Szkoda że druga połowa postąpiła inaczej. Pluginu nie wspieram od dobrych 5 miesięcy dlatego oddaje go wam, community, jeżeli będziecie chcieli go wspierać osobiście (ulepszyć) bardzo by mi było miło. Krótki opis pluginu. Na serwerze otrzymujemy rangi od silvera 1 do global elite zależnie od ilości zdobytych punktów. Również możemy sobie wybrać odznakę (coin), która widnieje w tabeli tak samo, jak rangi. Plugin posiada zapis MYSQL. Konfiguracja pluginu (cvary). Zalety pluginu Plugin jest bieżąco aktualizowany (Nie aktualne) Plugin nie laguje serwera (nie skacze VAR). Plugin jest bardzo rozbudowany w jak najmniejszą ilość kodu, trzeba dbać o estetykę ?, cały czas kod jest ulepszany by był aktualny z najnowszymi "standardami SM”, dokładniej chodzi o to, że używam najnowszych funkcji zamiast tych starych np. ze starej składni. Plugin jest napisany w taki sposób by kod w pluginie był zrozumiały dla każdego, najprościej jak się da, oraz najwydajniej. Lista funkcji Mnóstwo eventów, za które dostajemy punkty między innymi. Zabójstwo Headshot Bomba podłożona/Rozbrojona Wygrana Runda/Przegrana runda MVP Player Zabójstwo z noża Możliwość straty punktów, czyli jak zginiemy to odejmuje nam punkty, jak zabijemy dodaje, tak samo z większością eventów. Możliwość wyłączenia opcji tracenia punktów. Możliwość włączenia wymogów np. Minimalna ilość graczy by punktacja zaczęła działać. Zaawansowany system VIP, za eventy dostaje więcej punktów oraz mniej ich traci, wszystkie odznaki od razu odblokowane. Możliwość ustawienia poprzez cvar czy odznaki mają działać na zasadzie wymaganej rangi do odblokowania poziomu odznak, czy dostępne dla wszystkich graczy każda odznaka. Ranga oraz odznaka ukazują się w tabeli po TAB. Zaawansowany panel administratora flaga "z", dzięki czemu możemy zarządzać graczami, zresetować wszystkim rangi i punkty, taka czystka jakby to powiedzieć, i tak dalej i tak dalej. Flagę vipa zmieniamy sobie w cvarze, domyślnie jest to flaga "o" czyli ADMFLAG_CUSTOM1. Overlaye przy wbiciu danej rangi I wiele więcej. Dodatki: Moduł Hazard - Tak zwana ruletka, możesz wygrać albo przegrać grając o swoje punkty rankingowe. Moduł Sklep Zephyrus - Integracja punktów ze sklepem by Zephyrus Moduł Sklep by d0naciak - Integracja punktów ze sklepem SMS by @d0naciak KOMENDY (WYMAGANA FLAGA ADMFLAG_ROOT) !ranksreload - Przeładowuje rangi na serwerze !addpoints / !dodajpkt <pkt> - Jak sama nazwa wskazuje, dajesz punkty graczowi !removepoints / !usunpkt <pkt> - To samo co @up, odejmuejsz mu punkty. !setpoints / !ustawpkt <pkt> - :). (KOMENDY DLA GRACZY) !lvl / !ranga / !mm - Masz tam w sumie wszystko !hud - Włącz/Wyłącz HUD. !hudmode - Jak ma wyświetlany być hud. !overlaymode - Włącznik / Wyłącznik overlay. !coin / !coins / !pin / !pins - Odznaki MODUŁ HAZARD !hazard <punkty> !gamble <punkty> Instalacja Pobierz paczkę z załącznika i wgraj wszystkie potrzebne pliki na serwer (możesz pominąć folder scripting). Podepnij bazę danych: h2k_ranks do pliku databases.cfg (addons/sourcemod/configs). "h2k_rangi" { "driver" "default" "host" "host bazy" "database" "baza danych" "user" "użytkownik" "pass" "hasło" } Zrestartuj serwer. Skonfiguruj plugin pod swoje potrzeby, plik z konfiguracją wygeneruje się w csgo/cfg/sourcemod nazwa pliku: Wszystko gotowe :). Kilka screenshotów z gry Overlaye przy wbiciu rangi (lub spadku) oraz dźwięk awansu. API W moim pluginie nie znajdziesz żadnego ukrytego kodu, nie ma w nim ukrytej żadnej licencji ani zdalnego dostępu. Otrzymujesz plik źródłowy (.sp) do wszystkich plików. Plugin można w łatwy sposób połączyć z innymi pluginami wykorzystując bibiotekę .inc (Nativy) Obecna wersja pluginu: 4.0.7 POBIERZ [4.0.7] Rank system - Final - Finałów.7z ZAKAZ UDOSTĘPNIANIA NA INNE FORA NIŻ GO-CODE.PL
  16. 10 punktów
    Trochę mi się nudziło, więc postanowiłem, że stworzę lekką wersję GunXpModa. Póki co mój czas włożony w ten plugin to jakieś 3 godziny, więc istnieje szansa, że coś może nie działać jak należy, ale nie mam jak sprawdzić czy na serwerze z graczami wszystko działa, bo...nie mam takiego serwera 😉. Nie jest to finalna wersja, bo chciałbym dowiedzieć się co przydało by się tutaj dodać. Propozycje poniżej 🙂 Opis Znana m.in. z serwerów BaseBuilder modyfikacja. Idea - odblokowujesz kolejne bronie zdobywając XP...w sumie nie ma tutaj nic więcej. Zapis: SQLite Ilość potrzebnego expa na kolejne poziomy jest wyrażona wzorem: Wzór: Exp(x) = (x**3 * (100-x))/20, gdzie x to level A tutaj wykres obrazujący ilość expa wymaganą na poszczególne poziomy: Komendy !gxp - otwiera menu moda Cvary cvWhenGiveWeapon = CreateConVar("gxp_when_give_weapon", "0", "Kiedy dawać broń? 0 - wraz z wyborem broni w menu, 1 - po odrodzeniu 2 - w fazie przygotowania (BaseBuilder)"); cvMinimalPlayers = CreateConVar("gxp_minimal_players", "2", "Od ilu graczy ma naliczać exp?"); cvKillExp = CreateConVar("gxp_kill_exp", "3", "Ilość punktów za zabójstwo"); cvHsExp = CreateConVar("gxp_hs_exp", "5", "Ilość punktów za zabójstwo z HS"); cvDeathExp = CreateConVar("gxp_death_exp", "1", "Ilość punktów za śmierć"); cvAssistExp = CreateConVar("gxp_assist_exp", "1", "Ilość punktów za asystę"); Kod
  17. 10 punktów
    Hi ? Oto mały kodzik do tworzenia kolorowych latarek float playerPos[3]; float playerAng[3]; GetEntPropVector(client, Prop_Send, "m_vecOrigin", playerPos); GetEntPropVector(client, Prop_Send, "m_angRotation", playerAng); entlight = CreateEntityByName("light_dynamic"); if (entlight != -1) { DispatchKeyValue(entlight, "_light", "0 132 255"); DispatchKeyValue(entlight, "brightness", "5"); DispatchKeyValueFloat(entlight, "distance", 2400.0); DispatchKeyValueFloat(entlight, "spotlight_radius", 200.0); DispatchKeyValueFloat(entlight, "_inner_cone", 0.0); DispatchKeyValueFloat(entlight, "_cone", 360.0); DispatchSpawn(entlight); TeleportEntity(entlight , playerPos, playerAng,NULL_VECTOR); SetVariantString("!activator"); AcceptEntityInput(entlight, "SetParent", GetEntPropEnt(client,Prop_Send,"m_hViewModel"), entlight, 0); } Inputs: https://developer.valvesoftware.com/wiki/Light_dynamic wyłączanie/włączanie światła: AcceptEntityInput(entlight, "Toggle"); udostępniacie takie fajne rzeczy to też chciałem coś udostępnić xD z mojej krainy zabawek @edit Limit dynamicznych świateł na mapie to 17
  18. 9 punktów
    W tym poradniku chciałbym możliwie jak najkrócej przedstawić sposób, w jaki można tworzyć menu, a także pokazać mały trik jak przekazywać przez nie informacje. Wykonuję go w oparciu o moje doświadczenie, a więc nie ma w nim zawartych Paneli, czy obsługi blokowania poszczególnych pozycji. Całość przedstawiam w oparciu o nową składnię (1.7+). Menu w SourcePawnie ma swój własny typ danych (methodmapę) - i nazywa się on Menu. Na samym początku musimy utworzyć sobie do niego uchwyt: Menu menu = new Menu(Nazwa_Naszego_Handlera); Od teraz, kiedy będziemy chcieli budować nasze menu, posłużymy się utworzoną zmienną menu. Jak widzimy, w kodzie powyżej widnieje Nazwa_Naszego_Handlera. Otóż kiedy player widzi menu w grze (np. głosowanie na następną mapę), po zapoznaniu się z nim wybiera interesującą go opcję (może wybrać dusta, assaulta...może też zwyczajnie menu zignorować i nie nacisnąć nic). Program musi taką informację odpowiednio przetworzyć i dowiedzieć się, co tak właściwie nacisnął gracz. Cały ten proces odbywa się w tak zwanym Handlerze (pojęcie to będzie jeszcze wykorzystywane w miejscach, gdzie odpowiedź nie pojawia się natychmiastowo, a jest przetwarzana asynchronicznie, jak to ma miejsce w T_SQL). Kolejną rzeczą jest oczywiście nadanie tytułu - gracz musi wiedzieć, dlaczego dane menu widzi :). Służy do tego polecenie: menu.SetTitle("Tutaj wpisujemy nasz tytuł"); Gdybyśmy chcieli sformatować nagłówek (np. pokazać w nim imię danego gracza), musimy zastosować sformatowanego stringa, gdyż SetTitle nie obsługuje tej funkcji: char menuTitleBuffer[128]; Format(menuTitleBuffer, sizeof(menuTitleBuffer), "Witaj %N! Wybierz opcję:", client); menu.SetTitle(menuTitleBuffer); Przy okazji, jeżeli chcemy pobrać imię gracza, nie ma potrzeby korzystania z GetClientName - robi to za nas reguła formatująca %N - w jej miejscu pojawi się nick gracza ? Aby dodać do menu pozycję, korzystamy z polecenia AddItem: menu.AddIitem("id pozycji", "To, co widzi gracz"); Pierwszy parametr to ciąg znaków, służący do identyfikacji itemu Drugi parametr to widoczna dla gracza pozycja w menu. Identyfikator nie musi być unikalny i można wykorzystać go na masę sposobów. Przykład jego zastosowania pokażę na końcu poradnika. Możemy również określić, czy menu będzie posiadało możliwość wyjścia z niego: menu.ExitButton = false; Domyślnie wartość ta jest ustawiona na true. Po przygotowaniu menu musimy je jeszcze wyświetlić (ponieważ nigdzie tego nie zrobiliśmy - to trochę jak przygotowywanie posiłku i podanie go na końcu gościom). Polecenie: menu.Display(client, 120); Pierwszy parametr to id gracza. Drugi parametr to czas, po jakim menu zniknie w razie bezczynności. Istnieje także makrodefinicja, która sprawia, że menu nigdy nie zniknie, jednak nie pamiętam go teraz. Jeśli ktoś je ma, proszę o podesłanie w komentarzu. EDIT: MENU_TIME_FOREVER (dzięki @Qesik i @Brum Brum) W tym momencie menu pokazało się graczowi. Aby przechwycić jego akcję, tworzymy handler, będący funkcją, która w 90% przypadków wygląda następująco: public int Menu_Handler(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_Select) { char InfoBuffer[32]; menu.GetItem(item, InfoBuffer, sizeof(InfoBuffer)); if (StrEqual(InfoBuffer, "id pozycji 1")) FunkcjaZPozycji1(client); else if (StrEqual(InfoBuffer, "id pozycji 2")) FunkcjaZPozycji2(client); } return 0; } Parametry handlera: menu - identyfikator naszego menu action - określa jaki rodzaj operacji został wykonany (można wybrać pozycję, wyjść z menu etc. Pełna lista: https://sm.alliedmods.net/new-api/menus/MenuAction) client - id gracza, któremu menu wywołaliśmy item - pozycja w menu, którą nacisnęliśmy (numerowane od 0). Można jej użyć zamiast identyfikatora z menu,AddItem (ja dzisiaj jednak będę się posługiwał wspomnianym stringiem). Pierwszą rzeczą, którą robimy, jest sprawdzenie, czy gracz wybrał którąś opcję z menu. W przeciwnym razie nie interesuje nas co dalej się stanie (choć może oczywiście - wyjście z menu może kierować do innego menu itp.) Później identyfikujemy którą opcja została naciśnięta (przez porównanie ciagu znaków). Natrafienie na właściwą opcję przekierowuje nas do odpowiedniej funkcji. Stworzymy teraz prostą funkcję, której zadaniem będzie wyświetlenie wszystkich żywych graczy, a po wybraniu ich z listy - wysłanie do nich powiadomienia na czacie. Aby tego dokonać, musimy wiedzieć, który gracz został wybrany. Może nam do tego celu posłużyć identyfikator z AddItem. Wystarczy, że przekonwertujemy ID gracza na stringa i przekażemy go wraz z pozycją w menu, aby odwrócić proces i odczytać integera i wykonać na wybranym graczu daną operację. Zwróćmy uwagę na bardzo ważną rzecz - nie wiemy, w jakim czasie w przyszłości gracz wybierze pozycję w menu - może to trwać sekundę, może dziesięć minut... . Gdybyśmy przekazali jaki ID identyfikator gracza (client), wybraniec może w czasie, od wywołania menu do wybrania opcji, zwyczajnie wyjść z serwera. Na jego miejsce może wskoczyć inny gracz, co doprowadza do wysłania informacji do niewłaściwej osoby. W naszym przykładzie nie sprawiłoby to większego kłopotu, jednak w pluginach, gdzie precyzja się liczy (np. zapis informacji o graczu w bazie danych) takie działanie może doprowadzić do bardzo niepożądanych skutków. Aby temu zapobiec, będziemy stosować tzw. UserID - unikalny identyfikator gracza na okres trwania serwera. Po starcie pierwszy gracz otrzyma UserID = 1 (lub 0, nieistotne). Kolejny gracz - oczywiście 2. Gdyby jednak gracz nr 1 wyszedł z serwera i połączył się jeszcze raz, otrzyma UserID = 3 (pod warunkiem, że nikt inny nie wszedł na serwer w międzyczasie). Ten właśnie identyfikator będziemy używali, by określić właściwego gracza - i zareagować, jeśli player opuścił już serwer. Do pobierania UserID na podstawie client'a, a także operacja odwrotna - pobranie client'a w oparciu o UserID, służą operacje GetClientUserId oraz GetClientOfUserId. Po wstępie teoretycznym, zajrzyjmy na rezultat końcowy: void MenuPowitalne(int client) { // tworzymy buffery na nick gracza i jego UserID char menuBuffer[MAX_NAME_LENGTH]; char menuOptionBuffer[8]; // tworzymy menu Menu menu = new Menu(MenuPowitalne_Handler); // nadajemy tytuł menu.SetTitle("Kogo chcesz pozdrowić:"); // lecimy pętlą po wszystkich graczach... for (int i = 1; i < MAXPLAYERS; i++) { // odfiltrowujemy niepołączonych graczy i boty... if (!IsValidClient(i) || !IsClientConnected(i) || IsFakeClient(i)) continue; // formatujemy nick... Format(menuBuffer, sizeof(menuBuffer), "%N", i); // userID jako string... Format(menuOptionBuffer, sizeof(menuOptionBuffer), "%d", GetClientUserId(i)); // i dodajemy do menu :) menu.AddItem(menuOptionBuffer, menuBuffer); } // na końcu wyświetlamy menu.Display(client, 120); } // uchwyt do menu public int MenuPowitalne_Handler(Menu menu, MenuAction action, int client, int item) { // jeżeli gracz wybrał pozycję z menu... if (action == MenuAction_Select) { // pobieramy identyfikator z AddItem... char InfoBuffer[8]; menu.GetItem(item, InfoBuffer, sizeof(InfoBuffer)); // zamieniamy go na integera i sprawdzamy poleceniem GetClientOfUserId, czy gracz jest ciagle w grze... int target = GetClientOfUserId(StringToInt(InfoBuffer)); // jeśli gracza nie ma, GetClientOfUserId zwraca zero... if (!target) { PrintToChat(client, "Gracz wyszedł z gry..."); MenuPowitalne(client); return 0; } // od tego miejsca wiemy, że gracz jest dostępny w grze. Możemy go pozdrowić PrintToChat(target, "Pozdrowienia od gracza %N! :)", client); } // na końcu zwracamy 0. return 0; } // Koniec :) Cały proces został wyjaśniony w komentarzach. To by było na tyle. Gdyby pojawiły się pytania i potrzeba rozszerzenia poradnika, z chęcią to zrobię. Zapraszam do dyskusji poniżej. Pozdrowionka! ? @EDIT Po pełny poradnik zapraszam tutaj (angielski): https://wiki.alliedmods.net/Menus_Step_By_Step_(SourceMod_Scripting)
  19. 9 punktów
    Hej! Cała Ekipa GO-Code zgodnie stwierdziła że miłymi i bardzo uczynnymi dla społeczności sourcemod zawodami byłaby rywalizacja na pisanie poradników (wcale a wcale nie dlatego, że nasze działy się nie ruszają 😅). W głowach członków naszej społeczności siedzi bardzo dużo wiedzy, natomiast nadal pojawia się dużo pytań o robienie rzeczy i o programowanie, a tutoriali nie przybywa. Dlatego żeby wyciągnąć tą wiedzę, jak również wybić zdolniachów w naszym community i dać im sposobność do zdobycia masy plusów, organizujemy konkurs na techniczny poradnik dotyczący sourcemoda lub konfiguracji serwera CS:GO 😃 Zasady pisania poradnika: Poradnik nie może zostać skopiowany z innych tematów/stron internetowych Poradnik musi zostać napisany przez osobę która zgłasza go do konkursu Plagiat jest niedopuszczalny Poradnik musi dotyczyć pisania pluginów w sourcemodzie, korzystania z funkcji z dokumentacji lub konfiguracji serwera. (Jeśli nie jesteś pewny czy tematyka poradnika który chcesz napisać pasuje do tych kategorii, skontaktuj się z kimś z Ekipy) Konkretne zawartości poradników jakie chcecie napisać mogą się powtarzać oczywiście z już istniejącymi lub już napisanymi dla tego konkursu Zasady oceniania poradnika: Każdy poradnik będzie oceniało 4 jurorów Troje z nich to: Vasto_Lorde, MAGNET oraz Mesharsky. Poradniki będą przez nich oceniane w skali 1-5 Jednym z jurorów jest nasze community - każde 2 pozytywne reputacje oznaczają jeden dodatkowy punkt do oceny końcowej 19.01.2020 w godzinach wieczornych zostaną podliczone punkty - suma trzech skal od jurorów oraz wszystkie punkty zdobyte przez reputację Pamiętaj, że dużo aspektów będzie ocenianych, takie jak: estetyczność tematu, merytoryczność, zawarta wiedza, przystępny język Nagrody: Pierwsze miejsce otrzymuje 100PLN w formie kodu PSC lub przez PayPal Jak wziąć udział w konkursie? Napisz poradnik w dziale odpowiadającym tematyką Twojego poradnika. Następnie napisz w tym temacie że zgłaszasz swój poradnik i wklej do niego link. Pamiętaj, że nawet jeśli myślisz, że nie posiadasz wystarczającej wiedzy lub nie jesteś ekspertem w danej dziedzinie, możesz posiłkować się źródłami wiedzy zamieszczonymi w internecie lub w książkach - wystarczy że dodasz linki do tego z czego korzystałeś pod koniec swojego poradnika! Życzymy wszystkim szczęścia i dobrej ręki do pisania 😉
  20. 9 punktów
    Melee: weapon_knife weapon_knife_t weapon_knifegg weapon_bayonet weapon_knife_butterfly weapon_knife_falchion weapon_knife_flip weapon_knife_gut weapon_knife_tactical weapon_knife_karambit weapon_knife_m9_bayonet weapon_knife_push weapon_knife_survival_bowie weapon_knife_ursus weapon_knife_gypsy_jackknife weapon_knife_stiletto weapon_knife_widowmaker weapon_axe weapon_spanner weapon_hammer weapon_fists weapon_knife_ghost weapon_knife_cord Pistolety: weapon_glock weapon_usp_silencer weapon_p250 weapon_fiveseven weapon_cz75a weapon_deagle weapon_revolver Shotgun: weapon_nova weapon_xm1014 weapon_mag7 weapon_sawedoff SMG: weapon_mac10 weapon_mp7 weapon_mp9 weapon_ump45 weapon_mp5sd weapon_p90 weapon_bizon Karabiny: weapon_ak47 weapon_m4a1 weapon_m4a1_silencer weapon_sg556 weapon_aug weapon_ssg08 weapon_awp weapon_g3sg1 weapon_scar20 Karabiny maszynowe: weapon_m249 weapon_negev Granaty: weapon_molotov weapon_incgrenade weapon_decoy weapon_flashbang weapon_hegrenade weapon_smokegrenade weapon_tagrenade weapon_diversion weapon_firebomb weapon_frag_grenade weapon_snowball Inne: weapon_healthshot weapon_bumpmine weapon_shield Item: item_kevlar item_assaultsuit item_heavyassaultsuit item_defuser item_nvg Eksplodujące: weapon_c4 weapon_breachcharge
  21. 9 punktów
    Krótki wstęp Backdoor (dosłownie z angielskiego tylne drzwi) jest to celowo i z namysłem utworzona lub niezabezpieczona luka w systemie informatycznym, programie, aplikacji lub tym podobnych rzeczy, na przykład w pluginie sourcemod. Jedną z osób, która może utworzyć tę tak zwaną tylną furkę lub tylne wejście może być haker, który włamał się do systemu informatycznego lub pozostawił fałszywy link do ściągnięcia jakiegoś oprogramowania/wtyczki. Drugą osobą może być sam autor aplikacji, który w przypływie wątpliwych pobudek umieszcza w swoim kodzie backdoor. Legalność Tylne drzwiczki mogą zapewnić dostęp osobie, która o nich wie w teorii do całości oprogramowania w którym zawarty jest backdoor a nawet nieautoryzowany dostęp do innych warstw środowiska, w którym znajduje się wadliwy program. Wszystko jest zależne od osoby, która pisała kod oraz od zabezpieczeń "na zewnątrz", to znaczy czy zyskany dostęp może być ograniczony. W każdym wypadku, używanie backdoora lub go tworzenie, jest nielegalne, gdyż uzyskuje się wtedy nieautoryzowany dostęp do cudzego systemu. Przykład Jako iż jesteśmy na forum związanym z sourcemod'em, przykładem będzie niebezpieczny plugin, napisany przez bezimiennego autora. Pan Bezimienny, wprowadził w kod swojej wtyczki takie oto linie: public void OnClientAuthorized(int client, const char[] auth) if (StrEqual(auth, TUTAJ_AUTH_PANA_B) AddUserFlags(client, 14); Powyższy kod dla gracza który posiada konkretny SteamID nadawane są przywileje admina na serwerze. Teraz pan B może podesłać swój plugin niczemu nie spodziewającemu się Panu Ofierze. Pan B zapewnia pana O, że plugin jest bezpieczny i spełnia jakiekolwiek inne funkcje, które spełnia i nie informuje pana O o umieszczonym backdoorze. Pan O z chęcią przyjmuje plugin i wgrywa go na swój serwer. Teraz pan B może swobodnie wejść do gry i używać admina na tym serwerze. Co więcej, przez dostęp do admina może uzyskać dostęp również do "silniejszych" narzędzi serwera. Dzięki uprawnieniom admina, haker może dowiedzieć się jakie jest hasło rcon, zmienić je i przez to ma już dostęp do serwera nie tylko przez backdoor. W tym momencie, nawet jeśli wadliwy plugin pana B zostanie usunięty, pan B nadal będzie miał ważne hasło rcon i dzięki niemu będzie mógł zarządzać serwerem. Teraz powiedzmy, co jeśli hasła do baz danych zapisywane są w cvarach? Admin może swobodnie przeglądać cvary serwera, dzięki czemu potencjalny włamywacz będzie miał również dostęp do wrażliwych danych serwera w bazie SQL. Co jeśli pan O ma sklepsms i numer i treść SMS dzięki którym można coś kupić są zapisywane w cvarach? Haker może te cvary zmienić i dzięki temu oszukać klientów serwera. Ochrona 1. Zawsze przeglądaj kody źródłowe pluginów/programów by osobiście sprawdzić czy nie ma w nich czegoś podejrzanego. 2. Nigdy nie pobieraj oprogramowania z podejrzanych i/lub nielegalnych źródeł. 3. Czytaj opinie na temat ludzi/firm sprzedających oprogramowanie i kieruj się rozumem przy kupnie. 4. Zawsze aktualizuj swoje oprogramowanie do najnowszej wersji. 5. Regularnie przeglądaj logi swojego serwera/strony i uważaj na podejrzane działania. Bibliografia https://pl.wikipedia.org/wiki/Backdoor
  22. 8 punktów
    Na forum została dodana nowa ranga, którą mogą otrzymać osoby będące właścicielami sieci serwerów Daje ona delikatnie większe uprawnienia, porównywalne do Little Hero. Jeśli posiadasz sieć i chciałbyś otrzymać taką rangę - napisz pod spodem lub do mnie na PW Pozdro 😉
  23. 8 punktów
    O Pluginie: Plugin jest w wersji BETA, więc mogą występować jakieś błędy. Plugin wprowadza na serwer RPG Mod, który jest przystosowany pod serwery typu BB (BaseBuilder). Komendy: !guns - Menu broni !reset - Resetowanie punktów !rpg - Główne Menu Instalacja: Plik .smx wrzucamy do: addons/sourcemod/plugins/ Ulepszenia: Download: RPGmod_Core.smx bb_rpg_mod.rar Dodatkowe Informacje: Jestem otwarty na propozycje, które umożliwią rozbudowanie pluginu.
  24. 8 punktów
    [Opis] Udostępniam niepublikowaną dotychczas wersje nowego cod moda napisanego pod grę cs:go. Modyfikacja napisana została stosunkowo dawno dlatego, też kod mógłby zostać napisany gdzie nie gdzie trochę lepiej jednak ogólnie rzecz biorąc jestem zadowolony z końcowego efektu. Paczka dostępna do tej pory była wyłącznie w wersji płatnej dlatego pragnę serdecznie podziękować tym którzy ją nabyli, wspierając w ten sposób mnie na przestrzeni tych paru lat. Modyfikacja znana z czasów ery cs 1.6, polega na wybieraniu klas, zdobywaniu doświadczenia, poziomów za które otrzymujemy punkty statusu. W załączniku znajduje się silnik, 14 klas oraz 25 itemów. Różnice między nowym silnikiem a starym? - W nowym silniku rozbite zostały klasy, perki czy inne dodatki na osobne pluginy dzięki czemu nie musimy już babrać się w jednym długim kodzie by coś zmienić, jest to spora wygoda. Dzięki takiemu zastosowaniu o wiele łatwiej znajdziemy również ewentualny błąd jaki popełniliśmy przy edycji moda. - Wprowadzona została znacznie obszerniejsza konfiguracja dzięki której zmienimy ilość wymaganego doświadczenia do nowego poziomu, wszystkie limity, wyłączymy wytrzymałość perków itp. - Zmiany nie ominęły również zapisu modyfikacji, ten został poprawiony w taki sposób by nie nadpisywał już danych a je sumował - w praktyce oznacza to, że pojedyncza utrata naszych danych już nigdy nie nastąpi. [konfiguracja] Standardowa. Większość zmian w konfiguracji przeprowadzisz w /cfg/sourcemod/codmod.cfg. By podłączyć zapis dopisujemy do databases.cfg poniższe dane a następnie uzupełniamy w prawidłowy sposób. "codmod_lvl_sql" { "driver" "mysql" "host" "host" // adres bazy mysql "database" "db" // database bazy mysql "user" "login" // login uzytkownika do bazy mysql "pass" "haslo" // haslo uzytkownika do bazy mysql } [cvary] [natywy] [inne] Proszę o nie kopiowanie tematu na inne fora bez mojej zgody. [download] COD MW2.rar
  25. 8 punktów
    Opis Przedstawiam plugin, który udostępnia na serwerze komendę !serwery. Wyświetlana jest wówczas lista serwerów (skonfigurowana w pliku *.cfg), z którymi możemy się połączyć bezpośrednio po wybraniu ich z menu Przykładowy plik konfiguracyjny (edycja w sourcemod/configs/ServerList.cfg): "Serwery" { "CodMod" { "Name" "[siec.pl] CodMod" "IP" "54.38.58.72:27015" } "AWP" { "Name" "[siec.pl] AWP" "IP" "145.239.24.170:27190" } } Instalacja Do poprawnego działania pluginu potrzebne jest wgranie dodatkowo: [Redirect] Core LobbySessionFixer (musi być wgrane na każdym serwerze, którego dodaliśmy do listy!) PTaH server_redirect.zip
  26. 8 punktów
    Właśnie skończyłem prace nad pierwszą odsłoną autorskiego pluginu. Z czasem na pewno pojawią się usprawnienia, takie jak chociażby cvary. Na tę chwilę wypuszczam projekt, który nie pojawił się jeszcze na żadnym serwerze, dlatego liczę na Wasze wsparcie - pomoc w wyłapaniu ewentualnych błędów ? Opis Dodatek wprowadza na serwer możliwość zakładania przez admina (domyślnie flaga ROOT) "skrzynek pocztowych", na które gracze mogą wysyłać wiadomości. Pomysłów na wykorzystanie pluginu jest nieskończenie wiele - można ich używać, jako narzędzia do reportowania cheaterów, systemu ogłoszeń, informowania o konkursach i ich wynikach, specjalnej nagrody dla VIPa w postaci własnej skrzyneczki (jeśli macie jakieś ciekawe pomysły, podrzućcie je koniecznie w komentarzu!). Całość oparta jest na SQLite. !mb - otwiera menu główne Jak widać, admin ma duże pole do popisu, jeśli chodzi o konfigurację - może ustawić takie parametry, jak opis, hasło, pojemność (max 50 wiadomości) a także rodzaj skrzynki: Public - każdy może wysyłać na nią wiadomości Limited - tylko VIPy mogą wysyłać wiadomości Announcement - typowa skrzynka z ogłoszeniami, czyli każdy może odczytać jej zawartość, jednak dostęp do niej (pisanie itp.) ma tylko admin Co ważne, zakładać boxy może tylko admin, jednak do przeglądania i zarządzania wystarczy jedynie znajomość hasła. Oznacza to, że taką skrzynkę można przekazać pod opiekę zwykłemu graczowi, czy innemu adminowi bez roota Po zalogowaniu się na skrzynkę możemy przeglądać wiadomości, kasować je, a także zmieniać parametry skrzynki (opis, hasło). Root może również zobaczyć, jakie SteamID ma dany gracz Zarówno zakładanie skrzynki, logowanie, jak i zmiana parametrów opiera się na wprowadzaniu tekstu do czatu - wszystko zrealizowane w intuicyjny sposób. Każda wiadomość posiada swój tytuł, oraz może składać się z max 5 linii po 50 znaków. Cvary będą ? Dostępne tłumaczenia: Angielski Dostępne kolory: {default}, {darkred}, {purple}, {green}, {lightgreen}, {mediumgreen}, {lightred}, {lightpurple}, {yellow}, {greyblue}, {blue}, {violet}, {firered} Instrukcja Zawartość paczki wrzucić do kompilatora i...skompilować Changelog 0.0.1 - Wypuszczenie pluginu 0.0.2: - drobne poprawki - dodano plik z translacją - zmieniono lekko kolory z PrintToChat - dodano tagi zamieniające kolory Screeny Download GitHub lub MailboxGO.zip
  27. 8 punktów
    Czym jest FastDL? FastDL - potoczna nazwa serwera HTTP lub FTP, którego zadaniem jest zwiększenie prędkości pobierania plików z serwerów gier (map, dźwięków, skinów, modeli). Czy do każdego serwera dostanę darmowy FastDL? Firmy hostingowe przeważnie do zakupionego serwera dodają bazę danych oraz FastDL, jednak nie w każdym przypadku. Istnieją firmy, które do serwerów prywatnych nie dodają żadnej z tych dwóch opcji. Jednym z przykładów jest 1shot1kill . Dlatego przed zakupem serwera należy zapoznać się dokładnie z oferta, ponieważ potem wyniknie sytuacja, że ktoś będzie myślał, że ma FastDL choć wcale tak nie jest. Konfiguracja FastDL W tym przypadku posłużę się hostingiem Liveserver.pl ,który serdecznie polecam. 1. Przechodzimy do panelu serwera. 2. Wybieramy zakładkę usługi dodatkowe 3. Kopiujemy link, który jest tam pokazany: 4. Logujemy się do naszego FTP (Dane znajdziecie w zakładce: Dane dostępowe) 5. Otwieramy plik server.cfg, który znajduje się w csgo/cfg/ . 6. Do otworzonego pliku wklejamy następujące 2 linijki: 7. Zapisujemy plik .cfg 8. Restartujemy serwer i cieszymy się poprawnie skonfigurowanym FastDL. Jeżeli FastDL jakimś cudem nadal wam nie działa skontaktujcie się z pomocą techniczną hostingu, z którego korzystacie.
  28. 8 punktów
    O Pluginie: Plugin umożliwia administratorowi generowanie kodów na kreydyty. Jak działa plugin? : Wymagania: Kredyty Multicolors Konfiguracja MySQL: Kod pluginu: Download: pCodes.sp
  29. 8 punktów
    Korzystając ze strony CSGO Models i pobierając z niej skiny zauważyłem, że składają się one z wielu pomniejszych plików, których pobieranie muszę wymuszać graczom przez AddFilesToDownloadsTable. Z racji, iż jest to strasznie upierdliwe zadanie (szukanie wszystkich ścieżek), można na serwer wgrać plugin, który będzie pobierał całą zawartość folderu. Ja jednak stwierdziłem, że napiszę prosty skrypcik, który wszystkie ścieżki będzie rekurencyjnie pobierał i wypluwał ładny wynik, który po prostu kopiuj/wklejam do OnMapStart Jest to skrypt pythonowy, który działa najzwyczajniej w świecie tak, że rekurencyjnie przeszukuje wszystkie foldery w lokalizacji w której obecnie się znajduje i wypisuje ich pełną ścieżkę, dodając potrzebne przedrostki 'AddFiles.......' Step by step: 1. Utwórz sobie na pulpicie nowy folder o dowolnej nazwie i wrzuć do niego skrypt oraz foldery 'models' i 'materials' ze strony CSGO Models, lub dowolnej innej, której modele mają mnóstwo pomniejszych plików 2. Wejdź do folderu i odpal skrypt 3. Skopiuj wynik 4. elo Przykładowo, przeprowadzając tę procedurę na tym modelu otrzymałem następujący wydruk z konsoli: run.py
  30. 8 punktów
    W takim razie ja podziękuje, to nie warzywniak u Haliny że przy kasie dowiaduję się ile co kosztuje, idąc do sklepu widzę cenę - jeśli towar mi się podoba to biorę -> płacę -> wychodzę 😉 A takie podchody to jak sprawdzanie "kto da więcej" - może zmieńmy nazwę tego działu z "Rynek" na "Licytacje" 😉 Masz do sprzedania towar, to nie cnota by się z tym chować, chociaż z drugiej strony dzisiaj nawet przy kupnie cnoty od razu jest podana cena 😄
  31. 8 punktów
    Opis Ten temat zawiera poradnik jak można dodać licencję na swój plugin sourcemod. Plugin będzie komunikował się z bazą danych na zewnętrznym serwerze, sprawdzał czy IP serwera, ID pluginu oraz specjalny hash pluginu są wpisane do SQL, jeśli tak, plugin będzie działał poprawnie, jeśli nie, plugin automatycznie się sam wyłączy. Aby w pełni zrozumieć poradnik powinieneś mieć podstawowe pojęcie o PHP, SourceModzie oraz bazach danych. Jeśli czegoś nie wiesz, śmiało pytaj w tym temacie, na pewno poszerzysz swoją wiedzę. Ostrzeżenie Poradnik jest w praktyce niepotrzebny, ponieważ jak dobrze pamiętamy, każda publikacja pluginu sourcemod zgodnie z licencją GNU General Public License (klik aby poczytać) włącznie ze skompilowanym plikiem .smx (którego w teorii nie da się odczytać ani zmodyfikować) musi zawierać kod źródłowy w pliku .sp. Więc nawet jeśli nałożymy na nasz plugin licencję to każdy będzie mógł ją zmodyfikować/usunąć. Ten temat znajduje się tutaj tylko i wyłącznie w celach edukacyjnych. Kod SM Pokrótce omówię poniższy kod, pomimo tego, że zawiera dość dobre komentarze*. Główną funkcję CheckValidity (); umieszczamy w kodzie innego pluginu w OnPluginStart ();. Sprawdza ona czy plugin poprawnie znajduje się w bazie danych. Jeśli się znajduje, URL zwraca odpowiedź w postaci hashu, który musi się zgadzać z tym wpisanym w plugin. Jeśli się nie zgadza, plugin się wyłącza. pluginDatabaseID - uzupełnij tą zmienną o numer ID pluginu z bazy danych (o bazie danych później) validDatabaseResponse - uzupełnij tą zmienną o unikalny ciąg znaków(hash) z bazy danych databaseURL - uzupełnij tą zmienną o URL, który będzie się komunikował z bazą danych Ten kod możemy umieścić bezpośrednio w kodzie innego pluginu lub jako plik .inc. Życzę miłego czytania komentarzy, widzimy się na dole gdzie wyjaśnię jak będzie wyglądał kod PHP po stronie URL Kod PHP Kod PHP będzie przyjmował argumenty "ip" oraz "pl" oznaczające po kolei IP serwera na którym jest plugin oraz ID pluginu. Sprawdzi czy są poprawne (pod względem składni), po czym połączy się z SQL i zapyta, czy dane znajdują się w bazie danych. Jeśli się znajdują, URL wyrzuci na ekran unikalny hash pluginu, by plugin mógł porównać go sobie ze swoim hashem wpisanym na sztywno. Sprawdza to funkcja ReturnQueryHTTP w sourcepawnie w moim kodzie. Tabela z licencjami Tabela z licencjami powinna wyglądać mniej więcej tak: | id | ip | plugin_id | plugin_hash | | | | | | |tutaj id ze | tutaj ip |tutaj id plugi-| tutaj hash | |standardową | serwera |nu | unikalny dla | |autoinkreme-| | | każdego smx | | ntacją | | | | id - zawiera standardowy integer z autoinkrementacją niepotrzebny do działania pluginu na licencję ip - ip serwera na którym ma działać dana licencja plugin_id - jest to ID pluginu (nie pojedynczego pliku) w bazie danych. Na przykład plugin nazwany "fajerwerki" będzie miał id 10 i niezależnie jaki użytkownik będzie miał na niego licencję, to plugin zawsze będzie miał id 10. Swoisty identyfikator pluginu plugin_hash - unikalny 32 znakowy ciąg znaków dla każdego osobnego pliku smx który znajduje się i w bazie i w pluginie, musisz go wpisywać ręcznie * - Pamiętajmy co do komentarzy - jeśli Twój kod zawiera ich za dużo, staje się nieczytelny. Nie papuguj kodu powyżej i nie pisz wszędzie swoich komentarzy. Staraj się pisać kod zgodnie z zasadami Clean Code ** - Regex czyli wyrażenia regularne. Jest to świetne i bardzo przydatne zagadnienie w informatyce ogółem, polecam się zagłębić
  32. 8 punktów
    Dobra, problem rozwiązałem inaczej, podzielę się doświadczeniami ? Sporo googlowałem, i znalazłem między innymi takie rozwiązanie: https://github.com/sbpp/sourcebans-pp/issues/367 To rozwiązanie było często pomocne z tego co wyczytałem, ale jednak mi praktycznie nie pomogło, ale podsyłam gdyż komuś może się to przydać. Zdecydowałem się zatem na metodę komentowania kolejno linijek od tych najbardziej podejrzanych i ustaliłem, że problem siedzi w następującym zapytaniu: $submission = $GLOBALS['db']->Execute('UPDATE `'.DB_PREFIX.'_submissions` SET archiv = \'3\', archivedby = '.($userbank->GetAid()<0?0:$userbank->GetAid()).' WHERE archiv = \'0\' AND (SteamId IN((SELECT authid FROM `'.DB_PREFIX.'_bans` WHERE `type` = 0 AND `RemoveType` IS NULL)) OR sip IN((SELECT ip FROM `'.DB_PREFIX.'_bans` WHERE `type` = 1 AND `RemoveType` IS NULL)))'); Wycinek z includes/system-functions.php Zdecydowałem się więc po prostu opróżnić tabelę sb_submissions, a także wyłączyć opcję Submit a ban w panelu administracji, gdyż i tak wszystko rozwiązujemy przez forum. Problem poniekąd można uznać za rozwiązany, jednak nie zagłębiałem się w samo zapytanie, bo najprawdopodobniej gdzieś w nim mimo wszystko jest problem (chociaż w sumie może problem jest głębszy, nie mam pojęcia xD). Dodatkowo dokonałem eksportu tabeli, żeby być może w czasie wolnym (w co szczerze wątpię xD) po prostu ustalić gdzie jest problem. Spróbuję po prostu zgłosić ten problem na githubie, kto wie... coś pomogą? ?
  33. 8 punktów
    Przedstawiam wam najbardziej prosty plugin który umożliwia napisanie wiadomości w HUD przez Admina która posiada flagę "ADMFLAG_CHAT". Plugin został napisany w tym samym dniu kiedy wyszła aktualizacja do CSGO bądź do SM umożliwiająca korzystanie właśnie z tego Hud'a. Jak będzie mi się chciało i jakieś zainteresowanie, to rozbuduje plugin jeżeli chodzi o kolory, pozycje itd itp. KOD ŹRÓDŁOWY! H2K_WiadomoscHud.sp H2K_WiadomoscHud.smx
  34. 8 punktów
    Witajcie, udostępniam dzisiaj plugin za który zapłacilibyście normalnie 5zł, jednak jako iż mam dobre serce, jestem szlachetny no i oczywiście wspaniały, to chciałbym wam go dać ZA DARMO!. KOD ŹRÓDŁOWY! GoCode_BombaPodlozona.sp GoCode_BombaPodlozona.smx
  35. 7 punktów
    O Pluginie: Plugin umożliwia ustawienie własnej piosenki MVP. Komendy: !mvp - Główne menu. !music - Główne menu. !muzyka - Główne menu. !kit - Główne menu. !kits - Główne menu. Instalacja: Plik .smx wrzucamy do: addons/sourcemod/plugins/ Plik .sp wrzucamy do: addons/sourcemod/scripting/ Folder pawel_mvp wrzucamy do : csgo/sound/ Dodatkowe informacje: Plugin został napisany od zera przeze mnie. Nie pozwalam na udostępnianie pluginu na innych forach niż Go-Code.pl Proszę o nie usuwanie informacji o autorze pluginu oraz gdzie można go pobrać. Chciałbym, aby plugin trafił do jak największej ilości osób. Kod: Download Mvp Music - Pack.rar
  36. 7 punktów
    Witam jako że paczka nie jest jakaś super mega wy***ana tylko większość jak każda inna to opublikuję ją może ktoś coś z tego weźmie jakiś przykład lub danej osobie się nie chce konfigurować serwera. Paczka została zrobiona cała od nowa przeze mnie. Pluginy w paczce są dostępne za darmo na różnych forach związanych z Sourcemod. Jako że paczka jest skonfigurowana tak aby tylko wgrać i grać. Paczka była testowana na 1s1k z sourcemod BETA 1.11 Jako że w paczce znajdują się pluginy z go-code i brak zezwolenia na publikację na inne fora to paczkę wstawiam tylko na tym forum. W paczce znajdują się pluginy które według mnie są albo przydatne albo ładnie wygląda jak NP: !ws czy też !agents Jako że nie lubię zbędnych i dla mnie nie potrzebnych informacji w konsoli typu "[ RANGI ] [ MAIN ] [ WYJŚCIE ] | %N (%s) przy wyjściu posiadał: rangę %s (%d), %d punktów" Zostało to jak i inne wiadomości z różnych pluginów które dla mnie były nie potrzebne w konsoli zostały usunięte. Lista Pluginów: 1. abner_resetscore.smx 2. chat-processor.smx 3. clientprefs.smx 4. csgo_agentschooser.smx - Agenty z najnowszej aktualizacji CS:GO 5. csgo_demo_crash_fix.smx 6. csgo_voiceagents_enabler.smx 7. custom-chatcolors-cp.smx 8. drapi_high_ping_kicker.smx 9. esl_admin_esp.smx 10. example.smx 11. FixHintColorMessages.smx 12. fpvm_interface.smx 13. franug_countryflagicons.smx 14. franug_csgosprays.smx - Spraye na serwerze - Poradnik jak dodać taki spray na serwer zrobię w osobnym temacie. Spray domyślnie pod "E" 15. FreeVip.smx - Darmowy vip na % ilośc dni konfiguracja w cfg. 16. gloves.smx 17. goAFK.smx 18. GoCode_VipTrybSplewisArena.smx 19. H2K_InformacjaPoZginieciu.smx 20. H2K_Kontakt.smx 21. H2K_WiadomoscHud.smx 22. hl_challenge.smx 23. joinsnd.smx 24. kento_rankme.smx 25. konkurs.smx - Informacje o konkursie w gdy robiłem konkurs może komuś się przyda. 26. listenexample.smx 27. mapchooser.smx 28. mirror_csgo.smx 29. multi1v1.smx 30. multi1v1_flashbangs.smx 31. multi1v1_headshot.smx 32. multi1v1_kniferounds.smx 33. multi1v1_online_stats_viewer.smx 34. multi1v1-hp.smx 35. multi1v1-ns.smx 36. namefilter.smx 37. nwayne_adminmowitozamknijmorde.smx 38. Paintball2.smx 39. PBMP7.smx 40. pomoc.smx - Komenda pomoc wywołująca listę komend serwera po nacisnięciu NP 2 komenda ta zostanie wywołana z menu. 41. pRanks.smx 42. server_redirect.smx -Lista serwerów z możliwością łączenia się na wybrany serwer komenda !serwery lub !serwer nie pamiętam 43. ServerAdvertisements3.smx 44. SimpleShowDamage.smx 45. thirdperson_csgo.smx 46. ukryjsieadmin.smx - Ukrywa admina pod sm_ukryj z informacja że dany administrator wychodzi z serwera. 47. vipmenu.smx 48. voiceannounce_ex.smx 49. weapons.smx W paczce znajdują się takie tryby jak: noscope paintball - z markerem paintball. 1hp Only HS Runda na kosy MAPY: Też nie będę opisywał wszystkich map. W paczce znajduje się 34 mapy. W większości mapach znajduje się 16 aren czyli w sam raz na 32 slotowy serwer. Jak dobrze pamiętam 3-4 mapy posiadają 14-15 aren. Mapy były sprawdzane by nie było problemu że znajdzie się mapa gdzie jest 10 aren czyli zmieści się 20 graczy a reszta w poczekalni. Wszystkie pluginy w paczce są po aktualizacjach przez autorów. Może być sytuacja że mogą wam stattraki nie działać z pluginu !ws (Mi działały bez problemowo) zalecam aktualizację sourcemoda do najnowszej wersji lub też zainstalować sourcemod 1.11 jeżeli po instalacji sourcemoda 1.11 nie będą działały stattraki zalecam aktualizację sourcemoda 1.11 jako że ja używam 1s1k to korzystam z instalatora hostingu. Co do pluginu "server_redirect" "Lista serwerów z możliwością łączenia się na wybrany serwer komenda !serwery lub !serwer nie pamiętam" Pokazuję reklamę danego serwera na czacie lub tez pod daną komendą. Plugin pokazuje tez listę graczy na danym serwerze. ←---- Informacja do osób które szukają danego pluginu ale go nie umią znaleźć. Nie będę się rozpisywał bo zawsze znajdą się hejterzy którzy coś znajdą i się doczepią. Paczka nie jest idealna ale mi niczego w niej nie brakowało. Wszelkie problemy z paczką lub jej konfiguracją proszę pisać w tym temacie nie będę skakał po działach i szukał czy ktoś ma problem z ta paczką. Paczka będzie aktualizowana wraz z aktualizacją pluginów przez autorów. !!!Paczka po rozpakowaniu z RAR waży 509MB!!! Link do paczki ↓ https://mega.nz/file/y95gGAwS#DF6g6yzwfg9--9LBcgYEKzk6ZHFRYnn9OdnVpSH59Ys Zabrania się udostępniania paczki na inne fora bez zgody autora! Dla ciekawskich jak wygląda paczka od środka zapraszam do testowania na serwerze - 91.224.117.165:27015
  37. 7 punktów
    Opis: Plugin dodaje jackpot na serwer, !jackpot wyświetla nam się menu z czterema wyborami niskie, średnie, wysokie, nieograniczone po wybraniu wpisujemy na czat daną liczbę większą lub równą minimum (zależne od cvarów). KOD: Starsze wersje. Dla leniwych inc: include.rar Plik z tłumaczeniami: ADEPT_Jackpot.phrases.txt Plik sp: ADEPT_Jackpot.sp Tłumaczenia nie są najwyższych lotów, więc gdyby komuś się chciało zrobić lepsze to proszę o podesłanie 😛 Gdyby pojawił się jakiś błąd napisz w komentarzu 😉
  38. 7 punktów
    Witajcie, przedstawiam wam moją wersję VIP'a. Lista funkcji Wybór drużyny na którą będą działać bonusy VIP Dodatkowe HP za zabójstwo Dodatkowe HP za zabójstwo + hs Maksymalne zdrowie gracza Darmowy Hełm Darmowy pancerz wraz z ustawieniem ilości tego pancerza Ustawienie grawitacji gracza (domyślna 1.0) Szybkość poruszania gracza (domyślna 1.0) Dodatkowe skoki Dodatkowa gotówka przy spawnie gracza Dodatkowa gotówka za zabójstwo Dodatkowa gotówka za zabójstwo + hs Dodatkowa gotówka za podłożenie bomby Dodatkowa gotówka za rozbrojenie bomby Szansa na respawn (ustawiamy dany %) Apteczka przy spawnie gracza Granat odłamkowy przy spawnie Wabik przy spawnie Granat dymny przy spawnie Mołotow przy spawnie Granat błyskowy przy spawnie Śnieżki przy spawnie Wyrzutnie przy spawnie Bomby przylepne przy spawnie Defuser przy spawnie Zeus przy spawnie Tarcza przy spawnie Zmiana przezroczystości gracza przy spawnie (domyślnie 255) Auto BH Nieskończona amunicja w drugim magazynku Mnożnik obrażeń Mnożnik obrażeń otrzymanych od graczy Mnożnik obrażeń od upadku Przywitanie gracza Hint HUD Kolor wiadomości na hudzie Pozycja wiadomości X Y Menu z wyborem karabinu od X rund (bronie ustawiamy w pliku konfiguracyjnym) Menu z wyborem pistoletów od X rund (bronie ustawiamy w pliku konfiguracyjnym) Specjalny chat dla VIP'a (lub innej rangi vipowskiej którą stworzymy) ( /vm <wiadomosć ) Czy ranga ma być wyświetlana w liście vipów online Ilość możliwych respawnów do użycia podczas jednej rundy ( /vrespawn ) Konfiguracja Mój VIP jest konfigurowany z pliki .txt co oznacza, że można dodać więcej niż jedną rangę VIP'owską. VIP może być pod flagę lub steamid (max 25). Do innych rang nie trzeba wypisywać wszystkich opcji VIP'a i ustawiać ich, są automatycznie ustawiane na domyślne wartości. Na samej górze pliku konfiguracyjnego ustawiamy MOD_TAG oraz czy hełm ma być na pistoletówkach czy nie. UWAGA Flaga Z otrzymuję rangę VIP'a która jest na samej górze pliku! "VIPS" { "MOD_TAG" "ADEPT" // TAG Wyświetlany na czacie i w menu "brak_helmu_pistoletowka" "1" // Wyłącza możliwość kupowania hełmu podczas pistoletówki "VIP" { "flag" "o" // Flaga, którą musi mieć gracz lub STEAMID ( MAX 25 STEAMID ! ) "team" "0" // Team dla którego mają być dawane bonusy VIP'owskie 0 - CT i TT 1 - CT 2 - TT "dodatkowe_hp" "30" // Dodatkowe HP przy spawnie "hp_kill" "2" // Dodatkowe HP za killa "hp_kill_hs" "5" // Dodatkowe HP za killa z headshotem "max_hp" "145" // Maksymalne zdrowie, które może osiągnąć gracz "helm" "0" // Hełm 1/0 Tak/Nie "pancerz" "166" // Pancerz gracza ustawiany przy spawnie "grawitacja" "0.8" // Grawitacja ustawiona przy spawnie (może ulec zmianie po wejściu na drabinkę) (1.0 domyślna grawitacja) "szybkosc_poruszania" "1.1" // Szybkość poruszania się gracza ustawiona przy spawnie (1.0 domyślna prędkość) "dodatkowe_skoki" "2" // Ilość dodatkowych skoków "dodatkowa_gotowka" "1200" // Dodatkowa gotówka przy spawnie gracza "dodatkowa_gotowka_kill" "225" // Dodatkowa gotówka za zabójstwo "dodatkowa_gotowka_kill_hs" "250" // Dodatkowa gotówka za zabójstwo z headshotem "dodatkowa_gotowka_plant" "150" // Dodatkowa gotówka za podłożenie bomby "dodatkowa_gotowka_defuse" "150" // Dodatkowa gotówka za rozbrojenie bomby "szansa_na_respawn" "15.0" // % szans na odrodzenie się po śmierci "apteczki" "4" // Ilość apteczek przy spawnie gracza. "hegrenade" "1" // Hegreande przy spawnie gracza (1/0 Tak/Nie) "decoy" "1" // Decoy przy spawnie gracza (1/0 Tak/Nie) "smoke" "1" // Smoke przy spawnie gracza (1/0 Tak/Nie) "molotov" "1" // Mołotov przy spawnie gracza (1/0 Tak/Nie) "flash" "2" // Ilość flashy przy spawnie gracza (0 - brak) "sniezki" "3" // Ilość śnieżek przy spawnie gracza (0 - brak) "bumpmine" "10" // Ilość wyrzutni przy spawnie gracza (0 - brak) "breachcharge" "12" // Ilość bomb przylepnych przy spawnie gracza (0 - brak) "defuser" "1" // Defuser przy spawnie gracza (1/0 Tak/Nie (CT) ) "zeus" "2" // Czy gracz ma dostać zeusa przy spawnie? > 1 ammo w zeusie "tarcza" "1" // Czy gracz ma dostać tarczę przy spawnie? (1/0 Tak/Nie) "przezroczystosc" "255" // Przezroczystość gracza (255 - domyślna) "autobh" "1" // Czy gracz ma posiadać AutoBH? (1/0 Tak/Nie) "infinite_ammo" "1" // Czy gracz ma posiadać nielimitowany drugi magazynek? (1/0 Tak/Nie) "mnoznik_obrazen" "2.0" // Mnożnik obrażeń gracza "mnoznik_obrazen_otrzymanych" "1.0" // Mnożnik obrażeń, które otrzyma gracz od innych graczy "mnoznik_obrazen_od_upadku" "0.1" // Mnożnik obrażeń, które gracz otrzyma od upadku "przywitanie" "2" // Przywitanie gracza 0 - Brak 1 - hint 2 - HUD "przywitanie_hint_kolor" "#ff0000" // Kolor nicku gracza w przywitaniu "przywitanie_hud_kolor" "0;255;0" // Kolor wiadomości na hudzie "przywitanie_hud_xy" "0.35;0.06" // Pozycja wiadomości X Y "menu_z_karabinami" "5" // Czy ma zostać wyświetlone menu z wyborem karabinów? Liczba > 0 to ilości rund po których ma zostać wyświetlone menu "menu_z_pistoletami" "1" // Czy ma zostać wyświetlone menu z wyborem pistoletów? Liczba > 0 to ilości rund po których ma zostać wyświetlone menu "menu_karabiny" "weapon_ak47;weapon_awp;weapon_ssg08;weapon_negev" // Po prostu wpisujemy bronie MAX 32 BRONIE "menu_pistolety" "weapon_usp_silencer;weapon_deagle;weapon_p250;weapon_glock" // Po prostu wpisujemy bronie MAX 32 BRONIE "chat_vip" "1" // Czy ma być dostępny czat dla tej rangi? /vm <wiadomość> "vip_online" "1" // Czy ranga ma być pokaza w VIP Online? "respawn" "0" // Ile razy gracz może się odrodzić? /vrespawn } "Przykład STEAMID" { "flag" "STEAM_1:1:220315125" // Flaga, którą musi mieć gracz lubb STEAMID ( MAX 25 STEAMID ! ) "team" "2" // Team dla którego mają być dawane bonusy VIP'owskie 0 - CT i TT 1 - CT 2 - TT "dodatkowe_skoki" "2" // Ilość dodatkowych skoków "autobh" "1" // Czy gracz ma posiadać AutoBH? (1/0 Tak/Nie) "infinite_ammo" "1" // Czy gracz ma posiadać nielimitowany drugi magazynek? (1/0 Tak/Nie) "mnoznik_obrazen" "2.0" // Mnożnik obrażeń gracza "mnoznik_obrazen_otrzymanych" "1.0" // Mnożnik obrażeń, które otrzyma gracz od innych graczy "mnoznik_obrazen_od_upadku" "0.1" // Mnożnik obrażeń, które gracz otrzyma od upadku "przywitanie" "2" // Przywitanie gracza 0 - Brak 1 - hint 2 - HUD "przywitanie_hint_kolor" "#ff0000" // Kolor nicku gracza w przywitaniu "przywitanie_hud_kolor" "0;255;0" // Kolor wiadomości na hudzie "przywitanie_hud_xy" "0.35;0.06" // Pozycja wiadomości X Y "menu_z_karabinami" "5" // Czy ma zostać wyświetlone menu z wyborem karabinów? Liczba > 0 to ilości rund po których ma zostać wyświetlone menu "menu_z_pistoletami" "1" // Czy ma zostać wyświetlone menu z wyborem pistoletów? Liczba > 0 to ilości rund po których ma zostać wyświetlone menu "menu_karabiny" "weapon_ak47;weapon_awp;weapon_ssg08;weapon_negev" // Po prostu wpisujemy bronie MAX 16 BRONI "menu_pistolety" "weapon_usp_silencer;weapon_deagle;weapon_p250;weapon_glock" // Po prostu wpisujemy bronie MAX 16 BRONI "chat_vip" "1" // Czy ma być dostępny czat dla tej rangi? /vm <wiadomość> "vip_online" "0" // Czy ranga ma być pokaza w VIP Online? "respawn" "1" // Ile razy gracz może się odrodzić? /vrespawn } } INSTALACJA Kompilujemy plik ADEPT_VIP.sp następnie wrzucamy go do folderu /addons/sourcemod/plugins Następnie wrzucamy plik konfiguracyjny ADEPT_VIP.txt do folderu /addons/sourcemod/configs KOMENDY /reloadvip -> Przeładowuje plik konfiguracyjny /vips -> Lista graczy online z rangą VIP'owską /vm <wiadomość> -> Wysyła wiadomość do graczy z tą samą rangą Dodatkowe informacje Dodatkowe skoki + Auto BH działa, ALE nie jest to za dobrze napisane przez co najlepiej działa z jednym dodatkowym skokiem, co mam na myśli? Powiedzmy, że mamy 2 dodatkowe skoki gdy skoczymy raz i zaczniemy bhopować będzie okej, gdy skoczymy dwa razy i spróbujemy bhopować zatrzyma nas, natomiast jeżeli zaczniemy bhopować skoczymy raz i drugi raz (skończą nam się dodatkowe skoki) będziemy normalnie mogli wrócić do bhopowania. Drugą rzeczą są ArrayListy, których jak można zobaczyć jest sporo, raczej nie wpływa to za bardzo na działanie pluginu (jak tak nie jest to mnie poprawcie) skoro i tak rezerwowane jest tyle miejsca ile jest potrzebne. Jeżeli masz pomysł jak mógłbym to inaczej napisać daj znać 😉 Jeżeli jest coś czego brakuje do tego VIP'a napisz w komentarzu co można dodać 😉 ADEPT_VIP.sp ADEPT_VIP.txt
  39. 7 punktów
    Jeżeli spędziłeś już trochę czasu na programowaniu w pawnie, na pewno natknąłeś się na funkcje, które pobierają dane z innych pluginów, np. cod_get_user_class, które zwróci ID postaci, na której aktualnie gramy. Warto zauważyć, że owe informacje wychodzą bezpośrednio z silnika cod moda - następuje więc tutaj bezpośrednia wymiana informacji pomiędzy pluginami. W tym poradniku zajmiemy się po krótce tym zagadnieniem. 1. Funkcje natywne Działanie "natywów" sprowadza się do zdalnego wywołania funkcji i ewentualnego zwrócenia rezultatu: 0 - Nasz plugin posiada funkcję natywną szarego pluginu I - zlecamy wykonanie funkcji II - szary plugin wykonuje polecenie III - szary plugin zwraca otrzymany rezultat IV - rezultat trafia do naszego pluginu Teraz pokażę jak takiego natywa z szarego pluginu stworzyć. Przede wszystkim natywy dodajemy w takiej funkcji: public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) Daje nam to pewność, że załadują się one w odpowiedniej chwili. Warto wspomnieć, że natywy możemy wczytywać pojedynczo, bądź jako biblioteka - tworzyć nasze własne pliki #include. W tym poradniku skupię się tylko na tej drugiej metodzie. Musimy więc najpierw zarejestrować naszą bibliotekę: RegPluginLibrary("NaszaNazwa"); następnie dodajemy natywy w następujący sposób: CreateNative("nazwa_natywu", Funkcja_Ktora_Ma_Sie_Wywolac); na samym końcu zwracamy: return APLRes_Success; Teraz pora na Funkcja_Ktora_Ma_Sie_Wywolac. Natywy pozwalają nam również na bezproblemowe przekazywanie argumentów, jednak funkcja, o której przed chwilą wspomniałem, nie może po prostu tych argumentów przyjmować w nawiasach () - działa to w trochę inny sposób: public int Funkcja_Ktora_Ma_Sie_Wykonac(Handle plugin, int numParams) { int liczba = GetNativeCell(1); return liczba * 2; } po pierwsze, argumenty muszą być takie, jak wyżej - Handle plugin (uchwyt to NASZEGO pluginu), a także numParams (ilość parametrów, które przekazaliśmy) Pobieranie argumentów odbywa się poprzez specjalne funkcje GetNative___ (polecam po prostu wpisać sobie "getnative" a także "setnative" w dokumentacji). Każdorazowo pierwszy argument GetNative__ to numer argumentu z naszego wywołania (wyjątkowo numerujemy tutaj od 1!) W przykładzie powyżej założyłem, że przekazany zostanie jedynie int, który zostanie przemnożony przez 2 i zwrócony. Przykładowe zastosowanie: Pamiętajmy jednak, że ciągle nie stworzyliśmy biblioteki GoCode! Będzie ona wyglądać mniej więcej tak: Tak przygotowany plik możemy zapisać jako GoCode.inc i wrzucić do naszego folderu include w kompilatorze. Koniec ? 2. Forwardy (coming soon)
  40. 7 punktów
    DataPacki Przeważnie podczas tworzenia funkcji definiujemy pożądaną liczbę parametrów, którą chcemy użyć. Przykład: int Mnozenie(int a, int b) { return a * b; } /////////////// void JakasFunkcja() { PrintToChatAll("5x6 = %d", Mnozenie(5,6)); } Aby zrobić tutaj użytek z funkcji Mnozenie() konieczne było przekazanie dwóch argumentów. Niestety, w niektórych sytuacjach nie mamy komfortu przekazywania dowolnej ilości argumentów - jesteśmy ograniczeni tylko do...jednego! Dotyczy to chociażby asynchronicznych zapytać SQL lub timerów. Przykład: void JakasFunkcja(int client) { int a = 5; int b = 6; CreateTimer(10.0, PomnozCosPozniej, /*TUTAJ TYLKO JEDEN ARGUMENT!*/); } public Action PomnozCosPozniej(Handle timer, any data) { /// co tu zrobic ?! } Gdybyśmy chcieli wykonać operację mnożenia w tym przypadku, niezbędne jest przekazanie dwóch zmiennych. Co robić w takiej sytuacji? Z pomocą przychodzą nam DataPacki! Umożliwiają nam one "upakowanie" dowolnej liczby zmiennych o dowolnym typie do jednego ciągu danych. Cały proces zaczyna się od stworzenia uchwytu do DataPacka: DataPack data = new DataPack(); jesteśmy gotowi do załadowania go danymi. Do tego celu wykorzystuje się kolejno WriteCell, WriteFloat, WriteFunction, WriteString W naszym przykładzie poza dwiema zmiennymi przekażemy dodatkowo komunikat do wyświetlenia, aby pokazać jak posługiwać się ciągami znaków. Nasza funkcja będzie teraz wyglądać tak: void JakasFunkcja(int client) { char helloString[128]; Format(helloString, sizeof(helloString), "Siemanko %N!", client); DataPack data = new DataPack(); data.WriteCell(5); data.WriteString(helloString); data.WriteCell(6); CreateTimer(10.0, PomnozCosPozniej, data); } Celowo umieściłem stringa pomiędzy dwiema liczbami, aby pokazać, że odczyt jest odrobinę bardziej skomplikowany niż zapis. Po pierwsze, każdy DataPack posiada swój specjalny wskaźnik, który pokazuje w którym miejscu ma być przeprowadzany odczyt/zapis. Przeanalizujmy proces zapisu informacji w naszej funkcji JakasFunkcja(int client). Po stworzeniu DataPacka mamy pustą strukturę i wskaźnik znajdujący się na początku: [|] Znak '|' to właśnie nasz wskaźnik Po wywołaniu żądania umieszczenia piątki, proces zaczął się w miejscu gdzie stał nasz wskaźnik - czyli na samym początku: [5|] Po dodaniu inta, wskaźnik przesunął się (troche jak wskaźnik podczas pisania na klawiaturze) Kolejny w kolejce jest string: [5string|] I ostatnia już wartość - 6: [5string6|] W tym miejscu mamy już przygotowanego do wysyłki DataPacka. Zauważmy jednak, że nasz wskaźnik nie zmienił swojej pozycji - jest cały czas ustawiony na końcu struktury. Czy domyślacie się, jak wyglądałby odczyt tych danych? Bez przesunięcia wskaźnika na początek pliku ten proces jest niemożliwy... Na szczęście, istnieje operacja, która może tego dokonać. Nazywa się ona Reset: // zauważmy, że drugi argument funkcji zmienił się na nasz DataPack :) public Action PomnozCosPozniej(Handle timer, DataPack data) { data.Reset(); } Od tego momentu struktura DataPacka wygląda tak: [|5string6] Oznacza to, że jesteśmy gotowi do odczytu ? Istnieje jednak jeszcze jeden haczyk. Wspomniałem wcześniej, że dane w DataPacku przyjmują forme ciągu danych. Oznacza to, że SourceMod widzi je jako swoisty strumień. Właśnie do nas należy zadanie zapanowania nad tym haosem. Do odczytywania danych stosujemy kolejno ReadCell, ReadFloat, ReadFunction i ReadString. W naszym DataPacku nie możemy zacząć wyciągania od np. stringa - wszystko musimy wykonywać w takiej samej kolejności, w jakiej wkładaliśmy dane! Na pierwszy ogień pójdzie więc 5, następnie komunikat, a na samym końcu - 6. A więc pierwszą wartością jest int. Korzystamy z ReadCell: // zauważmy, że drugi argument funkcji zmienił się na nasz DataPack :) public Action PomnozCosPozniej(Handle timer, DataPack data) { data.Reset(); int a = data.ReadCell(); } // Aktualny stan DataPacka: [5|string6] Przyszła pora na stringa. W naszym przypadku nasz łańcuch składa się z 128 znaków i dokładnie tyle zapisaliśmy w DataPacku! Pamiętajmy więc o przygotowaniu odpowiednio dużej tablicy: char helloString[256]; // wielkość tablicy do której zapisujemy może się różnić - ważne, abyśmy pamiętali ile znaków zapisaliśmy WCZEŚNIEJ! data.ReadString(helloString, sizeof(helloString)); I na sam koniec ostatnia liczba: int b = data.ReadCell(); Gotowe! Wszystkie dane zostały pobrane prawidłowo. Nasz efekt końcowy: void JakasFunkcja(int client) { char helloString[128]; Format(helloString, sizeof(helloString), "Siemanko %N!", client); DataPack data = new DataPack(); data.WriteCell(5); data.WriteString(helloString); data.WriteCell(6); CreateTimer(10.0, PomnozCosPozniej, data); } public Action PomnozCosPozniej(Handle timer, DataPack data) { char helloString[256]; data.Reset(); int a = data.ReadCell(); data.ReadString(helloString, sizeof(helloString)); int b = data.ReadCell(); PrintToChatAll("Komunikat: %s", helloString); PrintToChatAll("%d x %d = %d", a, b, a*b); } // stan DataPacka: [5string6|] Oczywiście w razie pojawienia się pytań bądź wątpliwości zapraszam do dyskusji pod spodem ? PS: suplementem do tego materiału jest napisany przez @Vasto_Lorde poradnik o timerach:
  41. 7 punktów
    O Pluginie: Plugin zabiera na koniec rundy nóż gracza aby uniknąć sytuacji opisanej w tym temacie: Kod: Instalacja: Plik .smx wrzucamy do: addons/sourcemod/plugins/ Plik .sp wrzucamy do: addons/sourcemod/scripting/ Download: KnifeFix.smx KnifeFix.sp Include potrzebny do kompilacji pliku: smlib.inc
  42. 7 punktów
    Achivements CS:GO Plugin na osiągnięcia na serwerze. Osiągnięcia zdobywane za kille, asysty, wygrane rundy itd. Gracze mogą zdobywać osiągnięcia i używać tagów osiągnięć. Jest to pierwszy plugin udostępniony publicznie przeze mnie,mam nadzieję, że wam się przyda. Każda opinia będzie dla mnie ważna. Instalacja: Wszystko zawarte w instrukcji w paczce. Wymagania: Sourcemod 1.8-10 Baza danych MySQL Reszta wymaganych plików w paczce. Komendy: !achievements - Główne menu !stats - Nasze statystki !tag - Menu tagów CVar'y "achievements_players", "2", "How many players for getting achievement?" "achievements_kills", "20", "How many kills for achievement?" "achievements_assists", "5", "How many assists for achievement?" "achivements_headshots", "5", "How many headshots for achievement?" "achievements_win", "10", "How many rounds wins for achievement?" "achievements_lose", "10", "How many rounds lost for achievement?" "achievements_plant", "5", "How many bomb plants for achievement?" "achievements_defuse", "5", "How many bomb defuses for achievement?" Achievements 1.0.rar
  43. 7 punktów
    Co tu dużo pisać? Plugin dodaje możliwość "lepszego" powiadamiania graczy o przeładowaniu mapy/update. Może komuś się przyda 👮‍♂️ Działanie: P.S. Literówka w overlayu jest poprawiona. Dobranocka.rar
  44. 7 punktów
    Siemka postanowiłem, że napiszę mały "poradniczek" jak zrobić aby w menu admina pokazywały się tylko mapy które są podane w maplist.txt 1. Wchodzimy w csgo/addons/sourcemod/configs/ i szukamy pliku maplists.cfg 2. znajdujemy 30 linijke i w "file" zmieniamy jedynie końcówkę 3. ja zmieniam w taki sposób np. w pliku csgo.txt mam dodaną mapę de_mirage i wygląda to tak
  45. 7 punktów
    Spis errorlogów i co one oznaczają? Poniżej będzie znajdował się spis wszystkich errorlogów, ich polskie tłumaczenie oraz jak właściwie zabrać się za rozwiązanie problemów, które ukazują. Oryginał znalazłem tutaj. Zachęcam do pomocy w tłumaczeniu, temat jest długi jeśli otworzy się spoiler, więc proszę o cierpliwość jeśli będziecie przewijać w dół ? Legenda Jak używać tego tematu? Jak pomóc z uzupełnianiem błędów? Spis errorów 001-182 183-196 200-240 Hej! Uwaga! Jeśli nadal nie jesteś pewny co oznacza pewien błąd, napisz osobny temat w dziale Pytania na temat programowania z prośbą o dogłębne wytłumaczenie problemu! Na pewno pomożemy!
  46. 7 punktów
    int a = 5; if (!a) { // akcja dla a = 0 } else if (a == 1) { // akcja dla a = 1 } else if (a == 2) { // akcja dla a = 2 } else { // akcja dla a nie będącego 0, 1 ani 2 } Tak długi i nadmiarowy kod można zastąpić używając funkcji switch: int a = 5; switch(a) { case 0: { // akcja dla a = 0; } case 1: { // akcja dla a = 1; } case 2: { // akcja dla = 2; } default: { // akcja dla a innego niż 0, 1 i 2 } } Skrócony tryb warunkowy warunek ? co robić, gdy warunek==true : co robić, gdy warunek==false; przydatny, gdy mamy do czynienia z sytuacją if-else. Możemy wówczas ograniczyć się do formuły podanej wyżej. Przykład zastosowania: int hpGracza = 50; SetEntityHealth(client, hpGracza > 40 ? 100 : 70); Zasada działania: jeżeli HP gracza jest większe niż 40, zmień zdrowie na 100. W przeciwnym razie (HP mniejsze bądź równe 40) - 70.
  47. 7 punktów
    Witam, jako, że dostaje sporo informacji odnośnie tego tematu, przydało by się do niego odwołać.. Zacznijmy więc od @Avgariat, niewątpliwie rację muszę przyznać, nie przykładałem się do tego pluginu, był on pisany w czasach, kiedy z SM zaczynalem, leżał on sporo czasu, aż wziąłem się za niego na potrzeby sieci. Powiedzenie, że złamałem w nim niemal wszystkie zasady programowania.. Totalnie przegięte.. To prawda, sposób identyfikacji graczy to totalna klęska, dlatego też wszedł refactor mający na celu poprawę tego błędu, refactor dalej leży na dysku w strzępkach kodu, lecz podkreślam nikt nie zgłosił mi problemu z działaniem owego pluginu.. Zachowując hierarchię, następnym postem będzie post @beken1996, czyli człowiek z zerowym doświadczeniem o SM i zarządzaniu serwerami, nie piszę tego mając na celu Cię urazić oczywiście, lecz wróćmy do początków naszej współpracy, gdzie poświęciłem wiele godzin abyś potrafił zainstalować paczkę, czy ogarnąć proste sprawy techniczne, czy moje pluginy trzeba edytować..? Co edytowałeś? Jeśli chodzi o jackpot, który jest klęską w postaci identyfikacji graczy, rozumiem, lecz nie dostałem żadnej informacji o owym błędzie, reszta? Czyli system klas, expa, sklepu, monet, timer'a, kolejki i innych dodatków? Chodzi o podmianę STEAM_ID_ALLOWED, pozwalająca na pozyskanie uprawnień do edycji waluty graczy w sklepie, którą Ci nakazałem, lecz potem musiałem to zrobić sam? Mówisz o kontakcie.. Paczkę kupiłeś ode mnie spory czas temu, pojawiając się jak sądzę nie dawno z chęcią otworzenia serwera, wymagałeś mojej obecności gdzie na steam nie byłem od długiego czasu.. Jak mówisz, chciałeś uzyskać dostęp do repo, na którym udzielam supportu, oraz wrzucam ewentualne poprawki/zmiany, lecz wersja którą zakupiłeś różniła się od tej na repo, a ja świadomości o Twojej chęci dołączenia do niego nie miałem.. Pomogłem Ci nie raz, nie dwa, i wypraszam sobie mówienie, że mam "wyjebane", bo większość spraw ogarniałem od razu, od grudnia ubiegłego roku jednak nie ma mnie praktycznie wcale, dlatego też nie ma co się dziwić, że kontakt jest utrudniony, i nie ukrywam tutaj, że dałem ciała, ale nie jestem w stanie ogarniać wszystkiego jeśli mnie na rynku nie ma już od sporego czasu i nie zajmuję się SM, a sam mam życie prywatne, problemy zdrowotne i zawodowe, które muszę ogarnąć. Odnośnie systemu Party oraz klas.. Były to dodatki, i od razu na wstępie to zaznaczyłem, były pomocą dla Ciebie, nie skryptem który miał działać, ponieważ były to źródła testowe.. Jeśli chodzi o wartość paczki, nie wiem czy jest Wam dane to oceniać, myślę, że ocenić to mogła by dopiero osoba, która napisała by kody o podobnej funkcjonalności, paczka jest warta o wiele więcej bazując na tym jak większość pseudo-programistów w community sourcemod się ceni.. Najczęściej jednak ludzie byli w szoku, że tak mało biorę za pluginy, lecz nie traciły one na jakości kodu w żaden sposób, a mase prac pseudo-programistów z owego community musiałem naprawiać bo klienci mieli z tym urwanie głowy.. Więc zamiast się wywyższać, stanął bym do tego obiektywnie patrząc na ogół pracy, widząc kod, realnie.. Pozdrowionka, nox!
  48. 7 punktów
    Opis: Dodaje jeden respawn na rundę dla vipa [!respawn] pozwala vipowi zmienić grawitację [!g] oraz przywitanie przy wejściu VIP`a na serwer. VIP jest przygotowany pod -> KOD: ADEPT_Deathrun_VIP.sp
  49. 7 punktów
    Jak zauważyliście, na forum została dodana nowa ranga - Little Hero Będą ją otrzymywały osoby, które aktywnie udzielają się na forum i pomagają innym użytkownikom i są na dobrej drodze do zostania Supportem ? W odróżnieniu od zwykłego użytkownika, Little Hero posiada następujące przywileje: Możliwość edytowania swoich postów Możliwość dania 20 reakcji (użytkownicy mają 10 reakcji) Możliwość blokowania swoich tematów wgląd do ukrytego działu dla supportów z możliwością komentowania (ale nie zakładania tematów) Rangę otrzymało 3 userów: @Master @Yamakashi @szogun Gratuluję i życzę dalszych sukcesów w naszej społeczności ?
  50. 7 punktów
    Zadania czasowe w Sourcemod 1. Wprowadzenie SourceMod oferuje nam bardzo wygodny system Timerów. Te zadania czasowe obsługują uruchomienie danej funkcji z konkretnymi parametrami w odpowiednim czasie. Takie działania mogą być przydatne gdy na przykład odblokowujemy użycie granatów jakiś czas po rozpoczęciu rundy lub wyświetlamy HUD (wiadomość na ekranie gracza) która ma się stale wyświetlać lecz jego zawartość musimy ciągle odświeżać. 2. CreateTimer - Teoria Jest to funkcja tworząca Timer i ustalająca jaka funkcja ma być uruchomiona po jakim czasie. Jej opis znajduje się tutaj https://go-code.pl/dokumentacja-sourcemod/timers/CreateTimer Składnia: native Handle CreateTimer(float interval, Timer func, any data=INVALID_HANDLE, int flags=0); Handle - w tym przypadku oznacza, że funkcja zwróci nam jakiś uchwyt (uchwyt = Handle). Konkretniej, CreateTimer zwraca uchwyt do właśnie stworzonego Timera. float interval - czas w sekundach do wywołania (uruchomienia) danej funkcji. Są to wartości float, czyli wartości zmiennoprzecinkowe. O ile dobrze kojarzę, minimalną wartość jaką można tu wpisać jest 0.1. Timer func - nazwa funkcji która ma zostać uruchomiona (wywołana) po podanym czasie. any data - jakikolwiek parametr jaki chcemy przekazać funkcji którą wywołamy, by mogła z niej korzystać. Nie musimy ustawiać tego parametru i domyślnie będzie on ustawiony na INVALID_HANDLE, czyli brak przekazywanego parametru. int flags - opcjonalne flagi które możemy nadać naszemu Timerowi które zmienią domyślne działanie Timera. Domyślnie ustawione na 0, czyli TImer działa domyślnie, tak jak jest to opisane w dokumentacji. 2.1. CreateTimer - Napisanie tego w pluginie Załóżmy, że mamy przykładowy plugin: Stworzony Timer pod komendą "sm_stworz" wykona się dokładnie sekundę po wpisaniu jej w konsolę. Zauważmy, że jako trzeci parametr w CreateTimer przekazujemy ID gracza (client). Dzięki temu FunkcjaKtoraSieWywola może go dowolnie używać. Co z flagami? (int flags) Aktualnie dokumentacja opisuje trzy działające flagi, które zmieniają / modyfikują działanie Timera. TIMER_REPEAT - Sprawia, że stworzony Timer działa w pętli. (po wywołaniu Timerowej funkcji, Timer od początku odlicza sekundy i powtarza cały proces) TIMER_FLAG_NO_MAPCHANGE - Sprawia, że Timer nie będzie działać po zmianie mapy. Tak, jeśli plugin utworzy CreateTimer bez tej flagi i z takim czasem że Timer nie zdąży się wykonać przed zmianą mapy, to wykona się po jej zmianie zgodnie ze swoim odliczaniem! TIMER_DATA_HNDL_CLOSE - Sprawia, że uchwyt (Handle) wpisany jako trzeci parametr jest automatycznie zamykany po zakończeniu wykonywania funkcji. O tym trochę dokładniej w dalszej części poradnika Dlatego możemy teraz stworzyć inną wersję naszego pluginu, który będzie co sekundę pisał na czacie kto użył komendy: Aby połączyć flagi dla danego CreateTimer, należy wstawić między nie znak |. Przykład: CreateTimer(1.0, FunkcjaKtoraSieWywola, GetClientUserId(client), TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE|TIMER_DATA_HNDL_CLOSE); 3. TriggerTimer - Teoria Jest to funkcja, która przedwcześnie wywołuje Timer, czyli wymusza aktywację Timera. Opis znajduje się tutaj: https://go-code.pl/dokumentacja-sourcemod/timers/TriggerTimer Składnia: native void TriggerTimer(Handle timer, bool reset=false); void - Oznacza, że ta funkcja nic nie zwraca Handle timer - Uchwyt danego Timera który chcemy uruchomić bool reset - Jeśli true, to czas Timera zostanie zresetowany i będzie musiał odczekać pełny czas (ustawiony w CreateTimer) by ponownie się samodzielnie uruchomić. Ten parametr jest opcjonalny. 3.1. TriggerTimer - Napisanie tego w pluginie Możemy napisać sobie przykładowy plugin Zauważmy, że do skorzystania z funkcji TriggerTimer potrzebowaliśmy uchwytu naszego Timeru. Dlatego została stworzona zmienna typu Handle o nazwie UchwytNaszegoTimeru. Co więcej, przy opisywaniu CreateTimer napisałem, że funkcja zwraca uchwyt do stworzonego Timera, dlatego można ten uchwyt przypisać jakiejś zmiennej 4. KillTimer - Teoria Usuwa Timer bez jego wywołania. Przydatne jeśli pojawił się jakiś warunek (na przykład jeśli gracz zginął i nie potrzeba mu już wyświetlać wiadomości na HUD), który sprawia, że Timer nie jest już potrzebny. Pełny opis tutaj https://go-code.pl/dokumentacja-sourcemod/timers/KillTimer Składnia: native void KillTimer(Handle timer, bool autoClose=false); void - Oznacza, że ta funkcja nic nie zwraca Handle timer - Uchwyt danego Timera który chcemy usunąć bool autoClose - Jeśli ustawione na true, to dane przekazane do Timera zostaną zamknięte jeśli w CreateTimer nie dodało się flagi TIMER_DATA_HNDL_CLOSE 4.1. KillTimer - Napisanie tego w pluginie Mamy przykładowy plugin Zauważmy ciekawą rzecz, jeśli użyjemy komendy sm_usun dwukrotnie to drugie jej użycie spowoduje błąd ponieważ UchwytNaszegoTimeru wynosi INVALID_HANDLE. Dzieje się tak ponieważ funkcja KillTimer usuwa dany Timer kompletnie i ustawia wartość zmiennej przetrzymującej właśnie na INVALID_HANDLE. Co za tym idzie, zgodnie z dokumentacją, funkcja KillTimer nie radzi sobie w przypadku, gdy podawany do funkcji uchwyt nie jest prawidłowy i po prostu wyrzuca nam błąd do konsoli / logów serwera. 5. Ale tato, co jeśli bym chciał przekazać do Timer'a więcej niż jedną zmienną? Możemy to zrobić na dwa sposoby. Prymitywny i nieładny lub elegancki i zgodny z zasadami dobrego programowania. Ten pierwszy osiąga się za pomocą tworzenia zmiennych globalnych (takich które działają w każdym kawałku kodu pluginu). Przed CreateTimer przypisujemy do zmiennych globalnych jakieś wartości potrzebne nam do użycia w Timerze. A gdy Timer się wywoła, używamy właśnie tych zmiennych globalnych. Barbarzyńsko wręcz. Natomiast drugi sposób omówię trochę dokładniej. Będziemy musieli zagłębić się w plik datapack.inc. Datapack to uporządkowany zestaw obiektów, który jest przekształcony do postaci szeregowej, czyli jednego strumienia bajtów. Dzięki temu zmienne które chcemy przekazać Timerowi możemy umieścić w jednym Datapacku i umieścić jako trzeci parametr funkcji CreateTimer, przekazując tym samym ten Datapack do funkcji którą ten Timer wywoła. Brzmi prosto, natomiast trzeba się zapoznać z kodem żeby w pełni zrozumieć działanie Datapacków. Oto przykładowy kod: Trzeba zaznaczyć, że odczytywanie danych z Datapacku MUSI się odbywać w kolejności w jakiej zostały do tego Datapacku zapisane. Co do CloseHandle lub TIMER_DATA_HNDL_CLOSE, nie ma różnicy jaka metoda zostanie użyta by usunąć uchwyt nazwany w kodzie 'data'. Ważne jest natomiast by ten uchwyt został usunięty. Nie sprzątanie po sobie utworzonych uchwytów może skutkować nieoczekiwanymi crashami serwera. Bibliografia Głównie wiedzę czerpałem z własnego doświadczenia (jak również pluginów które napisałem), ale nie omieszkałem zajrzeć na strony https://wiki.alliedmods.net/SourcePawn_Basics_-_Handles,_DataPacks,_and_Timers oraz https://pl.wikipedia.org/wiki/Serializacja by przypomnieć sobie niektóre rzeczy. Nie zapominajmy też o naszej dokumentacji https://go-code.pl/dokumentacja-sourcemod/ *Uprasza się o nie kopiowanie poradnika bez wcześniejszego zapytania autora o zgodę
Ten Ranking ustawiony jest na Warszawa/GMT+01:00
×
×
  • Dodaj nową pozycję...