NPC, Non Player Character yani Türkçe karşılığı ile Oyuncu olmayan karakterdir. Bu derste ayrıntılı bir şekilde açıklayarak anlatacağım. Bu ders biraz ileri seviye olabilir. Düzenleyerek kullana kullana öğrenebilirsiniz. Bunun için bilinmesi gereken kütüphaneler,

fakemeta,
engine,
hamsandwich

Fakemeta ve engine kütüphaneleri kod bakımından birbirine çok benzer ama çalışma mantıkları farklıdır. Evet zor kütüphaneler ama ingilizce oldukları ve Türkçe kaynak olmadığı için zor geliyor. Mantığını kavrayabilirsek eğlenceli hale gelebiliyor.


Gelelim konumuza, NPC yani oyuncu olmayan karakter, adından da anlaşılacağı gibi herhangi bir oyuncu tarafındandan yönetilmez, sanal zekadır. Çoğu oyunda karşılaşırız mesela en anlamlı örnek, Half-Life' da karşılaştığımız her yaratık, insan, bilim adamı vb. birer NPC dir. Yönetilmezler. Onlar için daha önceden belirlenmiş belli başlı görevleri yaparlar. Bizde CS' de bu şekilde NPC yapabiliriz. Peki NPC ile neler yapabiliriz? Oyun içinde bir market, size sadık bir köpek, bir zombi, size yardım eden bir asker vb. bu şekilde sırayabiliriz. Yani bu NPC işiyle ortaya çok eğlenceli işler çıkabiliyor.

Bu derste biz NPC' ye ne yaptıracağız?

*NPC' yi öldürebileceğiz.
*NPC' yi konuşturacağız.
*NPC'yi hareket ettireceğiz.( şimdilik olduğu yerde )

Öncelikle gerekli kütüphaneleri girelim.

PHP- Kodu:
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <engine>
#include <hamsandwich> 
Şimdi de plugin için gerekli değişken ve sabit değerleri tanımlıyoruz. Burada NPC için ses, model ve sayısal değişkenleri tanımlayacağız. Buradaki sesleri değiştirebilirsiniz. Ancak modeli değiştirirseniz animasyonlar farklı olabileceği için sorun çıkabilir. Farklı modeller kullanacaksanız Jed's Half-Life Model Viewer programını kullanarak model için gerekli animasyonları seçebilirsiniz. Bunun için de programda bulunan squences bölümünü açın ve oradan hareketi seçip squence# nin karşısındaki sayıyı not alın. Bu sayı model için o hareketin değeridir. Daha sonra değişkendeki sayı değerini not aldığınız sayı ile değiştirebilirsiniz.

PHP- Kodu:
#define PLUGIN "NPC - Non Playar Character - Oyuncu Olmayan Karakter"
#define VERSION "1.0"
#define AUTHOR "peNgueN"

//NPC oldu mu yasiyor mu ?
new boolg_NpcOldu512 ]; 

//NPC Entity Ismi
new const NpcClass[] = "entity_npc"

//NPC Hareketleri
new const g_NpcIdleAnimations[] = { 1314151617 }; //NPC Durus Animasyonlari
new const g_NpcDamageAnimations[] = { 8910 }; //NPC Hasar Animasyonlari
new const g_NpcDeathAnimations[] = { 313233343536 }; //NPC Olum Animasyonlari
new const g_NpcTalkAnimations[] = { 5960616263 }; //NPC Konusma Hareketleri

//NPC kan efektleri
new npc_kan_sprnpc_kan_spr_sprey;

//NPC Modeli
new const g_NpcModel[] = "models/hostage.mdl";

//NPC Sayisi
new NpcSayisi;

//NPC Sesleri
new const g_NpcOlumSesi[][] =  {
    
    
"barney/ba_die1.wav"
    
"barney/ba_die2.wav"
    
"barney/ba_die3.wav" 


new const 
g_NpcHasarSesi[][] = {
    
    
"barney/ba_pain1.wav"
    
"barney/ba_pain2.wav"
    
"barney/ba_pain3.wav" 
}

new const 
g_NpcKonusma[][] = {
    
    
"barney/dontaskme.wav"
    
"barney/haybuddy.wav"
    
"barney/hayfella.wav",
    
"barney/hellonicesuit.wav",
    
"barney/howyoudoing.wav"
    

Daha sonra plugin başlangıcını yazıyoruz.( plugin_init ) Burada NPC için gerekli kodları gireceğiz ve model, sesleri yükleyeceğiz.

PHP- Kodu:
public plugin_init()
{
    
register_pluginPLUGINVERSIONAUTHOR );
    
    
//NPC Kontrol Menusu
    
register_clcmd"say /npc""NpcMenu" );
    
register_clcmd"say_team /npc""NpcMenu" );
    
    
//NPC Kontrol Fonksiyonlari
    
