Skocz do zawartości

Rekomendowane odpowiedzi

Witam mam 2 problemy po krótce je opiszę.

 

A więc pierwszy polega na tym iż mam funkcje GetRandomInt i wiem jak zrobić tak aby losowało int tych graczy którzy są aktualnie na serwerze.

Druga z zagwostek na dziś jak zaczymać na jakiś czas gracza w miejscu aby nie mógł się ruszyć, wpadłem na pomysł aby zrobić timer i na czas timera zmienić szybkość client'owi na 0. Aczkolwiek nie wiem czy jest to dobry pomysł może są jakieś szybsze wygodniejsze sposoby. Z góry dzięki za pomoc. Pozdrawiam i  życzę miłego kodowania.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

2. Nie ma szybszego sposobu niż zrobienie timera niestety

1. Co do losowego gracza można to zrobić tak:

stock int getRandomPlayer()
{
	int players[65];
	int players_counter = 0;
	for (int i = 1; i <= MaxClients; i++)
		if(IsClientValid(i))
		{
			players[players_counter] = i;
			players_counter++;
		}
	
	return players[GetRandomInt(0, players_counter-1)];
}

stock bool IsClientValid(int client)
{
	return (client > 0 && client <= MaxClients && IsClientInGame(client) && !IsClientSourceTV(client));
}

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Co do zamrażania, to jeśli chcesz aby ofiara nie mogła też ruszać myszką:

 

//Odmrozenie
int buttons = GetEntityFlags(client);
SetEntityFlags(client, (buttons &= ~FL_FROZEN))
  
//zamrozenie
int buttons = GetEntityFlags(client);
SetEntityFlags(client, (buttons |= FL_FROZEN))

 

 

Jeśli zaś chodzi o losowanie:

 

nie możesz po prostu pobrać sobie ilości graczy i wylosować przez:

GetRandomInt(1,Ilosc_graczy())

Załóżmy, że na serwerze masz 4 graczy. Mają oni przypisane indexy: 1 2 3 4. W momencie, gdy gracz z ID=2 wyjdzie na serwerze masz 3 graczy o indexach 1 3 4. Losowa wartość mogłaby natrafić na 2 - osobę niepołączoną

 

 

Skoro tak, to może po prostu losować gracza i patrzeć, czy jest połączony - i robić to aż do skutku?

bool wylosowano = false;
int winner_index = -1;
while (wylosowano == false) {
  winner_index = GetRandomInt(1,MAXPLAYERS);
  if (IsClientInGame(wylosowany)
      wylosowano = true;
}
      
// w tym miejscu mamy wygrany index

Teoretycznie jest to jakieś rozwiązanie, choć baardzo słabe. O ile przy większej ilości graczy (np. 30) ma to jeszcze sens, to w sytuacji, gdyby na serwerze było ich 3, to szansa na trafienie dobrego gracza to 3/65 (4%!). Kto wie, ile razy pętla będzie się musiała obrócić zanim kogoś trafisz...do tego czasu możesz nawet złapać crasha serwera. A jeśli nie będzie nikogo? Wtedy mamy do czynienia z nieskończoną pętlą i w efekcie pewnym crashem.

 

Oczywiście w trakcie pisania mojego wywodu vasto zdążył już podać prawidłowe rozwiązanie problemu - iterujemy pętlą po wszystkich indexach. Jesli znajdziemy gracza - wpychamy go do tablicy, by na samym końcu zwrócić z niej wartość pod losowym indexem w przedziale <0,ilość_znalezionych_graczy>

Jedyny problem jaki tutaj widzę w tym kodzie to sytuacja, gdy na serwerze nie ma żadnego gracza - wówczas funkcja zwróci niechybnie 0. Dlatego pamiętaj o tym, żeby zawsze sprawdzać, czy funkcja nie zwróciła 0 - jeśli tak, na serwerze nie ma żadnego gracza.

 

PS: Jeśli chcesz dowiedzieć się o co do cholery chodzi w kodzie na górze posta (dot. zamrażania, co to za |= &= ~flags itd.), to zapraszam tutaj: 

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Vasto_Lorde doszedłem do takiego czegoś
 

#include <sourcemod>
#include <sdktools>
#include <sdkhooks>

#pragma semicolon 1;

public void OnClientPutInServer(int client)
{
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
	HookEvent("round_start", Event_RoundStart);
}
public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype)
{	
	if (damagetype & DMG_SLASH)
	{
		SetEntityRenderColor(victim, 255, 0, 0, 255); 
		SetEntityRenderColor(attacker, 0); 
		PrintHintTextToAll("Goni : %n", victim);
		damage = 0.0;
		return Plugin_Handled;
	}
	return Plugin_Continue;
} 

