Skocz do zawartości
[Rozwiązane] Jak sprawdzić naciśnięte klawisze?
Pytania

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

Sygnatura użytkownika

b_560_95_1.png

  • Lubię to!
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) {
  ...
}

 

Sygnatura użytkownika

Użytkowniku! Pamiętaj, że nic tak nie motywuje jak porządna łapka w górę!

Nie mówię tylko o sobie - honoruj każdego, kto na to zasługuje 🙂

YouTube | SteamGitHub | MailboxGO | AchievementsGO | MuteGO

  • Lubię to!
Odnośnik do odpowiedzi
Udostępnij na innych stronach

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

Sygnatura użytkownika

b_560_95_1.png

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 😄

Sygnatura użytkownika

Użytkowniku! Pamiętaj, że nic tak nie motywuje jak porządna łapka w górę!

Nie mówię tylko o sobie - honoruj każdego, kto na to zasługuje 🙂

YouTube | SteamGitHub | MailboxGO | AchievementsGO | MuteGO

  • Dobry pomysł!
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

Sygnatura użytkownika

b_560_95_1.png

  • Lubię to!
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.

Sygnatura użytkownika

Użytkowniku! Pamiętaj, że nic tak nie motywuje jak porządna łapka w górę!

Nie mówię tylko o sobie - honoruj każdego, kto na to zasługuje 🙂

YouTube | SteamGitHub | MailboxGO | AchievementsGO | MuteGO

Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ostatnio przeglądający ten temat (1 użytkownik )

Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
×
×
  • Dodaj nową pozycję...