RegisterHamHam_TakeDamage"info_target""fw_NpcTakeDamage" ); //Hasar Fonksiyonu
    
RegisterHamHam_Killed"info_target""fw_NpcKilled" ); //Olum Fonksiyonu
    
RegisterHamHam_Think"info_target""fw_NpcThink" ); //Beyin Fonksiyonu
    
RegisterHamHam_TraceAttack"info_target""fw_NpcTraceAttack" ); //Mermi Fonksiyonu
    
RegisterHamHam_Touch"info_target""fw_NpcTouch" ); //Dokunma Fonksiyonu
}

public 
plugin_precache( )
{
    
npc_kan_spr precache_model"sprites/blood.spr" );
    
npc_kan_spr_sprey precache_model"sprites/bloodspray.spr" );
    
    
precache_modelg_NpcModel );
    
    for( new 
sizeof g_NpcOlumSesi i++)
        
precache_soundg_NpcOlumSesi] );
    
    for( new 
sizeof g_NpcHasarSesi i++)
        
precache_soundg_NpcHasarSesi] );
    
    for( new 
sizeof g_NpcKonusma i++)
        
precache_soundg_NpcKonusma] );    
    

Şimdi NPC için kontrol menüsü yapalım. NPC oluşturup, kaldırabilmek için.

PHP- Kodu:
public NpcMenuid )
{
    new 
iMenu64 ];
    
formatexiMenucharsmaxiMenu ), "NPC - Oyuncu Olmayan Karakter" );
    new 
menu menu_createiMenu"NpcMenu_go" );
    
    
formatexiMenucharsmaxiMenu ), "\wNPC Olustur \y( Aim ile yer belirleyin )" );
    
menu_additemmenuiMenu"1" );
    
formatexiMenucharsmaxiMenu ), "\wNPC Kaldir \y( Aim ile secin )" );
    
menu_additemmenuiMenu"2" );
    
formatexiMenucharsmaxiMenu ), "\wButun NPC'leri Kaldir^n \y  %d NPC Mevcut"NpcSayisi );
    
menu_additemmenuiMenu"3" );
    
    
menu_setpropmenuMPROP_EXITMEXIT_ALL);
    
menu_setpropmenuMPROP_EXITNAME"\rCIKIS" );
    
    
menu_display(idmenu);
    return 
PLUGIN_HANDLED;
}

public 
NpcMenu_goidmenuitem )
{
    
    if( 
item == MENU_EXIT )
    {
        
menu_destroymenu );
        return 
PLUGIN_HANDLED;
    }
    
    new 
info], szName64 ];
    new 
accesscallback;
    
    
menu_item_getinfomenuitemaccessinfocharsmaxinfo ), szNamecharsmaxszName ), callback );
    
    new 
key str_to_numinfo );
    
    switch( 
key )
    {
        case 
1:
        {
            if( !
is_user_aliveid ) ) return PLUGIN_HANDLED;
            
            
NpcOlusturid );
        }
        case 
2:
        {
            if( !
is_user_aliveid ) ) return PLUGIN_HANDLED;
            
            new 
iEntVucutNPC64 ];
            
get_user_aimingidiEntVucut );
            
            if ( 
is_valid_entiEnt ) ) 
            {
                
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
                
                if ( 
equalNPCNpcClass ) ) 
                {
                    
remove_entityiEnt );
                    
NpcSayisi--;
                    
client_printidprint_chat"[NPC] Bir NPC Kaldirildi." );
                }
                
            }
        }
        case 
3:
        {
            
remove_entity_nameNpcClass );
            
NpcSayisi 0;
            
client_printidprint_chat"[NPC] Butun NPC'ler Kaldirildi." );
        }
    }
    
    
    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;

Şimdi de NPC'nin hamsandwich ile oluşturduğumuz kontrol fonksiyonlarını ekleyelim. Burada NPC için, öldürme, dokunma, düşünme ve saldırma fonksiyonları bulunuyor.

PHP- Kodu:
//NPC'ye dokundugumuzda bizmle konusacak ve hareket edecek.
public fw_NpcTouchiEntid 
{
    if( !
is_user_aliveid ) )
        return 
HAM_SUPERCEDE;
    
    
//Sadece 1 kere çalismasi için kontrol ediyoruz.
    
static FloatgametimeFloatCooldown32 ]; 
    
