Skocz do zawartości
haooy

[Rozwiązane] Jak sprawdzić naciśnięte klawisze?

Rekomendowane odpowiedzi

witam, mam pytanie: Jak sprawdzić czy gracz naciska więcej niż jeden klawisz?. Chodzi mi o klawisz IN_USE(domyślnie 'e') oraz IN_SPEED(domyślnie 'shift'). Chciałbym zaimplementować to do pluginu na malowanie(laser), że kiedy gracz naciśnie 'shift + e' zacznie malować.
Dzięki za pomoc.

pspspsps: happy vd

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

To fajne pytanie, bo zahacza mocno o operacje bitowe

 

Jeśli wcześniej nie operowałeś na bitach i chcesz dowiedzieć się więcej, możesz poczytać sobie o tym tutaj:

 

Zakładając, że wiesz już o co chodzi, możemy przejść dalej...

 

Aby wykryć naciśnięcie klawiszy, najlepiej użyć funkcji: OnPlayerRunCmd

public Action OnPlayerRunCmd(int client, int & buttons, int & impulse, float vel[3], float angles[3], int & weapon, int & subtype, int & cmdnum, int & tickcount, int & seed, int mouse[2]) {
  // tutaj kod...
}

zmienna buttons zawiera wszystkie informacje o naciśniętych przyciskach

 

W normalnej sytuacji, gdybyśmy chcieli przykładowo sprawdzić czy gracz naciska tylko klawisz E, robi się to tak:

if (buttons & IN_USE) {
  .....
}

Gdyby natomiast interesowało nad naciśnięcie dwóch klawiszy naraz, po prostu używamy ANDa:

if (buttons & IN_USE && buttons & IN_SPEED) {
  ....
}

Ilość ampersantów '&' jest trochę przerażająca, ale jeśli ciężko to rozszyfrować można sobie pododawać nawiasy:

if ((buttons & IN_USE) && (buttons & IN_SPEED)) {
  ....
}

 

@EDIT

Można to załatwić jednym warunkiem:

if ((buttons & (IN_USE|IN_SPEED)) == (IN_USE|IN_SPEED)) {
  ...
}

Albo ładniej:

int yourFlags = IN_USE|IN_SPEED;
if ((buttons & yourFlags) == yourFlags) {
  ...
}

 

Udostępnij tę odpowiedź


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

sprawdzę jak działa ten edit

@edit
tak wygląda kod przed zmiana:

public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon)
{
	if (!g_bEquipt[client])
		return Plugin_Continue;

	if (!gc_bEnable.BoolValue)
		return Plugin_Continue;


	if ((buttons & IN_USE))
	{
		if (!(g_iLastButtons[client] & IN_USE))
		{
			TraceEye(client, g_fLastPainter[client]);
			g_bPainterUse[client] = true;
		}
	}
	else if ((g_iLastButtons[client] & IN_USE))
	{
		g_fLastPainter[client][0] = 0.0;
		g_fLastPainter[client][1] = 0.0;
		g_fLastPainter[client][2] = 0.0;
		g_bPainterUse[client] = false;
	}

	g_iLastButtons[client] = buttons;

	return Plugin_Continue;
}

a to jest po zmianie:
 

public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon)
{
	if (!g_bEquipt[client])
		return Plugin_Continue;

	if (!gc_bEnable.BoolValue)
		return Plugin_Continue;


	if ((buttons & (IN_USE|IN_SPEED)) == (IN_USE|IN_SPEED))
	{
		if (!(g_iLastButtons[client] & IN_USE) && !(g_iLastButtons[client] & IN_SPEED))
		{
			TraceEye(client, g_fLastPainter[client]);
			g_bPainterUse[client] = true;
		}
	}
	else if ((g_iLastButtons[client] & IN_USE) && (g_iLastButtons[client] & IN_SPEED))
	{
		g_fLastPainter[client][0] = 0.0;
		g_fLastPainter[client][1] = 0.0;
		g_fLastPainter[client][2] = 0.0;
		g_bPainterUse[client] = false;
	}

	g_iLastButtons[client] = buttons;

	return Plugin_Continue;
}

ogolnie to nie dziala bo nie wiem jak ogarnac to g_iLastButtons. moze wiesz jak to poprawic?

