←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

Łapanie eventu - pocisk trafiający w byt/m...

  • +
  • -
Sooldierr's Photo Sooldierr 19.02.2015

Witam

 

Chciałbym dodać dźwięki (3 losowo odgrywane gdy pocisk trafi w worek, 1 gdy zniszczony) do pluginu boostbags (stawiający worki zniszczalne w grze do kamp na ZM). Podczas ostrzału worków lub zniszczenia odgrywane byłyby dźwięki.

 

Jak powinienem złapać event trafienia pocisku w worek?

Ham_Touch czy Ham_Takedamage?

 

I jak ewentualnie dalej sprawdzać czy byt trafiany to model worka?

Poniżej kod pluginu

 

Attached Files

Quote

  • +
  • -
grankee's Photo grankee 19.02.2015

Ham_TakeDamage

 

Sprawdzasz czy classname victima to "func_bags" oraz czy attacker jest połączony (is_user_connected) żeby wyeliminować jakiej nieprzewidziane obrażenia i odgrywasz dźwięk.

Quote

  • +
  • -
Sooldierr's Photo Sooldierr 19.02.2015

Nie jestem jakoś zaawansowany w scriptingu.

 

Jak sprawdzić ten classname?

Oraz jak sprawdzić czy byt nadal istnieje? Bo w przeciwnym wypadku ma odegrać nie dźwięk trafienia w baga tylko dźwięk zniszczenia,

Quote

  • +
  • -
NoLiFeR's Photo NoLiFeR 19.02.2015

Sprawdzasz czy damage jest większy od pev_health (fakemeta) i wywołujesz dzwięk zniszczenia zamiast obrażeń.

Quote

  • +
  • -
Sooldierr's Photo Sooldierr 19.02.2015

Jak odegrać właściwie dźwięk? Przy użyciu emit_sound?

Jak powinienem zastosować?

 

Stworzyłem i zainicjalizowałem w zmiennych moje dźwięki:

new const g_soundhit[][]  = {"sound/misc/g_soundhit.wav", "sound/misc/g_soundhit2.wav", "sound/misc/g_soundhit3.wav"}
new const g_sounddestroy[]  = "sound/misc/g_sounddestroy.wav"

w:

public plugin_precache()

dodałem ich buforowanie:

for (new i=0; i < sizeof(g_soundhit); i++)
		precache_sound(g_soundhit[i])
	precache_sound(g_sounddestroy)

W:

public plugin_init()

Dodałem rejestrowanie wydarzenia zadawania obrażeń:

RegisterHam(Ham_TakeDamage, "player", "Fw_PlayerTakeDamage", 0)

Funkcja wywoływana przez Ham_TakeDamage:

public Fw_PlayerTakeDamage(victim, idinflictor, idattacker, Float:damage, damagebits)
{
	new szTouched[16]
	pev(victim , pev_classname , szTouched , 15);
	new szHealth = pev(victim, pev_health);
	if(!is_user_connected(idattacker) || containi(szTouched, "func_bags") == 1)
		return HAM_IGNORED
	if (damage < szHealth)
	{
		emit_sound(victim, CHAN_AUTO, g_soundhit[random(sizeof g_soundhit)], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
		return HAM_SUPERCEDE
	}
	if (damage > szHealth)
	{
		emit_sound(victim, CHAN_AUTO, g_sounddestroy, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
		return HAM_SUPERCEDE
	}
	return HAM_IGNORED
} 

Tak wygląda mój plugin ostatecznie. Ktoś zerknie i ewentualnie poprawi?

Attached Files


Edited by Sooldierr, 19.02.2015 21:06.
Quote

  • +
  • -
radim's Photo radim 19.02.2015

emit_sound

Quote

  • +
  • -
grankee's Photo grankee 20.02.2015


containi(szTouched, "func_bags") == 1

 

raczej

containi(szTouched,"func_bags")!=0

bo jeśli by classname było takie samo to funkcja zwróci 0 jako że od zerowej pozycji jeden wyraz zawiera drugi

a najlepiej

!equal(szTouched,"func_bags")
Quote

  • +
  • -
Droso's Photo Droso 20.02.2015


raczej

containi(szTouched,"func_bags")!=0

raczej != -1

Quote

  • +
  • -
GwynBleidD's Photo GwynBleidD 21.02.2015

raczej != -1


Warunek ma na celu sprawdzenie, czy napis ZACZYNA się podanym fragmentem, więc !=0 jest prawidłowe.
Quote

  • +
  • -
Sooldierr's Photo Sooldierr 21.02.2015

Odwróciłem warunek w drugą stronę, że gdy spełnione są warunki to wtedy się coś ma dziać, inaczej nic po prostu. Tak jest dobrze?

public Fw_PlayerTakeDamage(victim, idinflictor, idattacker, Float:damage, damagebits)
{
	new szTouched[16]
	pev(victim , pev_classname , szTouched , 15);
	
	if(equali(szTouched,"func_bags") && is_user_connected(idattacker))
	{
		new szHealth = pev(victim, pev_health);
		if (damage < szHealth)
		{
			emit_sound(victim, CHAN_AUTO, g_soundhit[random(sizeof g_soundhit)], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
			
		}
		if (damage > szHealth)
		{
			emit_sound(victim, CHAN_AUTO, g_sounddestroy, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
			if (get_user_team(idattacker) != 1)
			{
				new niszczyciel[32]
				get_user_name(idattacker, niszczyciel, 31)
				ColorChat(0, GREEN, "%s zniszczyl kladke!", niszczyciel)
			}

		}
	}
	return HAM_IGNORED
}
Quote

  • +
  • -
NoLiFeR's Photo NoLiFeR 22.02.2015

Myśle że zadziała prawidłowo.

Quote

  • +
  • -
Sooldierr's Photo Sooldierr 22.02.2015

Jednak nie działa prawidłowo.

Poniżej cały kod

Attached Files

Quote

  • +
  • -
radim's Photo radim 22.02.2015

RegisterHam(Ham_TakeDamage, "player", "Fw_PlayerTakeDamage", 0)
->
RegisterHam(Ham_TakeDamage, "func_wall", "Fw_PlayerTakeDamage", 0)
Quote

  • +
  • -
Sooldierr's Photo Sooldierr 23.02.2015

Dzięki to pomogło.

Pozostała ostatnia kwestia, chciałem dodać jeszcze info o graczu rozwalającym kładkę. Jednak nie ma takiego info. Domyślam się, że błędnie operuję tablicą dwuwymiarową, przypisywaniem do niej i wyświetlaniem.

 

Deklarowanie i inicjalizowanie:

new niszczyciele[15][32] = {"","","","","","","","","","","","","","",""}
new nr = 0

Rejestrowanie komendy wyświetlającej listę graczy (ludzi), którzy w aktualnej rundzie zniszczyli kładkę.

register_clcmd("amx_niszczyciele", "cmd_niszczyciele", ADMIN_KICK)

Funkcja wyświetlająca ową listę graczy:

public cmd_niszczyciele(id)
{
	client_print(id, print_console, "=== W tej rundzie paczki zniszczyli===")
	for (new i=0; i< 15; i++)
	{
		if (!equali(niszczyciele[i], ""))
		{
			client_print(id, print_console, "%s", niszczyciele[i])
		}
	}
}

Resetowanie listy co rundę:

public event_newround()
{
	nr = 0
	for (new i=0; i<15; i++)
		niszczyciele[i] = ""
}

Funkcja reagująca na obrażenia zadawane workowi:

public Fw_PlayerTakeDamage(victim, idinflictor, idattacker, Float:damage, damagebits)
{
	new szTouched[16]
	pev(victim , pev_classname , szTouched , 15);
	
	if(equali(szTouched,"func_bags") && is_user_connected(idattacker))
	{
		new szHealth = pev(victim, pev_health);
		if (get_user_team(idattacker) == 2)
		{
			if (damage < szHealth)
				emit_sound(victim, CHAN_AUTO, g_soundhit[random(sizeof g_soundhit)], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
			if (damage > szHealth)
			{
				get_user_name(idattacker, niszczyciele[nr], 31)
				emit_sound(victim, CHAN_AUTO, g_sounddestroy, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
				ColorChat(0, GREEN, "%s zniszczyl kladke!", niszczyciele[nr])
				nr++
			}
		}
	}
	return HAM_IGNORED
}
Quote

  • +
  • -
Sooldierr's Photo Sooldierr 16.03.2015

Ktos wie dlaczego to nie spełnia swojego zadania? Nie wyswietla kto zniszczyl kladke.

Mam wrazenie, ze kladka jest zniszczona wczesniej, niz by wskazywalo na to jej zycie.

Dodalem komunikat wysiwrtlajacy stan zycia za kazdym trafieniem i wyniki oscylowaly okolo 400-500 HP.

A ma ustawione 1000 hp to i powinno do konca zjechac i dopiero zniknac?

Czy moze zle pobieram zycie?

public Fw_PlayerTakeDamage(victim, idinflictor, idattacker, Float:damage, damagebits)
{
	pev(victim , pev_classname , szTouched , 15);
	if(equali(szTouched,"func_bags") && is_user_connected(idattacker))
	{
		if (get_user_team(idattacker) == 2)
		{
			pev(victim, pev_health, szHealth);
			if (damage < szHealth)
			{
				emit_sound(victim, CHAN_AUTO, g_soundhit[random(sizeof g_soundhit)], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
				return HAM_IGNORED
			}
			if (damage >= szHealth)
			{
				get_user_name(idattacker, niszczyciele, 31)
				emit_sound(victim, CHAN_AUTO, g_sounddestroy, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
				ColorChat(0, RED, "[%s] ^x04zniszczyl kladke!", niszczyciele)
				return HAM_IGNORED
			}
		}
		else return HAM_IGNORED
	}
	else return HAM_IGNORED
}
Quote

  • +
  • -
Sooldierr's Photo Sooldierr 19.03.2015

Ok, znalazłem już przyczynę i poprawiłem ją. Teraz sprawa jest taka, że fragment:

if (damage >= szHealth)
	{
		get_user_name(idattacker, niszczyciele, 31)
		emit_sound(victim, CHAN_AUTO, g_sounddestroy, VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
		ColorChat(0, RED, "[%s] ^x04zniszczyl kladke!", niszczyciele)
		return HAM_IGNORED
	}

Wykonuje się dwa razy dla jednej kładki. Czym to może być spowodowane? W momencie gdy wartość obrażeń przewyższa wartość pozostałego HP kładki, powinno się wykonać raz, potem kładki już nie ma, nie istnieje. Wartość pozostałego życia zostaje pobrana przed zadaniem obrażeń. Dlatego nie można zrobić warunku:

 

szHealth <= 0

 

gdyż, nie da się tego sprawdzić, a raczej pobrać takiej wartości, bo nie ma z czego. 

Ktoś wie dlaczego tak się dzieje, że dwa razy wykonuje się ten warunek?

 

Poniżej załączam aktualny kod:

 

Attached Files

Quote

  • +
  • -
Sooldierr's Photo Sooldierr 20.03.2015

Można pobrać w jakiś sposób HP kładki po wykonaniu się wydarzenia Ham_TakeDamage a nie przed?

Quote

  • +
  • -
grankee's Photo grankee 22.03.2015


RegisterHam(Ham_TakeDamage, "func_wall", "Fw_PlayerTakeDamagePost", 1)
public Fw_PlayerTakeDamagePost(...
Quote

  • +
  • -
Sooldierr's Photo Sooldierr 22.03.2015

Juz to znalazlem, ale dziekuje za wypowiedz, bo ostatnio brak zainteresowania.

Jednak event Ham_TakeDamage wykonuje sie nadal choc nie zawsze dwa razy.

O ile wczesniej wykonywal sie przed ostatnim pociskiem rozwalajacym kladke i po nim;

to teraz jest tak, ze nie zawsze dwukrotnie, ale jak juz sie zdarzy to wlasnie po tym ostatnim pocisku rozwalajacym od razu dwukrotnie.

Czyli tak jakby plugin "nie nadaza usunac bytu"??

 

Prawdopodobnie wina lezy w tym, ze rejestrowanie obrazen sie nachodzi gdyz:

- oryginalnie w pluginie sprawdzanie czy obrazenia zadawane sa bytowi kladki, wykonywane jest za pomoca fakemeta (Think), aby plugin wiedzial kiedy usunac

- moj dodatek dodajacy dzwieki oraz info potrzebuje hamsandwich (Ham_Take_Damage), aby uzyskac info o atakujacym.

 

Mam racje?

Czy moge sprobowac przeniesc funkcje z fakemeta do hamsandwich, uzyskujac ten sam efekt, bez jakis szkod albo wad w takim wypadku?

Bo to zapewne bardzo nieoptymalne rozwiazanie, podwojne sprawdzanie

 

 

Quote

  • +
  • -
grankee's Photo grankee 23.03.2015

Niezbyt czaję ideę, daj kod wszystkiego co masz na chwilę obecną i dokładnie wyjaśnij co się dzieje.

Quote