gametime get_gametime();
    
    if(
gametime 1.0 Cooldownid ] )
    {
        
//NPC kontrolu yapiyoruz. Burada NPC mizin ClassName yani ismini sorgulayarak onu baska nesnelerden ayiriyoruz.
        //Sadece bizim NPC mizde calismasi icin kontrol ediyoruz. Duvara degdiginde konusmasini istemeyiz :)
        
new NPC64 ];
        
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
        
        if( 
equaliNPCNpcClass ) )
        {
            
//NPC'ye dokundugumuzda hareket edecek. Hareketleri g_NpcTalkAnimations degiskeninden aldik.
            
Util_PlayAnimationiEntg_NpcTalkAnimationsrandomsizeof g_NpcTalkAnimations ) ] );
            
//NPC'ye dokunudugumuzda bizimle konusucak. Sesleri g_NpcKonusma degiskeninden aldik.
            
emit_soundiEntCHAN_VOICEg_NpcKonusmarandomsizeof g_NpcKonusma ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
        }
        
        
Cooldownid ] = gametime;
    }
    return 
HAM_IGNORED;
}

//NPC'ye hasar verdigimizde hareket edecek ve bagiracak.
public fw_NpcTakeDamageiEntinflictorattackerFloat:damagebits )
{
    
//NPC kontrolu yapiyoruz. Burada NPC mizin ClassName yani ismini sorgulayarak onu baska nesnelerden ayiriyoruz.
    
new NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//NPC'ye hasar verdigimizde hareket edecek. Hareketleri g_NpcDamageAnimations degiskeninden aldik.
        
Util_PlayAnimationiEntg_NpcDamageAnimationsrandomsizeof g_NpcDamageAnimations ) ], 1.25 );
        
//NPC'ye hasar verdigimizde bagiracak. Sesleri g_NpcHasarSesi degiskeninden aldik.
        
emit_soundiEntCHAN_VOICEg_NpcHasarSesirandomsizeof g_NpcHasarSesi ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
    }
}

//NPC'yi olduruyoruz.
public fw_NpcKillediEntKiller )
{
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//g_NpcOldu degiskenini dogru tanimladik.
        
g_NpcOlduiEnt ] = true;
        
//NPC oldugunde olum animasyonu calisacak.
        
Util_PlayAnimation(iEntg_NpcDeathAnimationsrandomsizeof g_NpcDeathAnimations ) ] );
        
//Oldugunde NPC'nin içinden geçebiliriz. SOLID_NOT entity nin içinden geçilmesini kapatir.
        
entity_set_intiEntEV_INT_solidSOLID_NOT );
        
//NPC'yi olu olarak tanimladik.
        
entity_set_intiEntEV_INT_deadflagDEAD_DEAD );
        
//NPC'nin cesedinin hasar almasini kapattik.
        
entity_set_float(iEntEV_FL_takedamage0.0 ); 
        
//NPC oldugunde bagiracak.
        
emit_soundiEntCHAN_VOICEg_NpcOlumSesirandomsizeof g_NpcOlumSesi ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
        
        
client_printKillerprint_chat"[NPC] NPC'yi oldurdunuz." );
        
        
//NPC oldugunden 5 saniye sonra cesedi yerden silinecek.
        
set_task5.0"NpcOluyuKaldir"iEnt );
    }
    return 
HAM_SUPERCEDE;
}

//NPC'yi kaldir
public NpcOluyuKaldirNpc )
{
    
remove_entityNpc );
}

//NPC'nin dusunme fonksiyonu yani beyni. bu fonksiyon içine NPC mize ne yaptirmak istiyorsaniz ekleyebilirsiniz.
//Biz sadece durmasini istiyoruz bu yuzden NPC miz durmaktan baska bisey yapmayacak.
public fw_NpcThinkiEnt )
{
    if( !
is_valid_entiEnt ) )
        return 
HAM_SUPERCEDE;
    
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( !
equaliNPCNpcClass ) )
        return 
HAM_SUPERCEDE;
    
    
//Eger NPC'miz oluyse dusunme fonksiyonunu kapat.
    
if( g_NpcOlduiEnt ] )
        return 
HAM_SUPERCEDE;
    
    
//NPC sadece duracak yani durus animasyonu.
    
Util_PlayAnimation(iEntg_NpcIdleAnimationsrandomsizeof g_NpcIdleAnimations ) ] );
    
//NPC'nin beyni her 5 saniyede bir çalisacak.
    
entity_set_floatiEntEV_FL_nextthinkget_gametime() + 5.0 );
    return 
HAM_IGNORED;
}

