NPC製作教學(最好有點插件基礎在進來!

Home Home
<< 1 2 3 >>
跳頁: (共 3 頁)
引用 | 編輯 husano896
2011-07-03 11:32
樓主
推文 x18
所謂NPC 基本上就是"非玩家控制"的角色 例如常見的ZBOT 人質都是

要做個NPC角色 我們需要用到<amxmodx>和<engine>這兩個模塊

就在sma上方加入(若有了就別再加了)
複製程式
#include <amxmodx>
#include <engine>

接著 要寫個製造NPC的function出來 並在plugin_init()裡面加入會調用到的指令
複製程式
public plugin_init()
{
       register_clcmd("npc_create", "create_npc")       //這個是只要玩家在控制台打npc_create這指令 就會讀取create_npc裡面的指令
}
複製程式
public create_npc(id)
1.我們首先需要用到create_entity這個指令來建立一個物體
複製程式
       new ent = create_entity("info_target")       //創立一個物體出來 並讓"ent"指向他

2.設定NPC的位置 可以有很多種用法 這裡是將NPC建立在玩家的頭上
複製程式
       new Float:origin[3]

       entity_get_vector(id,EV_VEC_origin,origin)
       origin[2] += 300.0
       entity_set_origin(ent,origin);

3.設定血量
複製程式
       entity_set_float(ent,EV_FL_takedamage,1.0)       //這裡是讓它變成可被攻擊
       entity_set_float(ent,EV_FL_health,100.0)                     //這裡是設定血量

有研究過NST原碼的玩家都會好奇 為什麼不要用DAMAGE_AIM呢
用過的人就會發現 攻擊npc時會lag 尤其是很多隻NPC在地圖上時會特別明顯

4.設定模組(範例是使用models/player/terror/terror.mdl)
複製程式
       //※記得在plugin_precache()裡面加入你的模組噢!!
       entity_set_model(ent, "models/player/terror/terror.mdl")

5.設定名稱(記住不要設中文!!)
複製程式
       entity_set_string(ent,EV_SZ_classname,"npc_terror")       //這裡可以隨便取 但是到後面會用到

6.設定大小(記住 不要調太大!! 不然會卡住)
複製程式
       new Float:maxs[3] = {16.0,16.0,36.0}       //這裡越大 NPC所佔的範圍越大
       new Float:mins[3] = {-16.0,-16.0,-36.0}       //這裡越小 NPC所佔的範圍越大
       entity_set_size(ent,mins,maxs)              //設定大小
       entity_set_int(ent,EV_INT_solid, 2)       //使NPC變為固體(不能穿透)

7.設定畫格
複製程式
       entity_set_float(ent,EV_FL_animtime,2.0)
       entity_set_float(ent,EV_FL_framerate,1.0)       //動作速率 調太大動作會像瘋子...
       entity_set_int(ent,EV_INT_sequence,0)              //調用的動作序號
8.讓NPC會思考
複製程式
       entity_set_float(ent,EV_FL_nextthink,halflife_time() + 0.01)       //這裡是設定成下次思考的時間為遊戲時間+0.01秒時

9.丟到地上(就真的這樣翻..)
複製程式
       drop_to_floor(ent)

10.設定NPC思考的東西
複製程式
在public plugin_init()裡面加入
register_think("npc_id","npc_think")       //前面的npc_id換成你前面npc設的名字!!
隨意找個地方加入
public npc_think(id)
{
       //看你要讓NPC幹嘛都扔在這裡
       entity_set_float(id,EV_FL_nextthink,halflife_time() + 0.01)
}
※瘟腥提示(?):如果sma裡面有中文字的話 記得轉成UTF-8 No Bom的格式!!

進入遊戲後 測試看看吧!!


下面附件是做好的範例 有問題歡迎發問

參考來源:https://forums.alliedmods.net/showthread.php?t=11756

本帖包含附件
檔名: zip npc_test.rar   (2022-06-09 14:18 / 2 KB)   下載次數:292


獻花 x8
引用 | 編輯 husano896
2011-07-03 11:33
1樓
  
要使NPC能在被傷害/擊殺時有特殊效果 我們需要用到hamsandwich這模塊

在sma最上方加入
複製程式
#include <hamsandwich>
#include <fakemeta> //2011.12.28修正(真晚- - 

在NPC創建的地方加入

為了確保傷害公式只會被讀一次 要記得加記錄項 像下面
複製程式
if (!g_hamnpc)       //記住!!g_hamnpc只能被放在function外面!!
{
       //這兩串是讓NPC讀到你的傷害公式
       RegisterHamFromEntity(Ham_TakeDamage, ent, "fw_TakeDamage")
       RegisterHamFromEntity(Ham_TraceAttack, ent, "fw_TraceAttack")
       RegisterHamFromEntity(Ham_Killed, ent, "fw_Killed")
       g_hamnpc = 1
}
※如果讀了好幾次的話 電腦當機恕不退費(? 不知道怎麼加歡迎PM我
並在plugin_init裡面加入
複製程式
       //這兩串是讓玩家讀到你的傷害公式
       RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
       RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
       //這裡就不需要加Killed了 不然會讀兩次

當然 我們還要在下面加入對應的function才行
複製程式
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
       if (victim==attacker)
              return HAM_IGNORED;

       if (!pev_valid(victim) || !pev_valid(attacker))
              return HAM_IGNORED;

       new classname[32]
       pev(victim,pev_classname,classname,31)
       if (equal(classname,"(你之前設的NPC名字)"))       //這裡是檢查被打的人是不是NPC
       {
              //看你要加啥都加在這邊
              //有一點要注意 "非"玩家使用的指令不能加在這邊 否則會有錯誤
              //例如 被攻擊/攻擊者是NPC 就不能使用 cs_get_user_team(victim) 或 cs_set_user_money(victim, ...)
              //當然 is_user_connected(回傳玩家是否連接)這類的指令可以用
              //傷害的修改教學 可以看a78大的文章 http://bbs-mychat.com/reads.php?tid=829669
       }
       return HAM_IGNORED; 
}
複製程式
#define DMG_HEGRENADE (1 << 24)       //感謝fouury提醒
new cache_bloodspray, cache_blood       //血的spr 等等會用到
public plugin_precache()
{
       //讀取spr
       cache_blood = precache_model("sprites/blood.spr")
       cache_bloodspray = precache_model("sprites/bloodspray.spr")
}
public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
{
       if (victim==attacker)
              return HAM_IGNORED;

       if (!pev_valid(victim) || pev_valid(attacker))
              return HAM_IGNORED;

       new classname[32]
       pev(victim,pev_classname,classname,31)
       if (equal(classname,"(你之前設的NPC名字)"))       //這裡是檢查被打的人是不是NPC
       {
              //注意事項跟上面一樣
              //get_tr/set_tr這類指令可以使用 可用來判定傷害部位/噴血位置
              //下面會有範例(飯粒?
              new body = get_tr2(tracehandle,TR_iHitgroup) //取得NPC被傷害的部位
              if (body == 1)       //爆頭的情況下
              {
                     damage *= 4.0       //傷害四倍
                     SetHamParamFloat(3, damage)       //讀取修改過後的傷害
              }

              new Float:Fend[3],end[3]
              get_tr2(tracehandle, TR_vecEndPos, Fend)       //在開槍的位置和被擊中的位置畫條線(我不知道怎麼解釋..)

              //This message will draw blood sprites at the end of the trace
              if (!(damage_type & DMG_HEGRENADE))       //如果不是被芭樂炸的
              {
                     end[0] = floatround(Fend[0])
                     end[1] = floatround(Fend[1])
                     end[2] = floatround(Fend[2])
                     create_block_sprites(end)       //在該位置顯示噴血(不會有血跡)
              }
       }     
       return HAM_IGNORED;
}

create_block_sprites(const origin[3])
{
       // Show some blood :)
       message_begin(MSG_BROADCAST, SVC_TEMPENTITY) 
       write_byte(TE_BLOODSPRITE)
       write_coord(origin[0])
       write_coord(origin[1])
       write_coord(origin[2])
       write_short(cache_bloodspray)
       write_short(cache_blood)
       write_byte(75)
       write_byte(5)
       message_end()
}

複製程式
public fw_Killed(victim, attacker)
{
       //※跟上上方的說明一樣 非玩家指令不能用 除非你能確定你用的人是玩家
       new classname[32]
     pev(victim,pev_classname,classname,31) 
       if (equal(classname,"(你之前設的NPC名字)"))       //這裡是檢查被打的人是不是NPC
       {
              if (is_user_connected(attacker))       //當攻擊者是玩家時
              {
                     //你可以在這裡加給玩家用的指令 例如加錢...加血
              }
       }
       return HAM_IGNORED
}
有興趣的人 可以看下面從Ham_const裡面拿來的說明(英文)
複製程式
        * Description:              Usually called whenever an entity gets attacked by a hitscan (such as a gun) weapon.
        *                                   Use the get/set tr2 natives in fakemeta to handle the traceresult data.
        *                                   Do not use a handle of 0 as a traceresult in execution, use create_tr2() from Fakemeta
        *                                   to pass a custom handle instead.  (Don't forget to free the handle when you're done.)
        * Forward params:       function(this, idattacker, Float:damage, Float:direction[3], traceresult, damagebits)
        * Return type:              None.
        * Execute params:       ExecuteHam(Ham_TraceAttack, this, idattacker, Float:damage, Float:direction[3], tracehandle, damagebits);
        */
       Ham_TraceAttack,
       
       /**
        * Description:              Usually called whenever an entity takes any kind of damage.
        *                                   Inflictor is the entity that caused the damage (such as a gun).
        *                                   Attacker is the entity that tirggered the damage (such as the gun's owner).
        * Forward params:       function(this, idinflictor, idattacker, Float:damage, damagebits);
        * Return type:              Integer.
        * Execute params:       ExecuteHam(Ham_TakeDamage, this, idinflictor, idattacker, Float:damage, damagebits);
        */
       Ham_TakeDamage,

這次說明可能比較難懂 多觀察其他插件的使用方式吧
如果完全看不懂 建議你先學一點c++

題外話:這次的東西好多都忘了改為engine的用法><

2011.12.28:還是改回fakemeta好了 問題好多..(汗尤其是get_tr2的部分根本不能用(汗顏

獻花 x4
引用 | 編輯 zdt
2011-07-03 12:54
2樓
  
请问可以做一个BOT出来吗?就是有分队的....

獻花 x0
引用 | 編輯 zz12345zxc
2011-07-03 13:07
3樓
  
這是來實現 cs的災厄之章嗎? 話說 你現在已經做到哪了!

獻花 x0
引用 | 編輯 冷場の飛天娘
2011-07-03 14:04
4樓
  
請盡快完成,

我真的很想了解這門技術 表情 ~~

雖然還沒完成先推推啦~~

(花花完成再給),花花是人質! 表情

獻花 x1
引用 | 編輯 HiNess
2011-07-03 14:05
5樓
  
之前看過一個NPC製作教學的POST(外國)
(很像這個post http://forums.alliedmods.net/showthread.php?t=11756...)

都是一些很難的英文(看不懂...)
終於有中文的教學^^

獻花 x0
引用 | 編輯 小XC
2011-07-04 12:36
6樓
  
我應該可以學起來!= =!

獻花 x0
引用 | 編輯 冷場の飛天娘
2011-07-04 20:09
7樓
  
我還是不太清楚這要怎麼使用.......

重生點在哪裡?

樓主提供的就是主插件?

如何使用?

需要他配其他插件嗎?

指令是什麼?

.....................等等........... 表情

獻花 x0
引用 | 編輯 離之彥
2011-07-04 20:16
8樓
  
加油~~~~~~~

話說NPC真的很笨...

讓您研究了不少時間哪...

獻花 x0
引用 | 編輯 小XC
2011-07-04 20:43
9樓
  
奇怪
未啥我打npc_create的時候會跳出遊戲阿到登入畫面阿

獻花 x0
引用 | 編輯 husano896
2011-07-05 09:22
10樓
  
下面是引用 飛天派 於 2011-07-04 20:09 發表的 : 到引言文
我還是不太清楚這要怎麼使用.......

重生點在哪裡?

樓主提供的就是主插件?

如何使用?

需要他配其他插件嗎?

指令是什麼?

.....................等等........... 表情




這篇是教"寫"插件噢

獻花 x0
引用 | 編輯 絕影華
2011-07-06 09:30
11樓
  
如果想拎玩家對NPC禁e有選單彈出

如何整出來

獻花 x0
引用 | 編輯 husano896
2011-07-06 13:50
12樓
  
下面是引用 絕影華 於 2011-07-06 09:30 發表的 : 到引言文
如果想拎玩家對NPC禁e有選單彈出

如何整出來


new ent前面的地方加入判定條件就行了
[font=]ex:[font=]
[font=]if (cs_get_user_money(id) < 6000)[font=]return...

獻花 x0
引用 | 編輯 絕影華
2011-07-06 16:24
13樓
  
下面是引用 husano896 於 2011-07-06 13:50 發表的 : 到引言文



new ent前面的地方加入判定條件就行了
[font=]ex:[font=]
[font=]if (cs_get_user_money(id) < 6000)[font=]return...

還是不明白-.-   例如我整了一個選單出來是


應該怎樣加上去





public mostrarmenu(id)
{
        {
        new menu = menu_create("\y 商店:", "mostrar_cliente")
   
        menu_additem(menu, "\r Admin專用武器", "1", 0)
   
    menu_display(id, menu, 0)
        }
}

public mostrar_cliente(id, menu, item, Float:damage)
{
    new data[6], iName[64]
    new access, callback
   
    menu_item_getinfo(menu, item, access, data,5, iName, 63, callback)
   
    new key = str_to_num(data)
   
    switch(key)
    {
        case 1:{
            if(cs_get_user_money(id) >= 10)
            {
                    if (get_user_flags(id) & ADMIN_KICK)
                {
                    {
                            give_item(id, "weapon_m249")
                            cs_set_user_money(id,cs_get_user_money(id) - 10)
                        client_print(id, print_chat, "[商店]恭喜管理員成功購買了武器")
                        return PLUGIN_HANDLED
                    }
                }
                else
                {
                    client_print(id, print_chat, "[商店]你不夠權限購買!")
                }
            }
            else
            {
                client_print(id, print_chat, "[商店]你不夠金錢購買")
            }
               }
        }
    menu_destroy(menu)
    return PLUGIN_HANDLED
}

獻花 x0
引用 | 編輯 husano896
2011-07-06 16:35
14樓
  
下面是引用 絕影華 於 2011-07-06 16:24 發表的 : 到引言文

還是不明白-.-   例如我整了一個選單出來是

應該怎樣加上去

.......


噢 我誤會你的意思了

是要碰到NPC後會叫出選單的話

就在plugin_init()裡面加入register_touch("(你之前設定的NPC名字)", "player", "npc_touch")

並在下面加入

public npc_touch(ent,id){//(這裡加入叫出商店的指令)}

獻花 x0
引用 | 編輯 絕影華
2011-07-06 16:55
15樓
  
下面是引用 husano896 於 2011-07-06 16:35 發表的 : 到引言文



噢 我誤會你的意思了

是要碰到NPC後會叫出選單的話

就在plugin_init()裡面加入register_touch("(你之前設定的NPC名字)", "player", "npc_touch")

並在下面加入

public npc_touch(ent,id){//(這裡加入叫出商店的指令)}

很多謝那麼樂意回答我的問題

還有3個問題要問問  thx

怎可以把那個NPC變無敵?

,

如果是禁E才有選單彈出 , 而不是碰到 應該怎樣改



如果那指令是say /shop  應該怎加上去

獻花 x0
引用 | 編輯 tw2twtw
2011-07-06 18:52
16樓
  
entity_set_float(ent,EV_FL_takedamage,0.0)     //設定成不能被攻擊就好了.... 表情

獻花 x0
引用 | 編輯 fouury
2011-07-06 22:04
17樓
  
關於DMG_HEGRENADE那裡好像忘了加上這個 表情

複製程式
#define DMG_HEGRENADE (1 << 24)
表情

獻花 x0
引用 | 編輯 絕影華
2011-07-07 01:29
18樓
  
下面是引用 tw2twtw 於 2011-07-06 18:52 發表的 : 到引言文
entity_set_float(ent,EV_FL_takedamage,0.0)     //設定成不能被攻擊就好了.... 表情



如果想令玩家對NPC禁E有選單彈出 , 而不是碰到 應該怎樣改



如果那指令是say /shop  應該怎加上去

獻花 x0
引用 | 編輯 杰;]
2011-07-07 18:27
19樓
  
嘩==
很詳盡而且解釋得很清楚的教學
可是我也感到很難明白..
不過也謝謝樓主用心的教學

獻花 x0
引用 | 編輯 honfai99
2011-07-08 21:05
20樓
  
可能做出一個好 Think 還是不能做出災厄.. 我做的災厄的 NPC 們都很容易卡住..

只要是彎路就會卡住在牆角... 做 waypoints 又怕他們只會行同一路徑..

waypoints 的話就不會追蹤玩家來攻擊..

獻花 x0
引用 | 編輯 husano896
2011-07-09 08:06
21樓
  
下面是引用 honfai99 於 2011-07-08 21:05 發表的 : 到引言文
可能做出一個好 Think 還是不能做出災厄.. 我做的災厄的 NPC 們都很容易卡住..

只要是彎路就會卡住在牆角... 做 waypoints 又怕他們只會行同一路徑..

waypoints 的話就不會追蹤玩家來攻擊..


不一定噢

可以做成 以waypoints為主

看到人在跟蹤

當人從視野中離開時 就移動最近的waypoint繼續移動

獻花 x0
引用 | 編輯 a7811311622
2011-07-09 12:47
22樓
  
唉…不是很看好這篇教學…
不是因為標題還是教的不好之類的問題…
而是目前有一堆人自從碰過NST的NPC後就一股腦兒想學怎麼弄NPC…
明明插件都還沒學過基礎就想學NPC…根本是想一步登天…
會寫插件的看完全部內容就知道前半部內容都是在說怎麼製造物件…
但是沒學過插件的光是前半段大概就不清楚在說什麼了…

嘛…但是讓會寫插件的來解釋插件原碼基礎…一堆人也不太會或不太想解釋…
總覺得會寫插件的人也是有問題就是了…(自婊?)

獻花 x2
引用 | 編輯 史來姆
2011-07-09 17:52
23樓
  
嗯,我也蠻同意a78大的說法
我也是因為nst而研究npc吶...
我個人覺得npc是插件中難度較為頗高
現在弄出了npc災厄,算是有點成就吧( 表情

我建議husano大你把題目改一下
免得嚇到想學插件的新手
新手:"甚麼嘛,插件都是這麼難的啊QAQ,我不學了~"
↑這樣的

獻花 x0
引用 | 編輯 冷場の飛天娘
2011-07-09 20:32
24樓
  
下面是引用 史來姆 於 2011-07-09 17:52 發表的 : 到引言文
嗯,我也蠻同意a78大的說法
我也是因為nst而研究npc吶...
我個人覺得npc是插件中難度較為頗高
現在弄出了npc災厄,算是有點成就吧( 表情  

我建議husano大你把題目改一下
免得嚇到想學插件的新手
新手:"甚麼嘛,插件都是這麼難的啊QAQ,我不學了~"
↑這樣的


"哇!好深奧!原來插件是如此高深的學問!我想要學表情 "

↑我

(雖然還沒踏出地一步表情 )

獻花 x0
引用 | 編輯 zxcvasd2
2011-07-09 23:36
25樓
  
husano大大喔

為什麼在我學寫npc的時候你不發這個post,
現在我學成了就發出來了 0.0 表情

話說這個post對新手npc入門還挺有用喔

獻花 x0
引用 | 編輯 fouury
2011-07-10 00:02
26樓
  
下面是引用 史來姆 於 2011-07-09 17:52 發表的 : 到引言文
嗯,我也蠻同意a78大的說法
我也是因為nst而研究npc吶...
我個人覺得npc是插件中難度較為頗高
現在弄出了npc災厄,算是有點成就吧( 表情

我建議husano大你把題目改一下
免得嚇到想學插件的新手
新手:"甚麼嘛,插件都是這麼難的啊QAQ,我不學了~"
↑這樣的

恩阿.表情
如果不懂.  直接接觸此文章的話.  
下場就是被文字打的落花流水表情   (劉海都濕了...)
且可能會造成一種對插件的"永久"刻版印象(就是很複雜)  表情

所以這些想法根本全鑑於自己本身的學習心態了 表情

獻花 x0
引用 | 編輯 784063999
2011-07-16 23:23
27樓
  
我覺得這個不是很難
有不少插件可以研究

獻花 x0
引用 | 編輯 andyt0621
2011-07-17 14:11
28樓
  
哈哈..看來nst的NPC對插件手影響很大耶..
我也是看了nst的NPC才寫了雷比亞和阿比隆 0.0

獻花 x0
引用 | 編輯 文♂
2011-07-17 17:46
29樓
  
這文章真有用 已經學會了表情

但問題.....問題是我現在不會弄成一個主插件把全部npc集合表情

-------------------------------------

還有一個問題......

怎樣設定npc擁有名字表情

獻花 x0
<< 1 2 3 >>
跳頁: (共 3 頁)