←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

Ściana itp. pomiędzy 2 entami

Zablokowany

  • +
  • -
SeeK - zdjęcie SeeK 10.03.2013

Witam, mam takie pytanie. Jak sprawdzić, czy 2 enty mogą się zobaczyć? Używanie entity_set_aim i potem is_visible się nie sprawdza. Można jakoś sprawdzić, czy jeden ent może zobaczyć drugiego? Wydaje mi się, że przydałoby się tutaj jakiegoś traceline użyć, ale do końca jeszcze tego nie łapię. Gdyby ktoś mógł pomóc, byłbym bardzo wdzięczny :)
Użytkownik SeeK edytował ten post 10.03.2013 23:46
Odpowiedz

Gość_21977_* 11.03.2013

1. Możesz puścić fakemetowe EngFunc_TraceLine i odczytać TR_pHit. Jeśli jest równe -1 (czyli mniejsze od 0), to oznacza, że linia w nic nie uderzyła, czyli byty powinny się widzieć.Osobiście napisalem sobie krótką funkcyjkę do tego:
public are_visible(Float:start[3], Float:end[3]){
new tr;
engfunc(EngFunc_TraceLine, start, end, IGNORE_MONSTERS, -1, tr);
return (get_tr2(tr, TR_pHit)<0);
}


2. Inną metodą jest puszczenie linii i sprawdzenie, ile trasy przebyła (z zakresu 0.0 do 1.0)
Jeśli przebyła całą drogę, czyli 1.0, to między entami nie powinno być ściany.

W poście z drugiego linku, ot_207 podał stock sprawdzający dokładnie to, o co prosisz w nazwie tematu.
stock is_wall_between_points(Float:start[3], Float:end[3], ignore_ent)
{
// Create the trace handle! It is best to create it!
new ptr = create_tr2()

// The main traceline function!
// This function ignores GLASS, MISSILE and MONSTERS!
// Here is an example of how you should combine all the flags!
engfunc(EngFunc_TraceLine, start, end, IGNORE_GLASS | IGNORE_MONSTERS | IGNORE_MISSILE, ignore_ent, ptr)

// We are interested in the fraction parameter
new fraction
get_tr2(ptr, TR_flFraction, fraction)

// Free the trace handle (don't forget to do this!)
free_tr2(ptr)

// If = 1.0 then it didn't hit anything!
return (fraction != 1.0)
}


3. Engine bez zbędnych ceregieli pozwala nam na sprawdzenie, czy dwa byty się widzą za pomocą funkcji is_visible
4. Fakemeta util nie pozostaje w tyle: fm_is_visible
5. Metoda HamSandwich:
ExecuteHam(Ham_FVisible, id_bytu_1, id_bytu_2);
Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 11.03.2013

Którą metodę lepiej stosować 1 czy drugą? Wydaje mi się, że obydwie są tak samo dobre, ale chciałbym się was o zdanie zapytać. 3, 4 - są trochę "szitowe" bo po pierwsze z niewiadomych przyczyn nie działają mi na innej animacji jak 0 i ponadto jak są plecami do siebie to wtedy zwraca, że się nie widzą(co jest logiczne, ale mi potrzeba aby zwracało prawdę, nawet jak są odwróceni do siebie plecami). Poza tym ta funkcja is_visible coś nie do końca działa tak jak powinna. A co do 5, to jej nie sprawdzałem, ale pewnie będzie działać na podobnej zasadzie jak 3 i 4.

Tak swoją drogą, wielkie dzięki Benio ;)
Odpowiedz

  • +
  • -
d0naciak - zdjęcie d0naciak 11.03.2013

Ja bym użył metody 1
Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 11.03.2013

Bienio niestety, ale ani pierwsza ani druga funkcja nie działa... Ktoś wie może dlaczego?
Odpowiedz

Gość_21977_* 11.03.2013

Metoda 5 bardzo dobrze mi działa dla graczy, dla bytów spoza klasy "player" nie używałem, więc nie podpowiem.
O metodach 3 i 4 wiem, że są, ale nigdy z nich nie korzystałem.

Metody 1 i 2 działają dla punktów w wolnej przestrzeni, jeśli na jej choć jednym krańcu znajdzie się byt o niezerowym rozmiarze, to linia uderzy
w brzeg sizeboxu bytu, przez co nie dotrze do punktu pozycji bytu. Należy w takim razie zignorować niezerowe byty, które tracelinujesz (ignore_ent).

W Twoim przypadku, przydatne się wyda tracelinowanie od jednego bytu (ignorując go) w stronę drugiego.
Jeśli byt, w którego traceline uderzy, będzie tym drugim, to byty widzą się nawzajem.

Intuicyjnie, napisałem stocka pod byty o niezerowym rozmiarze z komentarzami
/*
returns true if entities are visible, false otherwise
ent1, ent2 - id of entities
*/
stock bool:ents_are_visible(ent1, ent2){
new Float:origin1[3], Float:origin2[3], tr;

// Pobranie pozycji bytów
pev(ent1, pev_origin, origin1);
pev(ent2, pev_origin, origin2);

// Traceline od bytu 1 (i zignorowanie go, inaczej od razu linia by w niego uderzyła)
engfunc(EngFunc_TraceLine, origin1, origin2, IGNORE_GLASS | IGNORE_MONSTERS | IGNORE_MISSILE, ent1, tr);

// Sprawdzenie, czy linia uderzyła w byt 2
return (get_tr2(tr, TR_pHit)==ent2);
}
Odpowiedz

  • +
  • -
sebul - zdjęcie sebul 11.03.2013

Jest jeszcze jeden sposób w engine
stock bool:ECan_Trace_Line(ent, target, Float:dist = 30.0, ignoredent = 0) {
new Float:Eorigin[3], Float:Torigin[3], Float:Rorigin[3];
entity_get_vector(ent, EV_VEC_origin, Eorigin);
entity_get_vector(target, EV_VEC_origin, Torigin);

trace_line(ignoredent, Eorigin, Torigin, Rorigin);

return bool:(get_distance_f(Torigin, Rorigin) < dist);
}

Czyli pobranie położenia dwóch entów, a potem sprawdzenie odległości pomiędzy położeniem drugiego entu, a położeniem gdzie udeżyło traceline. Jeśli ta odległość jest większa od mniej więcej 30 jednostek, tzn. że dwa enty nie widzą się nawzajem, choć trzeba tutaj zaznaczyć, że to nie jest dokładny sposób, bo chociażby jeśli jeden gracz będzie gdzieś wysoko stał i będzie prawie cały zasłonięty jakąś grubszą ścianą, to wtedy funkcja może zwrócić fałsz, czyli że gracz nie jest widoczny.
Odpowiedz

  • +
  • -
SeeK - zdjęcie SeeK 12.03.2013

Benio dzięki, działa :)
Odpowiedz
Zablokowany