Jump to content
assignment_ind Existing user? Sign In

Sign In



person_add Sign Up
Go-Code.pl - Support SourceMod i Pluginy CS:GO
Sign in to follow this  
haooy

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

Recommended Posts

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

  • Lubię to! 1

Share this post


Link to post
Share on other sites

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) {
  ...
}

 

  • Lubię to! 1

Share this post


Link to post
Share on other sites

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?

Edited by haooy
asfasf

Share this post


Link to post
Share on other sites

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 😄

  • Dobry pomysł! 1

Share this post


Link to post
Share on other sites

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

  • Lubię to! 1
By MAGNET,

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.


O NAS Jesteśmy społecznością łączącą ludzi, którzy dzielą pasję poznawania CS:GO od strony programistycznej. Posiadamy duże zaplecze merytoryczne i zawsze cieszymy się, gdy dołączają do nas osoby gotowe do nauki. Gwarantujemy, że z odrobiną wytrwałości i otwartym umysłem bardzo szybko napiszesz swój pierwszy plugin. Zapraszamy! 🙂
Szablon wykonany z dużą ilością przez cyberpixelz / Mesharsky / Sitefuture
Forum dumnie napędzane przez: Invision Power Services, Inc.
×
×
  • Create New...