public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
{
	int random = getRandomPlayer();

	PrintToChatAll("%i", random);

	PrintHintTextToAll("Goni : %n", random);
	SetEntityRenderColor(random, 255, 0, 0, 255); 

	return Plugin_Continue;
}

stock int getRandomPlayer()
{
	int players[65];
	int players_counter = 0;
	for (int i = 1; i <= MaxClients; i++)
		if(IsClientValid(i))
		{
			players[players_counter] = i;
			players_counter++;
		}
	
	return players[GetRandomInt(0, players_counter-1)];
}

stock bool IsClientValid(int client)
{
	return (client > 0 && client <= MaxClients && IsClientInGame(client) && !IsClientSourceTV(client));
}

Niestety zamist raz wysolować jednego gracza losuje jakieś 20 nie wiem dlaczego.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ponieważ HookEvent round_start rejestrujesz w OnClientPutInServer. Więc za każdym razem jak wejdzie ktokolwiek na serwer, będzie się round_start wykonywał o jeden więcej razy. Rejestruj to w OnPluginStart

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Vasto_Lorde Bardzo ci dziękuję ale jeszcze jeden problem Na początku rundy nie działa PrintHintTextToAll("Goni : %n", random); i pewnie dlatego że nie mogę się odnieść do random prawda ?

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie działa prawdopodobnie dlatego, że używasz %n do wyświetlenia integer'a. %n oznacza formatowanie string'a. String to ciąg znaków, integer to liczba bez przecinka. Do formatowania intger'a użyj %i

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Vasto_Lorde Ale ja chciałbym wyświetlić tam nick gracza. Z tego co dobrze pamiętam u Magneta na filmach było że %n z client wyświetli nick.

 

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

%N wyświetla nick gracza

%n wyświetla string

😉

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Faktycznie dzięki serdeczne. 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
int buttons = GetEntityFlags(victim);

SetEntityFlags(victim, (buttons |= FL_FROZEN));

timerer = CreateTimer(10.0, Odmrozenie(victim),_, TIMER_DATA_HNDL_CLOSE);

PrintCenterText(victim, "Spowrotem możesz gonić za : %t", timerer);

 

// C:\Users\Prymex\Desktop\scripting\ganiany.sp(24) : error 017: undefined symbol "timerer"
// C:\Users\Prymex\Desktop\scripting\ganiany.sp(24) : error 100: function prototypes do not match
// C:\Users\Prymex\Desktop\scripting\ganiany.sp(25) : error 017: undefined symbol "timerer"

 

Czy tym razem ktoś zdefiniuje problem ?

Przez Vasto_Lorde,

Dodawaj proszę kod w tagi "code"

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Hej, dobrym pomysłem jest zaglądanie do tematu ze spisem errorów, gdzie niektóre rzeczy są już wytłumaczone

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Vasto_Lorde A jak zrobić aby timer był w PrintCenterText
A i jeszcze jedno pytanie ponieważ ja goniącemu daje color czerwony
A chciałbym później sprawdzać
kto jest goniący
A po kolorze sprawdzanie go będzie trochę trwało
Jak szybsza metoda
typu nadanie flagi
Albo coś

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
  • Lubię to! 1
Napisano (edytowane)
34 minuty temu, Prymex napisał:

@Vasto_Lorde A jak zrobić aby timer był w PrintCenterText
A i jeszcze jedno pytanie ponieważ ja goniącemu daje color czerwony
A chciałbym później sprawdzać
kto jest goniący
A po kolorze sprawdzanie go będzie trochę trwało
Jak szybsza metoda
typu nadanie flagi
Albo coś

 

Możesz stworzyć boola czyli wartość logiczną true/false  i sprawdzać czy dana osoba posiada tego bool'a ustawionego na true

 

bool NazwaBoola[MAXPLAYERS +1]; // Tworzenie boola

// Ustawianie wartości boola
NazwaBoola[client] = true; 
NazwaBoola[client] = false;
//

// if sprawdzający czy gracz posiada boola ustawionego na true
if(NazwaBoola[client] == true)
{
	// Funkcja zostaje wykonana kiedy wartośc jest ustawiona na true
}
else
{
    // Funkcja zostaje wykonana kiedy wartośc jest ustawiona na false
}

 