//NPC hasar fonksiyonu2, fark, bu fonksiyonda hasarimizin yonunu belirleyebiliyoruz. Bir bu fonksiyonu-
//NPC hasar aldiginda vucudundan kan cikmasi icin kullanacagiz.
public fw_NpcTraceAttack(iEntattackerFloatdamageFloatdirection[3], tracedamageBits)
{
    if( !
is_valid_entiEnt ) )
        return 
HAM_SUPERCEDE;
    
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//NPC hasar alma kapaliysa kan cikmasin.
        
if( entity_get_floatiEntEV_FL_takedamage ) == 0.0 )
            return 
HAM_SUPERCEDE;
        
        
//Merminin son carptigi yerin koordinatlarini buluyoruz.
        
new Floatend];
        
get_tr2traceTR_vecEndPosend );
        
        
//Mermi NPC'nin neresine çarptiysa kan o bolgeden cikacak.
        
message_beginMSG_BROADCAST,SVC_TEMPENTITY );
        
write_byteTE_BLOODSPRITE );
        
engfuncEngFunc_WriteCoordend] );
        
engfuncEngFunc_WriteCoordend] );
        
engfuncEngFunc_WriteCoordend] );
        
write_shortnpc_kan_spr_sprey );
        
write_shortnpc_kan_spr );
        
write_byte247 );
        
write_byterandom_num515 ) ); 
        
message_end();
    }
    return 
HAM_IGNORED;

NPC için ekstra oluşturduğumuz stockları ekliyoruz. NPC için hareket ve Nişan alınan noktanın koordinatları fonksiyonlarını kullanacağız.

PHP- Kodu:
//NPC icin animasyon,hareket fonksiyonu.
stock Util_PlayAnimation(indexsequenceFloatframerate 1.0)
{
    
entity_set_float(indexEV_FL_animtimeget_gametime());
    
entity_set_float(indexEV_FL_framerate,  framerate);
    
entity_set_float(indexEV_FL_frame0.0);
    
entity_set_int(indexEV_INT_sequencesequence);
}  

//Nisan alinan noktanin koordinatlarini bul. - akcaliberkk
stock get_user_hitpoint(idFloat:hOrigin[3]) {
    if ( ! 
is_user_aliveid ))
        return 
0;
    
    new 
Float:fOrigin[3], Float:fvAngle[3], Float:fvOffset[3], Float:fvOrigin[3], Float:feOrigin[3];
    new 
Float:fTemp[3];
    
    
pev(idpev_originfOrigin);
    
pev(idpev_v_anglefvAngle);
    
pev(idpev_view_ofsfvOffset);
    
    
xs_vec_add(fOriginfvOffsetfvOrigin);
    
    
engfunc(EngFunc_AngleVectorsfvAnglefeOriginfTempfTemp);
    
    
xs_vec_mul_scalar(feOrigin9999.9feOrigin);
    
xs_vec_add(fvOriginfeOriginfeOrigin);
    
    
engfunc(EngFunc_TraceLinefvOriginfeOrigin0id);
    
global_get(glb_trace_endposhOrigin);
    return 
1;

ve son olarak NPC'mizi oluşturuyoruz. Kodların üstünde açıkladım bazı değerleri istediğiniz gibi ayarlayabilirsiniz.

PHP- Kodu:
//ve NPC mizi bu fonksiyonda olusturuyoruz.
public NpcOlusturid )
{
    
//NPC icin koordinat ve aci degiskenleri olusturduk.
    
new FloatOrigin], FloatAngle];
    
    
//Herhangi bir entity yani nesne yaratiyoruz sonra bu nesneyi NPC olarak tanimlayacagiz.
    
new iEnt create_entity"info_target" );
    
//Yaptigimiz nesneyi bizim NPC miz olarak tanimladik.
    
entity_set_stringiEntEV_SZ_classnameNpcClass );
    
    
//Aim ile koordinatlari buluyoruz. NPC miz o koordinatlarda olucak.
    
get_user_hitpointidOrigin );
    
Origin] += 70.0;
    
entity_set_originiEntOrigin );
    
    
//Oyuncunun bakis acisini aliyoruzki NPC de o acida olussun.
    
entity_get_vector(idEV_VEC_anglesAngle );
    
Angle] = 0.0;
    
    
entity_set_vectoriEntEV_VEC_anglesAngle );
    
    
//NPC mizin modelini ayarliyoruz.
    
entity_set_modeliEntg_NpcModel );
    
//NPC miz hareketini ayarliyoruz. Yani ittirilebilir bir entity olacak.
    
entity_set_int(iEntEV_INT_movetypeMOVETYPE_PUSHSTEP );
    
//NPC miz içi dolu bir nesne olucak yani içinden geçemeyiz.
    
entity_set_int(iEntEV_INT_solidSOLID_BBOX );
    
    
//NPC miz hasar alabilir.
    
