|
|
| |
| ZASOBY |
| |
| |
|
|
|
| |
|
| NASZ BUTTON |
|
|
| |
|
|
| |
|
| |
|
TUTORIALE - CODING
|
[ Dodaj ]
|
|
Imię dla NPC_CITIZEN
| [ 2005-08-19 14:58:26 Dodał:
mefi Wyświetleń: 2029 Komentarzy: 4 ]
|
|
Dziś zrobimy aby NPC_CITIZEN, był mniej anonimowy i miał namiastkę osobowości. Zrobimy to dodając mu imię. Imię te będziemy wpisywać w Hamerze jako właściwość bytu i będzie się ono pokazywało nad głową NPC po na celowaniu na niego (podobnie jak w CS).
Zaczniemy od edycji pliku HALFLIFE2.FGD znajdującego się w katalogu gdzie jest Hammer. Otwieramy plik i szukamy tekstu npc_citizen. Teraz pod tą częścią kodu:
citizentype(choices) : "Type" : "Default" =
[
0 : "Default"
1 : "Downtrodden"
2 : "Refugee"
3 : "Rebel"
4 : "Unique"
] |
dopisujemy:
citizentype(choices) : "Type" : "Default" =
[
0 : "Default"
1 : "Downtrodden"
2 : "Refugee"
3 : "Rebel"
4 : "Unique"
]
imie(string) : "Imie" |
Teraz możemy włączyć Hamera i każdemu bytowi NPC_CITIZEN wpisać inne imię. Kolejną czynnością jest oczywiście modyfikacja kodu. Otwieramy projekt serwera i plik NPC_CITIZEN17.H. Szukamy w nim tekstu: FixupMattWeapon() i pod nim dopisujemy:
void FixupMattWeapon();
virtual bool KeyValue( const char *szKeyName, const char *szValue ); |
Jest to deklaracja funkcji służącej do odczytu właściwości bytów które ustawiamy w Hamerze. Dalej szukamy SelectSchedule() i pod tym dopisujemy:
int SelectSchedule();
string_t m_iszImie; |
Zadeklarowaliśmy właśnie zmienną do której będziemy przypisywać imię NPC, które wpisaliśmy przy tworzeniu planszy. Następny plik do modyfikacji to NPC_CITIZEN17.CPP . Szukamy: #define COMMAND_POINT_CLASSNAME "info_target_command_point" i za tym wklejamy następujący kod:
bool CNPC_Citizen::KeyValue( const char *szKeyName, const char *szValue )
{
if (FStrEq(szKeyName, "Imie"))
{
m_iszImie = AllocPooledString(szValue);
}
else
return BaseClass::KeyValue( szKeyName, szValue );
return true;
} |
W tym samym pliku szukamy BEGIN_DATADESC( CNPC_Citizen ) i w dowolnym miejscu dopisujemy:
DEFINE_KEYFIELD( m_iszAmmoSupply, FIELD_STRING, "ammosupply" ),
DEFINE_KEYFIELD( m_iszImie, FIELD_STRING, "imie" ),
|
Ten cały blok BEGIN_DATADESC służy do operacji SAVE/LOAD. Czyli jak chcemy zapisać jakąś zmienną do sava to wstawiamy ją w taki blok. Na początku podajemy co zapisujemy czy zwykłe pole czy tablicę itp. (definicję wszystkich opcji zapisu znajdziecie w pliku DATAMAP.H), dalej podajemy nazwę naszej zmiennej i jej typ, u nas jest to string. Nasza zmienna z imieniem musi być zapisana, gdyż inaczej po wczytaniu save-a była by pusta. Wynika z tego że engine gry tylko raz odczytuje właściwości bytu na starcie mapy, a przy wczytaniu save-a już nie. Po tych zmianach NPC ma już swoje imie, ale jeszcze trzeba je wyświetlić, zrobimy to w pliku PLAYER.CPP. Na początek musimy dołączyć plik NPC_CITIZEN17.H do pliku playera.
#include "tier0/memdbgon.h"
#include "hl2_dll/npc_citizen17.h" |
Dzięki temu będziemy mogli korzystać z klas i zmiennych zawartych w tym pliku. Teraz szukamy funkcji CBasePlayer::UpdateClientData. Funkcja ta jest wykonywana z każdym cyklem gry więc służy dobrze jako miejsce gdzie można aktualizować cały czas dane. Na początku jej wklejamy kodzik, który będzie wyświetlał imię NPC, a przy okazji jeszcze jego stan energii:
void CBasePlayer::UpdateClientData( void )
{
Vector forward, up;
EyeVectors( &forward, NULL, &up );
trace_t tr;
Vector searchCenter = EyePosition();
UTIL_TraceLine( searchCenter, searchCenter + forward * 9000.0f, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
CBaseEntity *entity = tr.m_pEnt;
if ( entity )
{
if (FClassnameIs( tr.m_pEnt, "npc_citizen" ))
{
CNPC_Citizen *pWskaznik = assert_cast(tr.m_pEnt);
const char *tekst = NULL;
if (FStrEq(STRING(pWskaznik->m_iszImie),""))
tekst = "Anonim";
else
tekst = STRING(pWskaznik->m_iszImie);
char temp[512];
Q_snprintf( temp, sizeof(temp), "Imie: %s Zdrowie: %i", tekst, pWskaznik->m_iHealth );
NDebugOverlay::Text( tr.m_pEnt->EyePosition()+Vector(0,0,10),temp, true, 0.0 );
}
} |
Teraz opisze w skrócie algorytm działania tego kodu. Na początku musimy wysyłamy wiązkę, linię czy jak to nazwać zaczynającą się od pozycji gracza na odległość przez nas zdefiniowaną. Służy do tego funkcja UTIL_TraceLine. W funkcji tej należy podać początek skąd ma wychodzić promień (współrzędne 3D podawane w postaci wektora)oraz na jaką długość jest tworzony promień, u nas daliśmy 9000 czyli nawet daleko stojąc od NPC pokaże się jego imie. W funkcji tej podać też należy co blokuje wiązke czyli przez co nasza wiązka potrafi przejść. W naszym przypadku MASK_SOLID i COLLISION_GROUP_NONE. Jeżeli w coś trafiliśmy to sprawdzamy czy jest to nasz NPC. Sprawdzać będziemy po klasie bytu i użyjemy do tego fukcji FClassnameIs. My szukamy bytu NPC_CITIZEN więc właśnie to musimy wpisać. Następnie musimy utworzyć jakiś wskaźnik i przypisać mu klasę naszego znalezionego bytu. Musimy to zrobić aby odczytać jego poszczególne właściwości czyli imię i zdrowie. Następnie sprawdzamy czy nasz byt ma zdefiniowane imię czyli jak tworzyliśmy go w Hamerze to czy przypadkiem pole imię nie zostało puste. Jeżeli się tak stało to wyświetlimy imię Anonim. Ostatnią czynnością jest wyświetlenie pobranych danych na ekranie. Posłużymy się funkcją którą wykorzystuje się w trybie Debug do testowania i wyświetlania danych diagnostycznych. Funkcja ta nazywa się NDebugOverlay::Text. Jest on o tyle fajna że wyświetla tekst w przestrzeni 3D. Więc idealnie się nada, aby wyświetlić imię i zdrowie NPC nad jego głową. Pobierzemy więc pozycje oczu bytu tr.m_pEnt->EyePosition() i dodamy 10 do wektora Z ( Vector(0,0,10) ) po to by napis pojawiał się nad głową a nie na głowie. Obrazek po niżej pomoże wam zrozumieć jak w przestrzeni 3D przedstawiają się wektory X,Y,Z.
Oczywiście kod ten można jeszcze rozbudować o losowe generowaniu imion dla NPC, ale zostawiam to już wam.
Na koniec jeszcze taka uwaga, że ten tutorial napisałem opierając się tylko o kod SDK z niego biorąc przykłady. Więc jak nie wiecie jak coś zrobić wzorujcie się na kodzie. A tak w grze wygląda efekt naszego tutorialu:

|
|
|
| |
| KOMENTARZE |
|
| [ 2006-07-25 22:37:50 Dodał:
Mafioz ]
|
|
|
|
Dupa dupa dupa o_O Błędy przy tworzeniu .dll |
| |
| [ 2006-07-26 09:04:09 Dodał:
mefi ]
|
|
|
|
Jakie błędy? |
| |
| [ 2006-07-26 10:11:51 Dodał:
Mafioz ]
|
|
|
http://img224.imageshack.us/img224/8600/sdk2nu7.jpg
No i zauważyłem błąd
Zadeklarowaliśmy właśnie zmienną do której będziemy przypisywać imię NPC, które wpisaliśmy przy tworzeniu planszy. Następny plik do modyfikacji to NPC_CITIZEN.CPP* . Szukamy: #define COMMAND_POINT_CLASSNAME "info_target_command_point" i za tym wklejamy następujący kod:
* To chyba było NPC_CITIZEN17.CPP |
| |
| [ 2006-08-10 11:11:48 Dodał:
mefi ]
|
|
|
|
TaK CITIZEN17.CPP |
|
|
|
|
|
| |
|
|
| |
| SHOUTBOX |
|
MoonBlaze: ciasto is a lie |
|
zwieracz: Przyłącz się do mnie, mam ciasto |
|
Jodla: <kontemplujac stwierdza iz obecna rzeczywistosc jest do bani> |
|
MoonBlaze: sm_ban @Dabu 1 |
|
Dabu: Ta strona umarła, zapraszam lepiej na heacrab.pl :D [/koniec reklamy] |
|
Jodla: open beta nowego gmoda a tu 0 info na stronie ...może czas to zmienic zwłaszcza iż screeny z GM13 wygladaja apetycznie |
|
Dabu: web 3.0 |
|
Elektryk: Link |
|
Tracha: Ruski gracz! |
|
zwieracz: Za moich czasów, to się bawilismy przy takiej gierce, gdzie zając łapaj kury za jaja. A moze to był wilk. |
|
| |
|
|
|