Skocz do zawartości

Nowy szablon forum

mygo.pl

Stworzyliśmy dla Was nowy wygląd forum. Z pewnością znajdziesz rzeczy, które wg Ciebie mogą zostać zmienione - wspomnij o tym w specjalnym wątku.

Czytaj więcej

Jak założyć własną sieć

serwerów CS

Zastanawiasz się nad prowadzeniem własnej sieci serwerów? Przeczytaj podstawowe informacje, na które należy zwrócić uwagę, przy takim projekcie.

Czytaj więcej

Tworzymy spis sieci

dodaj swoją

Dodaj sieć do której należysz, pozwoli to na promocję i budowę ogólnopolskiej bazy sieci CS.

Czytaj więcej

SUPER TIMOR

Zasłużony
  • Postów

    1007
  • Dołączył

  • Ostatnia wizyta

  • Wygrane w rankingu

    73

Odpowiedzi opublikowane przez SUPER TIMOR

  1. 6 godzin temu, Roberrt napisał:

    A ja tu wasze teorię obalę, moim skromnym zdaniem jednym z początkowych serwerów powinny być m.in. only mirage, only awp lub deathrun, serwery nie jest te za trudno rozkręcić (jeśli posiadają w sobie jakiś efekt WOW) a zastrzyk gotówki aby nie inwestować dużo ze swoich pieniędzy na pewno się przyda. Z autopsji mogę powiedzieć że te dwa mody potrafią utrzymać całą sieć serwerów jeśli są zarządzane przez *dobrych* ludzi.

    Nie obaliłeś teorii, ponieważ nie przedstawiłeś żadnych konkretnych kontrargumentów, a jedynie swoje zdanie na ten temat ??? 

     

    Ja uważam, że pierwszy serwer powinien być wymagający w pewien sposób. Chodzi o to, żeby przy jego tworzeniu nabrać pewnego rodzaju wprawy, mierzyć się z trudnościami i problemami, którym trzeba stawiać czoła.

    Ja zaczynałem swoją przygodę z serwerem, na którym był CodMod i nie żałuję. Tę samą drogę również polecam ?

    • Super! 1
  2. 1 godzinę temu, Umino napisał:

    Aaaa i sprawdź, czy dobrze wpisałeś token glst, czy jak to się nazywa.

    Token nie ma nic wspólnego z restartami serwera. W przypadku, gdyby był niepoprawny z serwerem połączyć by mogli się tylko klienci z wewnętrznej sieci lokalnej. 

     

    Godzinę temu, Zorix napisał:

    addouns

    addons*, i tak - to jedno z wielu rozwiązań.

    Na początek polecam standardowo update SM+MM, ew. Ptah/steamworks jeśli używasz changera tokenów od Adiego i WS/knife/gloves etc

  3. Już piszę Ci przykład o który prosiłeś. ? Edytuję ten post i Cię oznaczę ? 

     

     

    Spoiler
    
    /////// Plugin_Stop
    int ilosc_wyslanych_printow; // robie inta globalnie
    
    public void OnPluginStart()
    {
    		ilosc_wyslanych_printow = 0; // do stworzonego wyzej inta przypisuje wartosc 0
    		CreateTimer(0.1, FunkcjaX, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); // tworze powtarzajacy sie co 0.1s timer, ktory odpala FunkcjaX
    }
    public Action FunkcjaX(Handle timer, any server) // funkcja odpalana przez timer
    {
    	if(ilosc_wyslanych_printow <= 10) // sprawdzam, czy wartosc inta ilosc_wyslanych_printow jest mniejsza, badz rowna 10
    	{ // jesli jest
    		PrintToChatAll("BlaBlaBla"); // leci sobie print
    		ilosc_wyslanych_printow ++; // dodajemy +1 do inta
    	}
    	else // jesli nie jest
    		return Plugin_Stop; // timer zostanie zatrzymany
    		
    	return Plugin_Continue; // funkcja sobie leci dalej, timer się powtórzy, ze względu na flagę "TIMER REPEAT"
    }
    //// Plugin_Continue & Plugin_Changed
    
    public void OnClientPutInServer(int client) // przy wejsciu gracza
    {
    	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); // podpinam go do funkcji OnTakeDamage
    }
    public void OnClientDisconnect(int client) // przy wyjsciu gracza
    {
    	SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage); // odpinam go od tej funkcji
    }
    
    public Action OnTakeDamage(int client, int &attacker, int &inflictor, float &damage, int &damagetype) // funkcja do ktorej podpielismy graczy przy wejsciu
    {
    /// PLUGIN_CONTINUE	
    	if(!IsValidClient(attacker)) // sprawdzam czy gracz jest prawidlowy - jesli nie jest
    		return Plugin_Continue; // to funkcja przechodzi do końca omijając wszystko po drodze
    
    //// PLUGIN_CHANGED
    	if(GetClientTeam(client) == GetClientTeam(attacker)) // sprawdzam, czy gracz zadajacy i otrzymujacy obrazenia sa z tego samego teamu
    	{// jesli sa, to zalozmy ze mamy friendlyfire 1 i chce zwiekszyc obrazenia o 50
    		damage = damage + 50.0;	 // zwiekszam damage, ktory przyszedl jako input(wejscie) do tej funkcji z silnika (patrz argumenty funkcji)
    		return Plugin_Changed; // koncze funkcje zwracajac do silnika zmieniona wartosc "damage"		
    	} 
    
    	return Plugin_Continue;
    }
    
    // PLUGIN_HANDLED
    public void OnPluginStart()
    {
    	RegConsoleCmd("sm_komenda", Komenda); // tworze komende
    }
    
    public Action Komenda(int client, int args) 
    {
    	if(GetUserFlagBits(client) & ADMFLAG_RESERVATION)// no sprawdzam sobie czy gracz ma flage "a" przykladowo
    		return Plugin_Handled; // nie pokaze sie na czacie komenda, ktorej uzyl gracz jesli ma flage "a", i dalszy przebieg tej funkcji zostanie zablokowany tutaj, i w kazdym pluginie uzywajacym tej funkcji
    	
    	if(GetUserFlagBits(client) & ADMFLAG_CUSTOM1)// w innym przypadku robie sobie ifa, ktory sprawdza czy ma flage "o"
    		return Plugin_Continue; // pokaze sie na czacie komenda, ktorej uzyl gracz jesli ma flage "o", ale dalszy przebieg tej funkcji zostanie zablokowany
    	
    	return Plugin_Continue;
    }

     

     @Ktzp

    • Super! 1
  4. Dobrze zostało to opisane w tym temacie, przez użytkownika Greyscale.


    Plugin_Continue - Pozwala funkcji iść dalej normalnie, jak powinna z założeń
    Plugin_Handled - Zatrzymuje dalszy proces danej funkcji.
    Plugin_Changed - Zwraca zmodyfikowane parametry do silnika.
    Plugin_Stop - Zatrzymuje nazwijmy to "łańcuch funkcji", i rzeczywiście głównie używane w timerach ? 

     

    @Ktzp nadal nie rozumiesz? ?

    • Super! 1
    • Przykro mi 1
  5. W logach, które wysłałeś nie widzę nic nadzwyczajnego. Mam jednak podstawy, by pomyśleć że po ludzku coś zepsułeś podczas konfiguracji serwera. Ominąłeś -insecure, a mowa o tym była nawet nie w połowie poradnika. Proponuję, abyś krok po kroku, minuta po minucie skonfigurował ten serwer jeszcze raz, od zera. Innych pomysłów nie mam, wybacz!

  6. Ah, no tak. Umknęło mi coś, co jest dość istotne w tym temacie, wybacz ?

    Osobiście mam kompletnie zerowe doświadczenie w stawianiu serwerów lokalnych, w zasadzie nigdy tego nie robiłem. Nie sądzę jednak, że różnica jest diametralna w procesie konfigurowania takiego serwera.

    Zalecam Ci jednak w przypadku braku innych użytkowników, którzy będą w stanie Ci pomóc, abyś obejrzał poradnik @MAGNET jak postawić taki serwer. Może coś przeoczyłeś?

    W zasadzie jeśli masz tam sourcemod'a, to spróbuj w pierwszej kolejności zmienić nazwę folderu addons/sourcemod/plugins na np plugins1 i zrestartuj serwer. Jeśli nadal to samo - obejrzyj poradnik.

     

     

  7. @proxenek na przyszłość staraj się używać spoilerów (ikona oka w pasku narzędzi edytora tekstu). Tak długiego posta nie dało się czytać.

     

     

    // Najprawdopodobniej wyskakiwał Ci komunikat mówiący o próbie połączenia na serwer, który dopuszcza tylko klientów z sieci lokalnej. Spróbuj dodać convara sv_setsteamaccount i użyj tokena stąd https://steamcommunity.com/dev/managegameservers?l=polish. Kod dla CS:GO to 730. 

    Pamiętaj, że bany dla tokenów mogą wrócić w dowolnej chwili, więc jeśli nie mylę się i to jest solucją Twojego problemu - polecam skorzystać z usług firm, które zajmują się sprzedażą taki tokenów w sposób automatyczny, np csgotokens.com.

  8. Trudny orzech do rozgryzienia ? 

    Myślę, że od strony serwera zawsze będzie się to opierało na pluginie, który działa jak FPVMI. To są smaczki typowo cs'owe, podejrzewam że Francisco metodą prób i błędów trochę czasu się nagłowił zanim do tego doszedł ? Tak czy siak, uważam że solucja problemu jako gruntowne omówienie FPVMI będzie OK, zgadzasz się ze mną?

    Sam bym raczej nie wpadł na to od zera, żeby w ten sposób zmieniać ten model, to jest zabawa na offsetach ? 

    • Super! 1
  9. Jak umieścić tłumaczenie w pluginie, jak doprowadzić do tego, by plugin wczytał nam plik z tłumaczeniem, który mu przygotujemy?

    Jak zakodować różne komunikaty, z różnymi zmiennymi?

    Całość omówimy na przykładzie pluginu, który losuje dwie osoby na mapkę i daje im flagę "a".

     

    Spoiler
    
    #include <sourcemod>
    
    #pragma newdecls required
    
    #define PREFIX "\x02★Darmowy VIP★\x01" // prefix, który będzie wyświetlany przed wiadomościami tekstowymi - \x01 i \x02 odpowiadają za kolory
    
    int iVipID[2]; // tablica, w której będziemy przechowywać dwa indeksy graczy, którym należy się VIP
    int iVIPSID[2]; // tablica, w której będziemy przechowywać SID tych dwóch graczy
    
    bool rozdano_vip = false; // zmienna typu boolean, która będzie służyła do określenia, czy losowanie na danej mapie już nastąpiło
    
    public Plugin myinfo =
    {
    	name = "freeVIP",
    	author = "SUPER TIMOR",
    	description = "Darmowy vip dla 2 osób na mapę",
    	version = "1.0.0",
    	url = "http://steamcommunity.com/id/bonkwszlaufrocku"
    };
    public void OnMapStart() // łapiemy funkcję wywoływaną przy zmianie mapy
    {
    	CreateTimer(20.0, VIP1, TIMER_FLAG_NO_MAPCHANGE); // odpalamy timer, który za 20 sekund wywoła funkcję VIP1. Flaga TIMER_FLAG_NO_MAPCHANGE służy do zatrzymania timera, w przypadku gdyby mapa została zmieniona (np przez admina, który przez przypadek załadował inną mapę, niż chciał)
    	rozdano_vip = false; // nie rozdaliśmy jeszcze VIP'ów, więc ustawiamy zmienną na fałsz
    	for (int i = 0; i < 2; i++) // pętla, w której każdej "szufladce" tablicy nadamy wartość 0, czyli po prostu resetujemy ID klientów z darmowymi VIP'ami
    	{
    		iVipID[i] = 0; // o właśnie tutaj to robimy
    		iVIPSID[i] = 0; // yeah   
    	}
    }
    public void OnClientPutInServer(int client) // gdy gracz wejdzie na serwer..
    {
    	if(!IsValidClient(client) || !rozdano_vip) // i nie rozdano VIP'a, lub gracz jest nieprawidłowy (patrz stock na samym dole)
    		return; // no to cofamy dziada, nie możemy pozwolić sobie na dalszy przebieg funkcji
    		
    	for (int i = 0; i < 2; i++) // ale jeśli sytuacja wygląda inaczej - gracz jest prawidłowy, a VIP'y już są rozdane
    	{
    		if(iVIPSID[i] == GetSteamAccountID(client)) // sprawdzamy, czy SID któregoś z darmowych VIPów pokrywa się z ID klienta, który wchodzi na serwer
    			AddUserFlags(client, Admin_Reservation); // i dodaję mu flagę "a" jeśli tak - flagi są rozpisane tutaj : https://sm.alliedmods.net/new-api/admin/AdminFlag			
    	}	
    }
    public Action VIP1(Handle timer, any client) // funkcja, którą odpalaliśmy timerem na początku mapy, pamiętasz? :) 
    {
    	if(rozdano_vip) // jeśli jakimś cudem rozdano już VIP'y, a funkcja się odpaliła
    		return Plugin_Stop; // no to basta dziadu
    		
    	int gracze = GetAllPlayers(); // ale jeśli nie, to używając stocka poniżej pobieramy ilość graczy bez VIP'a na serwerze
    	if(gracze < 2) // jeśli jest ich mniej niż 2
    	{
    		if(!rozdano_vip) // i jeśli nadal nie rozdano VIP'ów
    		{
    			PrintToChatAll("%s Losowanie 2 darmowych VIP'ów nie może się teraz odbyć. Próba zostanie ponowiona za 20 sekund!", PREFIX); // powiadamiamy
    			CreateTimer(20.0, VIP1, TIMER_FLAG_NO_MAPCHANGE);	 // i odpalamy timer ponownie :)
    			return Plugin_Continue; // pomijamy poniższe linijki, żeby przypadkiem nikomu VIP'a nie rozdać!
    		}
    	}
    	
    	iVipID[0] = GetRandomPlayer(); // jeśli kod wyżej nie przeszedł, czyli graczy jest wystarczająco, stockiem łapimy osobę bez VIP'a i zapisujemy jej ID w pierwszej szufladce naszej tablicy
    	iVipID[1] = GetRandomPlayer();	// tutaj łapiemy do drugiej szufladki drugą osobę
    	while(iVipID[0] == iVipID[1]) // no, a co jeśli plugin wylosował jedną i tę samą osobę? pętla warunkowa! jeśli ID gracza z szufladki nr 1 jest takie samo jak z szufladki nr 2, to pobieramy do drugiej szufladki kolejny raz. Tak długo, aż uda nam się pobrać inną osobę
    		iVipID[1] = GetRandomPlayer(); // no i tu właśnie dzieją się te czary
    
      	iVIPSID[0] = GetSteamAccountID(iVipID[0]); // zapisujemy SID graczy
    	iVIPSID[1] = GetSteamAccountID(iVipID[1]); // zapisujemy SID graczy
    	PrintToChatAll("%s Gratulacje! VIP'ami na tej mapie zostali : %N oraz %N!", PREFIX, iVipID[0], iVipID[1]); // oznajmiamy powodzenie
    	rozdano_vip = true; // vipy rozdane, więc zmienną ustawiamy na prawdę
    	return Plugin_Continue;	// użyliśmy wcześniej, więc musimy użyć teraz. funkcja musi zwracać jakąś wartość
    }
    stock int GetRandomPlayer() // stock, dzięki któremu wcześniej pobraliśmy ID osoby nominowanej do zostania VIP'em :P
    {
    	int clients[MAXPLAYERS + 1];
    	int clientCount;
    	for (int i = 1; i <= MaxClients; i++)
    	{
    		if (IsClientInGame(i) && IsValidClient(i) && !ma_vip(i) && !IsFakeClient(i))
    			clients[clientCount++] = i;
    	}
    	if(clientCount < 2)
    		return -1;
    		
    	return (clientCount == 0) ? -1 : clients[GetRandomInt(0, clientCount - 1)];
    }
    stock int GetAllPlayers() // stock, dzięki któremu pobraliśmy wszystkich graczy bez VIP na serwerze
    {
    	int gracze = 0;
    	for(int i = 0; i <= MaxClients; i++)
    	{
    		if(!IsValidClient(i) || !IsClientInGame(i) || IsFakeClient(i))
    			continue;
    		if(ma_vip(i))
    			continue;
    			
    		gracze ++;
    	}
    	return gracze;
    }
    stock bool ma_vip(int client) // stock, dzięki któremu sprawdzamy, czy gracz o podanym ID ma VIP'a (w tym wypadku jest to flaga a - ADMFLAG_RESERVATION
    {
    	if(GetUserFlagBits(client) & ADMFLAG_RESERVATION)
    		return true;
    
    	return false;
    }
    stock bool IsValidClient(int client) // stock, dzięki któremu sprawdzamy, czy gracz jest prawidłowy
    {
    	if (client > 0 && client <= MAXPLAYERS && IsClientConnected(client))
    		return true;
    	return false;
    }

     

    No i OK. Zacznijmy od początku.

     

     

    1. Poinformuj plugin o pliku z tłumaczeniem. 

     

    W tym celu w funkcji startupu pluginu (OnPluginStart) należy załadować translacje. Użyjemy do tego funkcji LoadTranslations.

    W naszym przypadku będzie to wyglądało w ten sposób : 

    public void OnPluginStart()
    {
    	LoadTranslations("free-vip.phrases");
    }

     

    2. Napisz funkcję wyświetlającą tekst pobierany z pliku *.phrases.txt

     

    Pierwszym i jednocześnie dość istotnym krokiem w tym miejscu będzie zdanie sobie sprawy, że istnieją dwie możliwości zaimplementowania tłumaczenia w kodzie.

     

    %t - użyjemy, gdy wyświetlany tekst będzie bezpośrednio do gracza, przykładowo przez funkcję PrintToChat.

    %T - tego dziada użyjemy, gdy funkcja nie będzie bezpośrednio kierowana do gracza, a do serwera, zatem PrintToServer, LogMessage czy Format zawierający tłumaczenie musi być napisany w tej formie. Ważnym jest, żeby zaznaczyć w kodzie, jakiego języka mamy użyć do translacji.

    LANG_SERVER - funkcja użyje języka serwera.

    client(indeks klienta) - w wypadku, gdybyśmy używali przykładowo funkcji Format w celu podstawienia stringa do nazwy menu, funkcja użyje języka klienta.

     

    W naszym przykładzie skupimy się na funkcji PrintToChatAll, bo występuje ona dwa razy, i jako jedyna wyświetla tekst.


     

    Cytat

     

    PrintToChatAll("%s Gratulacje! VIP'ami na tej mapie zostali : %N oraz %N!", PREFIX, iVipID[0], iVipID[1]);

    PrintToChatAll("%s Losowanie 2 darmowych VIP'ów nie może się teraz odbyć. Próba zostanie ponowiona za 20 sekund!", PREFIX);

     

     

    Jak widać, pierwsza funkcja najpierw wyświetli zdefiniowany na początku pluginu prefiks, potem tekst i dwie zmienne. %N odpowiada za nazwę klienta, którego ID podaliśmy w argumentach za prefiksem.

    Druga funkcja wyświetli tylko prefiks i tekst.

     

    Jako, że prefiks jest zdefiniowany i jest stały, pominiemy go w tłumaczeniu.

    Cytat

     

    PrintToChatAll("%s %t", PREFIX, "Gratulacje", iVipID[0], iVipID[1]);

    PrintToChatAll("%s %t", PREFIX, "Losowanie odroczone");

     

     

    3. Stwórz plik z tłumaczeniem

     

    Na tym etapie zajmiemy się stworzeniem pliku tekstowego, którego nazwa będzie odpowiadała tej, którą zaznaczyliśmy w naszym pluginie na jego początku.

    Zatem - tworzymy plik free-vip.phrases.txt, a w nim:

    "Phrases" // koniecznie. Zawsze ta linijka musi się tak nazywać :)
    {
    	"Gratulacje" // odniesienie do nazwy tłumaczonego wyrażenia w kodzie
    	{
    		"#format" "{1:N},{2:N}"     //ustalamy w odpowiedniej kolejności typy zmiennych, które implementujemy w argumentach funkcji wyświetlającej tekst
    		"en" "Congratz! This map VIP players are: {1} and {2}!" //tłumaczenie dla języka angielskiego
    		"pl" "Gratulacje! VIP'ami na tej mapie zostali: {1} oraz {2}!" //tłumaczenie dla języka polskiego
    	}
    	"Losowanie odroczone"
    	{
    		//tutaj nie trzeba nic formatować, bo nie mamy żadnych zmiennych, więc przechodzimy od razu do tłumaczeń
    		"en" "The draw of 2 free VIPs will be denied. The attempt will be renewed in 20 seconds!" //tłumaczenie dla języka angielskiego
    		"pl" "Losowanie 2 darmowych VIP'ów nie może się teraz odbyć. Próba zostanie ponowiona za 20 sekund!" //tłumaczenie dla języka polskiego
    	}
    }

    Plik należy umieścić w folderze addons/sourcemod/translations/

     

    Inne typy zmiennych w "#format" :

     

    {1:d},{2:x},{3:f},{4:s},{5:c},{6:t}

     

    d lub i : wyświetli liczbę, cyfrę

    x : wyświetli zmienną w systemie szesnastkowym

    f : wyświetli zmienną typu float

    s : wyświetli zmienną typu string

    c : wyświetli jeden znak (UTF-8)

    t : służy do załączania kolejnej translacji

     

     

    Zezwalam na kopiowanie tego poradnika w dowolne miejsca internetu, niech niesie pomoc komu tam trzeba ?

    Fajnie by było, gdyby tak udostępniony poradnik został odpowiednio opisany kto jest autorem, oraz skąd pochodzi ? 

    • Super! 3
×
×
  • Dodaj nową pozycję...