entity_set_floatiEntEV_FL_takedamage1.0 );
    
//NPC'nin canini 500 yaptik.
    
entity_set_floatiEntEV_FL_health500.0 );
    
    
//Simdide NPC mizin buyuklugunu ayarliyoruz bu degerler min ve max olarak ayarlanir. 3 boyutlu olarak yani.
    
new Floatmins[3] = {-12.0, -12.00.0 };
    new 
Floatmaxs[3] = { 12.012.075.0 };
    
    
entity_set_size(iEntminsmaxs);
    
    
//NPC kafasini kontrol edebilir.
    
entity_set_byteiEntEV_BYTE_controller1125 );
    
    
//ve NPC mizi yere sabitliyoruz yanlis anlamayin yani havada duvarda vb. yerde olusabilir eger olusursa yere indirir
    //bu kod.
    
drop_to_flooriEnt );
    
    
//NPC mizin canli oldugunu tanimliyoruz.
    
g_NpcOlduiEnt ] = false;
    
//NPC sayisina +1 ekliyoruz.
    
NpcSayisi++;
    
    
//NPC nin beyni 1 saniye sonra calisacak. 
    
entity_set_floatiEntEV_FL_nextthinkget_gametime() + 1.0 );    

NPC plugininin son hali:

PHP- Kodu:

#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <engine>
#include <hamsandwich>  

#define PLUGIN "NPC - Non Playar Character - Oyuncu Olmayan Karakter"
#define VERSION "1.0"
#define AUTHOR "peNgueN"

//NPC oldu mu yasiyor mu ?
new boolg_NpcOldu512 ]; 

//NPC Entity Ismi
new const NpcClass[] = "entity_npc"

//NPC Hareketleri
new const g_NpcIdleAnimations[] = { 1314151617 }; //NPC Durus Animasyonlari
new const g_NpcDamageAnimations[] = { 8910 }; //NPC Hasar Animasyonlari
new const g_NpcDeathAnimations[] = { 313233343536 }; //NPC Olum Animasyonlari
new const g_NpcTalkAnimations[] = { 5960616263 }; //NPC Konusma Hareketleri

//NPC kan efektleri
new npc_kan_sprnpc_kan_spr_sprey;

//NPC Modeli
new const g_NpcModel[] = "models/hostage.mdl";

//NPC Sayisi
new NpcSayisi;

//NPC Sesleri
new const g_NpcOlumSesi[][] =  {
    
    
"barney/ba_die1.wav"
    
"barney/ba_die2.wav"
    
"barney/ba_die3.wav" 


new const 
g_NpcHasarSesi[][] = {
    
    
"barney/ba_pain1.wav"
    
"barney/ba_pain2.wav"
    
"barney/ba_pain3.wav" 
}

new const 
g_NpcKonusma[][] = {
    
    
"barney/dontaskme.wav"
    
"barney/haybuddy.wav"
    
"barney/hayfella.wav",
    
"barney/hellonicesuit.wav",
    
"barney/howyoudoing.wav"
    
}

public 
plugin_init()
{
    
register_pluginPLUGINVERSIONAUTHOR );
    
    
//NPC Kontrol Menusu
    
register_clcmd"say /npc""NpcMenu" );
    
register_clcmd"say_team /npc""NpcMenu" );
    
    
//NPC Kontrol Fonksiyonlari
    
RegisterHamHam_TakeDamage"info_target""fw_NpcTakeDamage" ); //Hasar Fonksiyonu
    
RegisterHamHam_Killed"info_target""fw_NpcKilled" ); //Olum Fonksiyonu
    
RegisterHamHam_Think"info_target""fw_NpcThink" ); //Beyin Fonksiyonu
    
RegisterHamHam_TraceAttack"info_target""fw_NpcTraceAttack" ); //Mermi Fonksiyonu
    
RegisterHamHam_Touch"info_target""fw_NpcTouch" ); //Dokunma Fonksiyonu
}

public 
plugin_precache( )
{
    
npc_kan_spr precache_model"sprites/blood.spr" );
    
npc_kan_spr_sprey precache_model"sprites/bloodspray.spr" );
    
    
precache_modelg_NpcModel );
    
    for( new 
sizeof g_NpcOlumSesi i++)
        
precache_soundg_NpcOlumSesi] );
    
    for( new 
sizeof g_NpcHasarSesi i++)
        
precache_soundg_NpcHasarSesi] );
    
    for( new 
sizeof g_NpcKonusma i++)
        
precache_soundg_NpcKonusma] );    
    
}

public 
NpcMenuid )
{
    new 
iMenu64 ];
    
