Skocz do zawartości

Rekomendowane odpowiedzi

Gość

W poradniku podlinkowanym wyżej, znajdziecie informacje na temat samego tłumaczenia, niejako wykorzystywania już gotowych plików *.phrases.txt znajdujących się w folderze addons/sourcemod/translations/

Ja chciałbym zwrócić uwagę na problem od strony kodowania.

 

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?

Sprawdźmy to! (xd)

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
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!.

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 PrintToChat, 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" //ZAWSZE "Phrases"!
{
	"Gratulacje"
	{
		"#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

Edytowane przez Gość

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość

Wydaje mi się, że wypadałoby to wyprostować..

Otóż %T i %t. Różnica między tymi dziadami jest taka, że %t używane w funkcji np PrintToChat użyje domyślnego języka klienta użytego jako argument funkcji.

To znaczy dla przykładu : PrintToChat(client, "%t", "przykladowe-tlumaczenie");  użyje języka, który używa "client". 

%T pozostaje bez zmian, tak jak w poradniku wyżej.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić obrazków. Dodaj lub załącz obrazki z adresu URL.


×
×
  • Dodaj nową pozycję...