Witamy w Nieoficjalnym polskim support'cie AMX Mod X
Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
Rozpoczynaj nowe tematy i odpowiedaj na inne
Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
Dodawaj wydarzenia do kalendarza społecznościowego
Stwórz swój własny profil i zdobywaj nowych znajomych
Witam. Postanowiłem trochę się rozpisać o entitach. Poradnik ten z założenia ma być długi i obszerny, a mój system pracy nie sprzyja więc czego nie skończę dziś, dopiszę jutro.
Entity to nic innego jak byty na mapie. Mapa (widzialna i namacalna bryła, wewnątrz której toczymy rozgrywkę wraz z jej wszystkimi elementami, które nie są odrębnymi bytami) sama w sobie też jest bytem o numerze 0.
Każde entity ma swój unikalny numer, raz nadany podczas tworzenia entity nigdy nie ulega zmianie. Oczywiście jeśli dany ent zostanie usunięty to jego numer zostaje "zwolniony" i może zostać on nadany kolejnemu entowi podczas jego tworzenia.
Entity posiada wiele właściwości, które z grubsza postaram się objaśnić. Podstawową sprawą jest, że ma kształt prostopadłościanu i jakiś model, czyli jakoś wygląda, ale model nie musi wcale się pokrywać z kształtem i wymiarami bytu. Do tworzenia lub modyfikacji tych właściwości możemy używać dwóch modułów - <engine> oraz <fakemeta>, jednak w tym tutorialu skupię się na tym pierwszym z prostego powodu - jest łatwiejszy i bardziej przejrzysty. Na koniec postaram się nie zapomnieć przedstawić przykładów użycia fakemety z tym samym skutkiem.
Te 3 ostatnie różnią się tym, że aktualizują zmienione dane w silniku gry. Koniecznie trzeba ich użyć, aby poprawnie stworzyć entity.
Pobierać te właściwości można funkcjami:
entity_get_byte(index,klucz)//zwraca returnem wartość typu int
entity_get_edict(index,klucz)//zwraca returnem wartość typu int
entity_get_float(index,klucz)//zwraca returnem wartość typu float
entity_get_int(index,klucz)//zwraca returnem wartość typu int
entity_get_string(index,klucz,tablica_znakow[],dlugosc_tablicy_znakow)//zwrot przez referencję do tablicy znaków podanej jako argument
entity_get_vector(index,klucz,tablica_float[3])//zwrot przez referencję do tablicy trójelementowej typu float
No dobra, ale co to jest ten klucz?
Jest to liczba całkowita określająca, którą właściwość chcemy sprawdzić/zmienić. Dla ułatwienia skorzystajmy z przygotowanych do tego elementów typu wyliczeniowego, dzięki czemu będziemy wiedzieli z grubsza co dany klucz nam zmieni.
Każda funkcja ma przygotowany dla siebie typ wyliczeniowy, osobny dla byte,edict,float,int,string i vector(postaram się uzupełniać, może ktoś coś podpowie):
Spoiler
Dla funkcji entity_get_int() oraz entity_set_int()
enum {
EV_INT_gamestate = 0,//stan gry-czy byt bierze udział w grze?
EV_INT_oldbuttons,//suma bitowa przycików naciskanych podczas trwania klatki, która właśnie minęła.
//Można w ten sposób np. sprawdzić oldbutton oraz button żeby dowiedzieć się
//czy klatkę temu gracz nie trzymał tego przycisku a teraz trzyma wciśnięty,
//to znaczy, że właśnie go nacisnął, a nie trzyma go już jakiś czas.
EV_INT_groupinfo,
EV_INT_iuser1,
EV_INT_iuser2,
EV_INT_iuser3,
EV_INT_iuser4,
EV_INT_weaponanim,//numer animacji broni, np przeładowanie, wyciąganie, przykręcanie/odkręcanie tłumika itp.
EV_INT_pushmsec,
EV_INT_bInDuck,//określa czy gracz jest w trakcie kucania. Ma wartość 1 od momentu gdy zaczniesz kucać
// i zmienia się nazad na 0 po uzyskaniu pozycji wyjściowej kucającej
EV_INT_flTimeStepSound,
EV_INT_flSwimTime,//odlicza w kółko od 1000 do 0 z prędkością ok. 1000/s jeśli trzymamy przycisk skoku w wodzie
EV_INT_flDuckTime,odlicza raz od ok. 1000 do 0 podczas wykonywania kucania
EV_INT_iStepLeft,//zmienia się podczas biegania, określa czy w danym momencie wykonujemy krok lewą nogą czy nie.
//Pomocne np. w określeniu dźwięku tupania, każda noga ma nieco inny odgłos.
EV_INT_movetype,//rodzaj poruszania się bytu//objaśnienie w dalszej części o tworzeniu bytu
EV_INT_solid,//Dotykalność bytu//objaśnienie w dalszej części o tworzeniu bytu
EV_INT_skin,
EV_INT_body,
EV_INT_effects,
EV_INT_light_level,//poziom jasności światła mapy w jakim byt się znajduje
EV_INT_sequence,//sekwencja modelu, np gracz trzyma ak, strzela z ak, trzyma nóż, macha nożem, dla każdego to inna wartość
EV_INT_gaitsequence,//sekwencja ruchu modelu, skok, kucnięcie itp
EV_INT_modelindex,
EV_INT_playerclass,
EV_INT_waterlevel,//poziom wody na jakim gracz się znajduje-0 nie jest w wodzie,1-wyskakuje z wody,2-pływa po wierzchu,3-jest pod wodą
EV_INT_watertype,
EV_INT_spawnflags,
EV_INT_flags,
EV_INT_colormap,
EV_INT_team,//ustala czy byt dotyczy jakiegoś teamu, np func_buyzone ma tu numer teamu dla którego działa, tj który team może kupować będąc na jego terenie.
EV_INT_fixangle,
EV_INT_weapons,
EV_INT_rendermode,
EV_INT_renderfx,
EV_INT_button,//suma bitowa naciskanych przycisków w momencie trwania obecnej klatki
EV_INT_impulse,
EV_INT_deadflag,//stan śmierci, 0-żywy, 1-przechodzi upada i przechodzi w zwłoki,2-już jest wolnym oglądaczem.
};
Dla entity_get_byte() oraz entity_set_byte()
enum {
EV_BYTE_controller1 = 0,//niektóre modele (podobno np. barney z hl) posiadają coś takiego jak kontroler ruchu głowy, ust itp. Myślę, że to właśnie do tego służy.
EV_BYTE_controller2,
EV_BYTE_controller3,
EV_BYTE_controller4,
EV_BYTE_blending1,//chyba też coś związane z modelem
EV_BYTE_blending2,
};
Dla entity_get_edict() oraz entity_set_edict()
enum {
EV_ENT_chain = 0,
EV_ENT_dmg_inflictor,
EV_ENT_enemy,
EV_ENT_aiment,
EV_ENT_owner,//posiadacz bytu, np. posiadaczem bytu broni jest gracz, który ją ma
EV_ENT_groundentity,
EV_ENT_pContainingEntity,//numer bytu
EV_ENT_euser1,
EV_ENT_euser2,
EV_ENT_euser3,
EV_ENT_euser4,
};
Dla entity_get_string() oraz entity_set_string()
enum {
EV_SZ_classname = 0,//nazwa klasy bytu
EV_SZ_globalname,
EV_SZ_model,//ścieżka do modelu bytu (czasem *numer np. *34 jeśli model nie jest osobny lecz wkompilowany w mapę)
EV_SZ_target,//np. dla przycisku to cel, np włącznik ma target "slight" a światło ma targetname "slight", nie wiem jak to dalej działa, ale tak wygląda.
//Inny przykład Button ma target CAMERA1, a ta kamera ma targetname CAMERA1 i po naciśnięciu przełącza gracza w widok z kamery
EV_SZ_targetname,//nazwa jako celu, to o czym pisałem wyżej, obiekt będący celem musi mieć tutaj nazwę taką jak przełączkin uruchamiający go ma w 'target'
EV_SZ_netname,//imię w sieci? w przypadku gracza jest to jego nick
EV_SZ_message,
EV_SZ_noise,//dźwięk jaki może wydawać byt w określonych okolicznościach, np drzwi mają dźwięk skrzypienia
EV_SZ_noise1,//jw
EV_SZ_noise2,//jw
EV_SZ_noise3,//jw
EV_SZ_viewmodel,//ścieżka do modelu jaki gracz widzi (kawałek rąk+broń)
EV_SZ_weaponmodel,//ścieżka do modelu broni jaki inni widzą u gracza w rękach
};
Dla entity_set_float() oraz entity_get_float()
enum {
EV_FL_impacttime = 0,
EV_FL_starttime,
EV_FL_idealpitch,
EV_FL_pitch_speed,
EV_FL_ideal_yaw,
EV_FL_yaw_speed,
EV_FL_ltime,//nie wiem jak to nazwać, ale np. na de_prodigy są drzwi, zmienna ta zlicza łączny czas kiedy drzwi są otwarte
EV_FL_nextthink,//czas następnego thinka bytu, czas wyrażony nie "za ile" lecz "kiedy", podajemy tutaj gametime() w którym ma think nastąpić
//czyli jak chcemy za sekundę to ustawiamy get_gametime()+1.0. Przykładowo granat po wyrzuceniu-powstaje byt, jego think jest za 4 sekundy, think następuje i granat wybucha.
EV_FL_gravity,//współczynnik grawitacji, tak zakładam. 1.0->normalna grawitacja, poniżej mniejsza,a powyżej większa
EV_FL_friction,//współczynnik tarcia bytu o byt, które to tarcie doprowadza do zatrzymywania się. j/w
EV_FL_frame,
EV_FL_animtime,//aktualnie odtwarzana klatka animacji modelu
EV_FL_framerate,//współczynnik klatek na sekundę, 1.0 normalna ilość klatek, mniej-mniejsza, więcej-większa
EV_FL_health,//aktualna ilość punktów zdrowia bytu
EV_FL_frags,//aktualna ilość fragów
EV_FL_takedamage,//nie wiem dokładnie, ale gracz ma 2.0, a na przykład kratka do stłuczenia 1.0
EV_FL_max_health,//maxymalne życie bytu, prawdopodobnie tyle punktów dostaje na spawnie
EV_FL_teleport_time,
EV_FL_armortype,
EV_FL_armorvalue,//ilość puntów pancerza
EV_FL_dmg_take,
EV_FL_dmg_save,
EV_FL_dmg,
EV_FL_dmgtime,
EV_FL_speed,
EV_FL_air_finished,//wartość gametime w który byt przestał być w powietrzu, ale nie chodzi tu o lot, a np. o moment w który wskoczył do wody.
EV_FL_pain_finished,//przychodzi mi do głowy spray na de_rats, moment w którym przestał obrywać sprayem np., ale do sprawdzenia
EV_FL_radsuit_finished,
EV_FL_scale,
EV_FL_renderamt,
EV_FL_maxspeed,//maxymalna prędkość bytu
EV_FL_fov,
EV_FL_flFallVelocity,//prędkość spadania bytu, jeśli wartość ujemna to byt porusza się w górę
EV_FL_fuser1,
EV_FL_fuser2,
EV_FL_fuser3,
EV_FL_fuser4,
};
Dla entity_get_vector() oraz entity_set_vector()
enum {
EV_VEC_origin = 0,//współrzędne bytu na mapie.
EV_VEC_oldorigin,
EV_VEC_velocity,//Prędkość poruszania się w poszczególnych kierunkach. Pamiętamy, że tu wartością jest tablica Float:tablica[3] tak więc
//tablica[0] to prędkość w osi x, tablica[1] to prędkość w osi y, a tablica[2] to prędkość w osi z
//jeżeli poruszamy się w kierunku ujemnych współrzędnych to prędkość także będzie ujemna
EV_VEC_basevelocity,
EV_VEC_clbasevelocity,
EV_VEC_movedir,
EV_VEC_angles,//kąt ustawienia modelu, w przypadku gracza kąt[0] to wartość od -29.6 (gdy patrzy w dół) do 29.6 (gdy parzy w górę),
//kąt[1] to kąt pod jakim jest obrócony byt, obracając się w kierunku współrzędnych ujemnych wartość jest od 0 do -179.9, w kierunku dodatnich od 0 do 179.9
EV_VEC_avelocity,
EV_VEC_punchangle,//kąty recoila, podczas strzału wzrastają i to właśnie tam leci pocisk.
EV_VEC_v_angle,//kąt patrzenia gracza, kat[0] -88.9 całkowicie patrzy w górę, 88.9 całkowicie w dół,
//kąt[1] to kierunek patrzenia, w kierunku ujemnych współrzędnych ujmeny, w kier. dodatnich dodatni
EV_VEC_endpos,
EV_VEC_startpos,
EV_VEC_absmin,//położenie na mapie rogu bytu najbardziej wysuniętego w kierunku współrzędnych ujemnych
EV_VEC_absmax,//położenie na mapie rogu bytu najbardziej wysuniętego w kierunku współrzędnych dodatkich
EV_VEC_mins,//odległość rogu najbardziej wysuniętego w kierunku współrzędnych ujemnych od originu
EV_VEC_maxs,//odległość rogu najbardziej wysuniętego w kierunku współrzędnych dodatnich od originu
EV_VEC_size,//rozmiar bytu, odległość mins od maxs,
EV_VEC_rendercolor,
EV_VEC_view_ofs,
EV_VEC_vuser1,
EV_VEC_vuser2,
EV_VEC_vuser3,
EV_VEC_vuser4,
};
Podzielmy entity ze względu na klasę.
Pierwsza podstawowa klasa bez jakiej gra nie zainstnieje to
player
Więcej o graczu:
Spoiler
To byt gracza, czyli po ludzku to ludzik biegający po mapie.Jest to najbardziej złożony byt w tej grze.
Specyficzne tylko dla gracza jest posiadanie kości oraz hitzonów.
Kości-jak sama nazwa wskazuje są to kości gracza tworzone wraz z modelem.
Ilość kości i ich położenie nie musi być stałe i takie samo dla każdego modelu. Dodatkowo są unikalne kości np kość "bomb" umieszczona na plecach modelu terrorysty lub kość "defuser" umieszczona w okolicach pasa CT'ka.
Kości numerowane są od 1 do ich ilości.
Położenie (origin) danej kości można sprawdzić funkcją z <fakemeta>
new Float:origin[3]
engfunc(EngFunc_GetBonePosition,id,origin)
Hitzony - są to miejsca w które gracz może oberwać pociskiem. Można ustawić miejsca w jakie gracz może oberwać (obrażenia zostaną zadane) za pomocą funkcji set_user_hitzones lub je sprawdzić funkcją get_user_hitzones. Obie funkcje z modułu <fun>. Miejsca można określić liczbą całkowitą, która jest sumą składowych poszczególnych części ciała:
func_bomb_target - w jego wnętrzu można podkładać pakę
weapon_usp, weapon_glock i cała reszta broni - broń posiadana przez gracza
func_wall - ściana, ale nie tylko, paradoksalnie chyba żadna ściana nie jest bytem tej klasy tylko częścią mapy. Praktycznie każdy obiekt może być tej klasy(np. skrzynka, barierka...), są to obiekty nie pełniące żadnej roli specjalnej a jedynie mają być i istnieć.
func_breakable - obiekt, który da się zniszczyć np. szyba, kratka do wentylacji, skrzynki niszczone wybuchem bomby i wiele innych
func_illusionary - ma model, czyli jakoś wygląda, ale nie zatrzymuje pocisków, nie blokuje ruchu.
trigger_multiple - byt o solidzie 1 czyli SOLID_TRIGGER, jego dotknięcie alarmuje go, ale nie blokuje ruchu, zwykle alarmuje inny byt do wykonania thinku, czyli jakiejś czynności, np drzwi do otwarcia się na de_prodigy.
func_door - drzwi
func_door_rotating - drzwi obrotowe
func_ladder - drabina
trigger_hurt - rani po dotknięciu go
Postaram się coś jeszcze dopisać.
No to trochę teorii za nami, teraz pora stworzyć nasze entity:
Załóżmy, że potrzebna nam ściana, której ścieżka do modelu to "models/wall/wall.mdl"
new byt=create_entity("func_wall")//funkcja tworzy byt klasy func_wall, zwracając numer powstałego entity, który przypisujemy zmiennej 'byt'
entity_set_model(ent,"models/wall/wall.mdl")
new Float:mins[3],Float:maxs[3]//aby powstał prostopadłościan (takiego kształtu jest entity) musimy rozciągnąć go w przestrzeni za przeciwległe rogi i to właśnie odległości od originu do tych rogów
//odpowiednio do rogu najbardziej wysuniętego w kierunku ujemnym
mins[0]=-112.0//oś x
mins[1]=-113.0//oś y
mins[2]=-1.0//oś z (góra-dół)
//oraz najbardziej wysniętego w kierunku dodatnim
maxs[0]=115.0
maxs[1]=116.0
maxs[2]=117.0
entity_set_size(ent,mins,maxs)//ustawia w/w odległości-czyli po prostu rozmiar
new Float:origin[3]
entity_get_vector(id,EV_VEC_origin,origin)//tu pobieram położenie gracza, aby z grubsza wiedzieć gdzie to entity umieścić, jeśli mam własne dane co do położenia,
//a nie interesuje nas położenie gracza, to przypisujemy dane do zmiennej origin[3]
origin[0]+=350.0//tu zmieniam położenie względem jednej z osi, żeby byt nie został stworzony na mnie (graczu) tylko w pobliżu
entity_set_origin(ent,origin)//ustawiam położenie bytu. Należy uważać, aby byt nie został stworzony w mapie, tzn jego część nie była schowana w podłodze, bo byt zacznie nam opadać powoli w dół aż zniknie całkowicie z pola widzenia. Dobrze ustawiony origin poskutkuje pojawieniem się nieruchomego bytu, ew pojawieniem się bytu i opadnięciem na ziemie.
entity_set_int(ent,EV_INT_solid,SOLID_BBOX)//ustawiamy dotykalność bytu (bez ustawionego movetype ( MOVETYPE_NONE ) nie przynosi efektu)
entity_set_int(ent,EV_INT_movetype,MOVETYPE_TOSS)//ustawiamy sposób poruszania się bytu, wybrany tutaj to po prostu kolidowanie z entitami, grawitacja
ważne, model musimy precachować:
public plugin_precache()
{
precache_model("models/wall/wall.mdl")
}
Możliwe SOLIDy:
#define SOLID_NOT 0 /* Brak interakcji z obiektami */
#define SOLID_TRIGGER 1 /* Tworzy dotyk (alarmując funkcje), ale nie blokuje (można przez niego przejść) */
#define SOLID_BBOX 2 /* Tworzy dotyk (alarmując funkcje), blokuje */
#define SOLID_SLIDEBOX 3 /* Tworzy dotyk, ale nie na ziemi(nie czaje o co chodzi:P-nie testowałem) */
#define SOLID_BSP 4 /* Część mapy, tworzy dotyk (alarmując funkcje), blokuje */
Możliwe movetype'y:
#define MOVETYPE_NONE 0 /* nie porusza się */
#define MOVETYPE_ANGLENOCLIP 1 /* nie mam pojęcia - crashuje serwer jak ustawię */
#define MOVETYPE_ANGLECLIP 2 /* nie porusza się */
#define MOVETYPE_WALK 3 /* Tylko gracz tego używa - chodzenie po ziemi - ustawisz innemu entity=crash */
#define MOVETYPE_STEP 4 /* gravity, special edge handling -- monsters use this */
#define MOVETYPE_FLY 5 /* Koliduje z elementami mapy/entami, ale nie działa nań grawitacja */
#define MOVETYPE_TOSS 6 /* Koliduje z elementami mapy/entami, działa nań grawitacja */
#define MOVETYPE_PUSH 7 /* no clip to world, push and crush - nie testowałem, ale entity z solid_bsp mają ten movetype */
#define MOVETYPE_NOCLIP 8 /* Może posiadać prędkość tzn poruszać się, ale nie koliduje i nie działa nań grawitacja */
#define MOVETYPE_FLYMISSILE 9 /* extra size to monsters */
#define MOVETYPE_BOUNCE 10 /* Tak jak TOSS, ale odbija się od wszystkiego */
#define MOVETYPE_BOUNCEMISSILE 11 /* Odbija się, ale nie działa nań grawitacja */
#define MOVETYPE_FOLLOW 12 /* Śledzi ruchy celu (EV_ENT_aiment ?) */
#define MOVETYPE_PUSHSTEP 13 /* BSP model that needs physics/world collisions (uses nearest hull for world collision) */
new classname[32]
entity_get_string(id,EV_SZ_classname,classname,31)
pev(id,pev_classname,classname,31)
Teraz już wiecie jak stworzyć swoje entity. Postaram się uzupełniać w wolnych chwilach, a także po waszych sugestiach i uwagach, na które bardzo liczę. Jak zbierzemy do kupy wiedzę paru osób to może powstać z tego na prawdę dobry poradnik.
Użytkownik grankee edytował ten post 10.12.2014 02:30
Lokalizacja:C: / program Files / Valve / Cstrike / G[o]Q.dem
Offline
Napisano 09.12.2014 21:37
#define MOVETYPE_FOLLOW 12/* Śledzi ruchy celu (EV_INT_owner ?) */
pev_aiment
i mysle ze fakemeta jest fajniejsza latwiejsza i ogólnie lepiej się z nią pracuje dodatkowo nie napisales nic o info_target reszta na +
//size i origin zawsze ustawialem pev'em i bylo ok w sumie model chyba też
0
Manual ponad wszystko, konsola ponad manual :&
Chcesz wysłać do mnie PW ? użyj nazwy GoQ zamiast G[o]Q Chcesz Kupić moduł płatności via Pukawka,Tserwery, Gamesol, Zabijaka do mojego sklepu? napisz PW cena to tylko 10 zł/sztuka
GG:6022845 (nie pomagam za free osobom ponizej rangi MoD)
i mysle ze fakemeta jest fajniejsza latwiejsza i ogólnie lepiej się z nią pracuje
Dla mnie teraz też, ale na początku engine był dla mnie bardziej przejrzysty, wiedziałem, że jak coś jest EV_INT to ma być liczba całkowita, jak EV_FL to float itd. Jak ktoś ogarnie to w engine to spokojnie sobie poradzi z przejściem na FM
dodatkowo nie napisales nic o info_target
Będę wdzięczny jak wtrącisz swoje 3 grosze i napiszesz parę słów na jego temat, bo sam nie bardzo wiem co to jest i komu to potrzebne
hmmm bytu jako takiego, który by zatrzymał kule to się raczej zrobić nie da, ale możesz spróbować get_user_aim(id), jesli patrząc na ściane zwróci id tejże ściany to w ham_takedamage dajesz get_user_aim(attacker) i jeśli zwróci ściany id to blokujesz obrażenia, bo to znaczy, że w momencie strzału miał celownik na ścianie.
Nie do końca będzie to sprawne, bo między ścianą a graczem może być coś jeszcze, wtedy nie zblokuje obrażeń i jeśli będzie dość mocna broń (awp) to ktoś za ścianą też oberwie.
Inna opcja to wykrywanie obrażeń zadanych ścianie, zwrócenie jej hp (aby nie dało się jej zniszczyć), blokada zadawania obrażeń dla attackera na ułamek sekundy(najdłużej do momentu oddania kolejnego strzału). Wtedy obiekt przed ścianą dostanie obrażenia, ale już ten za ścianą będzie miał zblokowane. Oczywiście też w ham_takedamage.
Użytkownik grankee edytował ten post 25.05.2016 21:58
Lokalizacja:C: / program Files / Valve / Cstrike / G[o]Q.dem
Offline
Napisano 13.06.2016 16:37
robisz traceline'a jesli gosc strzela w gracza amiedzy nimi jest twoj byt to blokujesz obrazenia i tyle
1
Manual ponad wszystko, konsola ponad manual :&
Chcesz wysłać do mnie PW ? użyj nazwy GoQ zamiast G[o]Q Chcesz Kupić moduł płatności via Pukawka,Tserwery, Gamesol, Zabijaka do mojego sklepu? napisz PW cena to tylko 10 zł/sztuka
GG:6022845 (nie pomagam za free osobom ponizej rangi MoD)