formatexiMenucharsmaxiMenu ), "NPC - Oyuncu Olmayan Karakter" );
    new 
menu menu_createiMenu"NpcMenu_go" );
    
    
formatexiMenucharsmaxiMenu ), "\wNPC Olustur \y( Aim ile yer belirleyin )" );
    
menu_additemmenuiMenu"1" );
    
formatexiMenucharsmaxiMenu ), "\wNPC Kaldir \y( Aim ile secin )" );
    
menu_additemmenuiMenu"2" );
    
formatexiMenucharsmaxiMenu ), "\wButun NPC'leri Kaldir^n \y  %d NPC Mevcut"NpcSayisi );
    
menu_additemmenuiMenu"3" );
    
    
menu_setpropmenuMPROP_EXITMEXIT_ALL);
    
menu_setpropmenuMPROP_EXITNAME"\rCIKIS" );
    
    
menu_display(idmenu);
    return 
PLUGIN_HANDLED;
}

public 
NpcMenu_goidmenuitem )
{
    
    if( 
item == MENU_EXIT )
    {
        
menu_destroymenu );
        return 
PLUGIN_HANDLED;
    }
    
    new 
info], szName64 ];
    new 
accesscallback;
    
    
menu_item_getinfomenuitemaccessinfocharsmaxinfo ), szNamecharsmaxszName ), callback );
    
    new 
key str_to_numinfo );
    
    switch( 
key )
    {
        case 
1:
        {
            if( !
is_user_aliveid ) ) return PLUGIN_HANDLED;
            
            
NpcOlusturid );
        }
        case 
2:
        {
            if( !
is_user_aliveid ) ) return PLUGIN_HANDLED;
            
            new 
iEntVucutNPC64 ];
            
get_user_aimingidiEntVucut );
            
            if ( 
is_valid_entiEnt ) ) 
            {
                
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
                
                if ( 
equalNPCNpcClass ) ) 
                {
                    
remove_entityiEnt );
                    
NpcSayisi--;
                    
client_printidprint_chat"[NPC] Bir NPC Kaldirildi." );
                }
                
            }
        }
        case 
3:
        {
            
remove_entity_nameNpcClass );
            
NpcSayisi 0;
            
client_printidprint_chat"[NPC] Butun NPC'ler Kaldirildi." );
        }
    }
    
    
    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;
}


//NPC'ye dokundugumuzda bizmle konusacak ve hareket edecek.
public fw_NpcTouchiEntid 
{
    if( !
is_user_aliveid ) )
        return 
HAM_SUPERCEDE;
    
    
//Sadece 1 kere çalismasi için kontrol ediyoruz.
    
static FloatgametimeFloatCooldown32 ]; 
    
gametime get_gametime();
    
    if(
gametime 1.0 Cooldownid ] )
    {
        
//NPC kontrolu yapiyoruz. Burada NPC mizin ClassName yani ismini sorgulayarak onu baska nesnelerden ayiriyoruz.
        //Sadece bizim NPC mizde calismasi icin kontrol ediyoruz. Duvara degdiginde konusmasini istemeyiz :)
        
new NPC64 ];
        
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
        
        if( 
equaliNPCNpcClass ) )
        {
            
//NPC'ye dokundugumuzda hareket edecek. Hareketleri g_NpcTalkAnimations degiskeninden aldik.
            
Util_PlayAnimationiEntg_NpcTalkAnimationsrandomsizeof g_NpcTalkAnimations ) ] );
            
//NPC'ye dokunudugumuzda bizimle konusucak. Sesleri g_NpcKonusma degiskeninden aldik.
            
emit_soundiEntCHAN_VOICEg_NpcKonusmarandomsizeof g_NpcKonusma ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
        }
        
        
Cooldownid ] = gametime;
    }
    return 
HAM_IGNORED;
}

//NPC'ye hasar verdigimizde hareket edecek ve bagiracak.
public fw_NpcTakeDamageiEntinflictorattackerFloat:damagebits )
{
    
//NPC kontrolu yapiyoruz. Burada NPC mizin ClassName yani ismini sorgulayarak onu baska nesnelerden ayiriyoruz.
    
new NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//NPC'ye hasar verdigimizde hareket edecek. Hareketleri g_NpcDamageAnimations degiskeninden aldik.
        
Util_PlayAnimationiEntg_NpcDamageAnimationsrandomsizeof g_NpcDamageAnimations ) ], 1.25 );
        
//NPC'ye hasar verdigimizde bagiracak. Sesleri g_NpcHasarSesi degiskeninden aldik.
        
emit_soundiEntCHAN_VOICEg_NpcHasarSesirandomsizeof g_NpcHasarSesi ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
    }
}

