Skocz do zawartości
Paweł

[Rozwiązane] Problem z hookiem OnWeaponEquip

Rekomendowane odpowiedzi

Witam, mam problem z hookiem OnWeaponEquip. Kilka dni temu zostałem poproszony przez Właściciela Sieci o przerobienie modyfikacji GoMod pod serwer typowo pod FFA.

Aktualnie jeżeli wejdzie się  na broń to blokujesz się w niej. Hooka wykorzystuję, aby ustawić skina dla danej broni. Dodam, że w konsoli serwera cały czas spami "Weapon spawning in solid"

 

Kod:

Spoiler

public void OnClientPostAdminCheck(int client)
{
	if(IsValidClient(client))
	{
		char steam32[20];
		char temp[20];
		GetClientAuthId(client, AuthId_Steam3, steam32, sizeof(steam32));
		strcopy(temp, sizeof(temp), steam32[5]);
		int index;
		if((index = StrContains(temp, "]")) > -1)
			temp[index] = '\0';
			
		g_iSteam32[client] = StringToInt(temp);
	}
}

public Action OnWeaponEquip(int client, int weapon)
{
	char sWeapon[64];
	GetEntityClassname(weapon, sWeapon, sizeof(sWeapon));
	if(IsValidEdict(weapon))
	{
		if(weapon != g_iEarlierEntity[client])
		{
			int weaponindex = GetEntProp(weapon, Prop_Send, "m_iItemDefinitionIndex");
			int clip = GetEntProp(weapon, Prop_Send, "m_iClip1");
			int reserve = GetEntProp(weapon, Prop_Send, "m_iPrimaryReserveAmmoCount");
			RemovePlayerItem(client, weapon);
			AcceptEntityInput(weapon, "Kill");
			weapon = CreateEntityByName(sWeapon);
			SetEntProp(weapon, Prop_Send, "m_iItemDefinitionIndex", weaponindex);
			SetEntProp(weapon, Prop_Send, "m_bInitialized", 1);
			SetEntProp(weapon, Prop_Send, "m_iClip1", clip);
			SetEntProp(weapon, Prop_Send, "m_iPrimaryReserveAmmoCount", reserve);
			g_iEarlierEntity[client] = weapon;
			EquipPlayerWeapon(client, weapon);
			if(IsValidEdict(weapon))
			{
				static int IDHigh = 16384;
				SetEntProp(weapon, Prop_Send, "m_iItemIDLow", -1);
				SetEntProp(weapon, Prop_Send, "m_iItemIDHigh", IDHigh++);
					
				if(StrContains(sWeapon, "weapon_knife") != -1 || StrContains(sWeapon, "bayonet") != -1)
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientKnife[client]);
				else if(StrEqual(sWeapon, "weapon_ak47"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientAk47[client]);
				else if(StrEqual(sWeapon, "weapon_m4a1"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientM4a4[client]);
				else if(StrEqual(sWeapon, "weapon_m4a1_silencer"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientM4a1[client]);
				else if(StrEqual(sWeapon, "weapon_awp"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientAwp[client]);
				else if(StrEqual(sWeapon, "weapon_ssg08"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientScout[client]);
				else if(StrEqual(sWeapon, "weapon_glock"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientGlock[client]);
				else if(StrEqual(sWeapon, "weapon_usp_silencer"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientUsp[client]);
				else if(StrEqual(sWeapon, "weapon_deagle"))
					SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientDeagle[client]);
		
				SetEntPropFloat(weapon, Prop_Send, "m_flFallbackWear", 0.000001);
				SetEntProp(weapon, Prop_Send, "m_nFallbackSeed", GetRandomInt(0, 8192));

				SetEntProp(weapon, Prop_Send, "m_iAccountID", g_iSteam32[client]);
				SetEntPropEnt(weapon, Prop_Send, "m_hOwnerEntity", client);
				SetEntPropEnt(weapon, Prop_Send, "m_hPrevOwner", -1);
			}
			return Plugin_Handled;
		}
	}
	return Plugin_Continue;
}

 

 

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Kilka pomysłów/porad:

 

- Sprawdź najpierw, czy samo usunięcie broni Ci działa, możliwe że błąd w konsoli (który oznacza że byt broni tworzymy w innym bycie który jest stały, SOLID) właśnie tego dotyczy

 

- Dlaczego tworzysz broń jak byt? Nie prościej jest po prostu... dać graczowi tę broń którą kasujesz i nadać jej odpowiednie właściwości? Przecież te właściwości i tak nadajesz po stworzeniu bytu, więc nie powinno to mieć zbytniej różnicy, a zmniejszy ilość operacji

 

- Jeśli nadajemy bytowi broni jakieś właściwości, to dlaczego dopiero w połowie ich nadawania sprawdzamy czy IsValidEdict? To samo pytanie dotyczy się dania klientowi broni, dlaczego dzieje się to w połowie funkcji a nie na jej końcu?

 

- Jeśli zamiast g_iClientKnife/g_iClientAK47 użyłbyś g_iClientWeapon[id_broni][client] (dwu wymiarowej tablicy zawierającej ID skinu dla każdego klienta oraz każdej broni zamiast dla każdej broni używać nowej zmiennej), mógłbyś wtedy użyć CS_AliasToWeaponID
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! i zamiast masy else if'ów kod na nadanie skina nowej broni wyglądałby mniej więcej tak:

SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientWeapons[CS_AliasToWeaponID(sWeapon)][client]);

I ta jedna linia obsługiwałaby wszystkie bronie. Minus jest taki, że nadal tablica g_iClientWeapons jest tworzona dla wszystkich broni więc zajmuje na pewno więcej pamięci, bo zajmuje miejsce nawet dla broni dla których skinów nie używasz. Ale jeśli nawet byś jej użył to możesz ją lekko "zoptymalizować" i skrócić tablicę bo według listy broni CSWeaponID
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! nie trzeba przecież nadawać skinów dla granatów które akurat znajdują się na samym końcu. Wtedy tablica skraca się z 55 miejsc na 51

 

- Możesz ukrócić sobie pracę w elseifach i zamiast podwójnie sprawdzać M4A1, użyj StrContains na string "weapon_m4a1"

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

@Update do pomysłu z tablicami:
W sumie to nie trzeba robić dwuwymiarowej tablicy która będzie zawierała każdą broń. Zoptymalizowane rozwiązanie w pseudokodzie:

//1
int weaponHasSkin[MAX_WEAPONS] = {1, -1, -1, 3, 0 ... 2};

//2
int clientWeaponSkins[MAX_AVALIBLE_SKINS][MaxClients+1];

//3
if (weaponHasSkin[CS_AliasToWeaponID(sWeapon)] != -1)
	SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", clientWeaponSkins[weaponHasSkin[CS_AliasToWeaponID(sWeapon)]][client]);
  1. W pierwszej linii znajduje się tablica jednowymiarowa, dla każdego indeksu broni jest wartość int określająca indeks z clientWeaponSkins w jakim znajduje się skin dla danej broni
  2. W drugiej linii jest już omawiana wcześniej zmienna przechowująca wszystkie wybrane przez klienta skiny, jednakże tym razem nie zawiera ona miejsca tylko dla tych broni, które skina posiadają
  3. W trzeciej linii jest już sposób użycia

 

W poprzednim rozwiązaniu zajmujemy zawsze 50*65(MAX_WEAPONS*MaxClients) miejsc

W tym rozwiązaniu zajmujemy zależnie od ilości skinów na serwerze w najgorszym przypadku 50*65(MAX_AVALIBLE_SKINS*MaxClients) + 50(MAX_WEAPONS), więc o 50 więcej niż w pierwszym rozwiązaniu, ale jak się domyślam nie każda broń będzie miała skin. Dlatego spokojnie można założyć, że jest to 20*65+50, co daje nam ponad dwukrotnie mniejszą zajętą pamięć

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