Edytowane przez haooy
asfasf

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Też się musiałem chwilę zastanowić dlaczego to nie działa, ale znalazłem wyjaśnienie:

 

Kiedy chcesz zacząć malować to naciskasz dwa klawisze, czyli shift i e. Zauważ, że praktycznie nigdy nie naciśniesz dwóch klawiszy idealnie w tym samym momencie. Z tego powodu, najpierw funkcja uruchamia się z wciśniętym IN_USE, a dopiero potem drugi raz z IN_USE oraz IN_SPEED (lub odwrotnie). Wówczas spełnia się ten warunek:

 

if ((buttons & (IN_USE|IN_SPEED)) == (IN_USE|IN_SPEED))

niestety, wchodząc do kolejnego, zagnieżdżonego warunku masz już takie coś:

if (!(g_iLastButtons[client] & IN_USE) && !(g_iLastButtons[client] & IN_SPEED))

lastButtons przechowuje zwyczajnie informacje jakie klawisze trzymałeś w ostatnim wywołaniu funkcji OnPlayerRunCmd. W momencie kiedy trzymasz obydwa klawisze w zmiennej 'buttons' będzie IN_USE oraz IN_SPEED, natomiast w lastButtons...tylko jeden klawisz. Dlatego właśnie if nigdy nie przechodzi i nie rozpoczyna się proces malowania.

 

 

Po co w ogóle jest ten warunek? Ponieważ TraceEye(client, g_fLastPainter[client]); służy do rozpoczęcia procesu malowania. Później mógłbyś trzymać shift oraz e i przykładowo poruszać się WSAD - gdyby tego zagnieżdżonego warunku nie było, TraceEye uruchamiałby się za każdym razem.

 

Rozwiązanie które teraz przychodzi mi do głowy (może da się to zrobić lepiej, ale to co wymyśliłem jest w miarę sensowne) to stworzenie dwóch globalnych zmiennych typu bool: paintEnabled oraz lastPaintEnabled. lastPaintEnabled będzie działał podobnie do lastButtons - sprawdza, czy malowanie zaczęło być dozwolone przy ostatnim  wywołaniu OnPlayerRunCmd i będzie zapobiegało wielokrotnemu wywoływaniu TraceEye:

 

 

// dodaj sobie do globalnych
bool paintEnabled[MAXPLAYERS];
bool lastPaintEnabled;

public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon)
{
	if (!g_bEquipt[client])
		return Plugin_Continue;

	if (!gc_bEnable.BoolValue)
		return Plugin_Continue;


	if ((buttons & (IN_USE|IN_SPEED)) == (IN_USE|IN_SPEED))
	{
		if (!lastPaintEnabled[client])
		{
			TraceEye(client, g_fLastPainter[client]);
			g_bPainterUse[client] = true;
            paintEnabled[client] = true;
		}
	}
	else if ((g_iLastButtons[client] & IN_USE) && (g_iLastButtons[client] & IN_SPEED))
	{
		g_fLastPainter[client][0] = 0.0;
		g_fLastPainter[client][1] = 0.0;
		g_fLastPainter[client][2] = 0.0;
		g_bPainterUse[client] = false;
        paintEnabled[client] = false;
	}

	g_iLastButtons[client] = buttons;
    lastPaintEnabled[client] = paintEnabled[client];

	return Plugin_Continue;
}

Sprawdź czy to działa w ogóle, bo musze zmykać i nie przekminiłem tego do końca 😄

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

error wystepuje taki: error 028: invalid subscript (not an array or too many subscripts): "lastPaintEnabled", wiec te globalne powinny wygladac tak:
 

bool paintEnabled[MAXPLAYERS + 1];
bool lastPaintEnabled[MAXPLAYERS + 1];

i teraz wszystko ladnie dziala, dzieki.

@edit podczas malowania troche przycina jak sie szybko poruszy myszka, ale tak to jest ok

Przez MAGNET,

zapomniałem dodać [MAXPLAYERS] do lastPainta, mój błąd ;) a co do "+ 1" - nie ma potrzeby tego używać

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wiadomość wygenerowana automatycznie

 

Temat został zamknięty. Powodem jest całkowite rozwiązanie problemu zawartego w temacie.

 

Jeśli się z tym nie zgadzasz, zaraportuj ten post z prośbą o ponowne otwarcie i kontynuację dyskusji.

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ę...