//NPC'yi olduruyoruz.
public fw_NpcKillediEntKiller )
{
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//g_NpcOldu degiskenini dogru tanimladik.
        
g_NpcOlduiEnt ] = true;
        
//NPC oldugunde olum animasyonu calisacak.
        
Util_PlayAnimation(iEntg_NpcDeathAnimationsrandomsizeof g_NpcDeathAnimations ) ] );
        
//Oldugunde NPC'nin içinden geçebiliriz. SOLID_NOT entity nin içinden geçilmesini kapatir.
        
entity_set_intiEntEV_INT_solidSOLID_NOT );
        
//NPC'yi olu olarak tanimladik.
        
entity_set_intiEntEV_INT_deadflagDEAD_DEAD );
        
//NPC'nin cesedinin hasar almasini kapattik.
        
entity_set_float(iEntEV_FL_takedamage0.0 ); 
        
//NPC oldugunde bagiracak.
        
emit_soundiEntCHAN_VOICEg_NpcOlumSesirandomsizeof g_NpcOlumSesi ) ],  VOL_NORMATTN_NORM0PITCH_NORM );
        
        
client_printKillerprint_chat"[NPC] NPC'yi oldurdunuz." );
        
        
//NPC oldugunden 5 saniye sonra cesedi yerden silinecek.
        
set_task5.0"NpcOluyuKaldir"iEnt );
    }
    return 
HAM_SUPERCEDE;
}

//NPC'yi kaldir
public NpcOluyuKaldirNpc )
{
    
remove_entityNpc );
}

//NPC'nin dusunme fonksiyonu yani beyni. bu fonksiyon içine NPC mize ne yaptirmak istiyorsaniz ekleyebilirsiniz.
//Biz sadece durmasini istiyoruz bu yuzden NPC miz durmaktan baska bisey yapmayacak.
public fw_NpcThinkiEnt )
{
    if( !
is_valid_entiEnt ) )
        return 
HAM_SUPERCEDE;
    
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( !
equaliNPCNpcClass ) )
        return 
HAM_SUPERCEDE;
    
    
//Eger NPC'miz oluyse dusunme fonksiyonunu kapat.
    
if( g_NpcOlduiEnt ] )
        return 
HAM_SUPERCEDE;
    
    
//NPC sadece duracak yani durus animasyonu.
    
Util_PlayAnimation(iEntg_NpcIdleAnimationsrandomsizeof g_NpcIdleAnimations ) ] );
    
//NPC'nin beyni her 5 saniyede bir çalisacak.
    
entity_set_floatiEntEV_FL_nextthinkget_gametime() + 5.0 );
    return 
HAM_IGNORED;
}

//NPC hasar fonksiyonu2, fark, bu fonksiyonda hasarimizin yonunu belirleyebiliyoruz. Bir bu fonksiyonu-
//NPC hasar aldiginda vucudundan kan cikmasi icin kullanacagiz.
public fw_NpcTraceAttack(iEntattackerFloatdamageFloatdirection[3], tracedamageBits)
{
    if( !
is_valid_entiEnt ) )
        return 
HAM_SUPERCEDE;
    
    new 
NPC64 ];
    
entity_get_stringiEntEV_SZ_classnameNPCcharsmaxNPC ) );
    
    if( 
equaliNPCNpcClass ) )
    {
        
//NPC hasar alma kapaliysa kan cikmasin.
        
if( entity_get_floatiEntEV_FL_takedamage ) == 0.0 )
            return 
HAM_SUPERCEDE;
        
        
//Merminin son carptigi yerin koordinatlarini buluyoruz.
        
new Floatend];
        
get_tr2traceTR_vecEndPosend );
        
        
//Mermi NPC'nin neresine çarptiysa kan o bolgeden cikacak.
        
message_beginMSG_BROADCAST,SVC_TEMPENTITY );
        
write_byteTE_BLOODSPRITE );
        
engfuncEngFunc_WriteCoordend] );
        
engfuncEngFunc_WriteCoordend] );
        
engfuncEngFunc_WriteCoordend] );
        
write_shortnpc_kan_spr_sprey );
        
write_shortnpc_kan_spr );
        
write_byte247 );
        
write_byterandom_num515 ) ); 
        
message_end();
    }
    return 
HAM_IGNORED;
}

//NPC icin animasyon,hareket fonksiyonu.
stock Util_PlayAnimation(indexsequenceFloatframerate 1.0)
{
    
entity_set_float(indexEV_FL_animtimeget_gametime());
    
entity_set_float(indexEV_FL_framerate,  framerate);
    
entity_set_float(indexEV_FL_frame0.0);
    
entity_set_int(indexEV_INT_sequencesequence);
}  