Edytowane przez Inext

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Napisano (edytowane)

Kolejny błąd na mojej drodzę nie wiem dlaczego ma prawo bytu ale po 1 starcie pluginy PrintHintTextToAll działa poprawnie ale powinien działać po każdym rozpoczęciu rundy niestety tak się nie dzieje.

 

public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
{

	int random = getRandomPlayer();
	int userid = GetClientUserId(random);
	int client = GetClientOfUserId(userid);

	PrintToChatAll("%i", random);
	NazwaBoola[client] = true; 

	PrintHintTextToAll("Goni : %N", client);
	SetEntityRenderColor(client, 255, 0, 0, 255); 

	return Plugin_Continue;
}

I właśnie linijka PrintHintTextToAll("Goni : %N", client); działa tylko raz po starcie pluginy. A powinna działać co nową rundę.

Edytowane przez Prymex

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
1 minutę temu, Prymex napisał:

Kolejny błąd na mojej drodzę nie wiem dlaczego ma prawo bytu ale po 1 starcie pluginy PrintHintTextToAll działa poprawnie ale powinien działać po każdym rozpoczęciu rundy niestety tak się nie dzieje.

 

Najlepiej jakbyś podesłał teraz cały kod pluginu 😋

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Vasto_Lorde Prosze bardzo

 

#include <sourcemod>
#include <sdktools>
#include <sdkhooks>

#pragma semicolon 1;

bool NazwaBoola[MAXPLAYERS +1]; 

public void OnClientPutInServer(int client)
{
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public OnPluginStart( ) {
	HookEvent("round_start", Event_RoundStart);
	HookEvent("round_end", Event_RoundEnd);
}
public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype)
{	
	if (damagetype & DMG_SLASH && NazwaBoola[attacker]==true)
	{
		SetEntityRenderColor(victim, 255, 0, 0, 255); 
		SetEntityRenderColor(attacker, 0); 
		PrintHintTextToAll("Goni : %N", victim);
		NazwaBoola[victim] = true; 
		NazwaBoola[attacker] = false;
		int buttons = GetEntityFlags(victim);
		SetEntityFlags(victim, (buttons |= FL_FROZEN));
		Handle timer = CreateTimer(10.0, Odmrozenie, victim);
		PrintCenterText(victim, "Spowrotem możesz gonić za : %t", timer);
		damage = 0.0;
		return Plugin_Handled;
	}
	return Plugin_Continue;
} 

public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
{

	int random = getRandomPlayer();
	int userid = GetClientUserId(random);
	int client = GetClientOfUserId(userid);

	PrintToChatAll("%i", random);
	NazwaBoola[client] = true; 

	PrintHintTextToAll("Goni : %N", client);
	SetEntityRenderColor(client, 255, 0, 0, 255); 

	return Plugin_Continue;
}

public Action Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
{
	int players[65];
	int players_counter = 0;
	for (int i = 1; i <= MaxClients; i++)
	if(IsClientValid(i))
	{	
		players[players_counter] = i;
		int userid = GetClientUserId(players[players_counter]);
		int client = GetClientOfUserId(userid);
		NazwaBoola[client] = false; 
		players_counter++;
	} 

	return Plugin_Continue;
}


stock int getRandomPlayer()
{
	int players[65];
	int players_counter = 0;
	for (int i = 1; i <= MaxClients; i++)
		if(IsClientValid(i))
		{
			players[players_counter] = i;
			players_counter++;
		}
	
	return players[GetRandomInt(0, players_counter-1)];
}

stock bool IsClientValid(int client)
{
	return (client > 0 && client <= MaxClients && IsClientInGame(client) && !IsClientSourceTV(client));
}

public Action Odmrozenie(Handle timer, int client){
	int buttons = GetEntityFlags(client);
	SetEntityFlags(client, (buttons &= ~FL_FROZEN));
	NazwaBoola[client] = false; 
	KillTimer(timer);
}

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
4 godziny temu, Prymex napisał:

Kolejny błąd na mojej drodzę nie wiem dlaczego ma prawo bytu ale po 1 starcie pluginy PrintHintTextToAll działa poprawnie ale powinien działać po każdym rozpoczęciu rundy niestety tak się nie dzieje.

 

U mnie na serwerze ten błąd nie występuj.

Obstawiam że sprawdzałeś to na zwykłym serwerze , w drużynie terrotystów i wyskakiwała ci informacja, że posiadasz bombe w EQ.

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach
Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.

×
×
  • Dodaj nową pozycję...