//Nisan alinan noktanin koordinatlarini bul.
stock get_user_hitpoint(idFloat:hOrigin[3]) {
    if ( ! 
is_user_aliveid ))
        return 
0;
    
    new 
Float:fOrigin[3], Float:fvAngle[3], Float:fvOffset[3], Float:fvOrigin[3], Float:feOrigin[3];
    new 
Float:fTemp[3];
    
    
pev(idpev_originfOrigin);
    
pev(idpev_v_anglefvAngle);
    
pev(idpev_view_ofsfvOffset);
    
    
xs_vec_add(fOriginfvOffsetfvOrigin);
    
    
engfunc(EngFunc_AngleVectorsfvAnglefeOriginfTempfTemp);
    
    
xs_vec_mul_scalar(feOrigin9999.9feOrigin);
    
xs_vec_add(fvOriginfeOriginfeOrigin);
    
    
engfunc(EngFunc_TraceLinefvOriginfeOrigin0id);
    
global_get(glb_trace_endposhOrigin);
    return 
1;
}  

//ve NPC mizi bu fonksiyonda olusturuyoruz.
public NpcOlusturid )
{
    
//NPC icin koordinat ve aci degiskenleri olusturduk.
    
new FloatOrigin], FloatAngle];
    
    
//Herhangi bir entity yani nesne yaratiyoruz sonra bu nesneyi NPC olarak tanimlayacagiz.
    
new iEnt create_entity"info_target" );
    
//Yaptigimiz nesneyi bizim NPC miz olarak tanimladik.
    
entity_set_stringiEntEV_SZ_classnameNpcClass );
    
    
//Aim ile koordinatlari buluyoruz. NPC miz o koordinatlarda olucak.
    
get_user_hitpointidOrigin );
    
Origin] += 70.0;
    
entity_set_originiEntOrigin );
    
    
//Oyuncunun bakis acisini aliyoruzki NPC de o acida olussun.
    
entity_get_vector(idEV_VEC_anglesAngle );
    
Angle] = 0.0;
    
    
entity_set_vectoriEntEV_VEC_anglesAngle );
    
    
//NPC mizin modelini ayarliyoruz.
    
entity_set_modeliEntg_NpcModel );
    
//NPC miz hareketini ayarliyoruz. Yani ittirilebilir bir entity olacak.
    
entity_set_int(iEntEV_INT_movetypeMOVETYPE_PUSHSTEP );
    
//NPC miz içi dolu bir nesne olucak yani içinden geçemeyiz.
    
entity_set_int(iEntEV_INT_solidSOLID_BBOX );
    
    
//NPC miz hasar alabilir.
    
entity_set_floatiEntEV_FL_takedamage1.0 );
    
//NPC'nin canini 500 yaptik.
    
entity_set_floatiEntEV_FL_health500.0 );
    
    
//Simdide NPC mizin buyuklugunu ayarliyoruz bu degerler min ve max olarak ayarlanir. 3 boyutlu olarak yani.
    
new Floatmins[3] = {-12.0, -12.00.0 };
    new 
Floatmaxs[3] = { 12.012.075.0 };
    
    
entity_set_size(iEntminsmaxs);
    
    
//NPC kafasini kontrol edebilir.
    
entity_set_byteiEntEV_BYTE_controller1125 );
    
    
//ve NPC mizi yere sabitliyoruz yanlis anlamayin yani havada duvarda vb. yerde olusabilir eger olusursa yere indirir
    //bu kod.
    
drop_to_flooriEnt );
    
    
//NPC mizin canli oldugunu tanimliyoruz.
    
g_NpcOlduiEnt ] = false;
    
//NPC sayisina +1 ekliyoruz.
    
NpcSayisi++;
    
    
//NPC nin beyni 1 saniye sonra calisacak. 
    
entity_set_floatiEntEV_FL_nextthinkget_gametime() + 1.0 );    

İşte NPC miz:





Evet biraz gelişmiş bir NPC oluşturduk. Bu eklentide ki NPC konuşabiliyor, hasar alabiliyor ve hareket edebiliyor ama sadece yerinde duruyor. Bir menü yardımıyla NPC oluşturabilir, onu silebilirsiniz. Bu arada menü kodu "say /npc" Daha sonra biraz daha geliştirebiliriz. Hareket eden, koşan bir NPC gibi.

Anlamadığınız yer olursa sorabilirsiniz. Eklentide hata, bug, sorun olursa veya daha mantıklı bir algoritma varsa beni uyarabilirsiniz.

Kolay gelsin.