引用 | 編輯
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) 複製程式 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) //調用的動作序號 複製程式 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) } 進入遊戲後 測試看看吧!! 下面附件是做好的範例 有問題歡迎發問 參考來源:https://forums.alliedmods.net/showthread.php?t=11756
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 } 並在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 } 複製程式 * 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++ 題外話: 2011.12.28:還是改回fakemeta好了 問題好多..(汗尤其是get_tr2的部分根本不能用(汗顏 x4 |
引用 | 編輯
zz12345zxc
2011-07-03 13:07 |
3樓
▲ ▼ |
這是來實現 cs的災厄之章嗎? 話說 你現在已經做到哪了!
x0 |
引用 | 編輯
HiNess
2011-07-03 14:05 |
5樓
▲ ▼ |
之前看過一個NPC製作教學的POST(外國)
(很像這個post http://forums.alliedmods.net/showthread.php?t=11756...) 都是一些很難的英文(看不懂...) 終於有中文的教學^^ x0 |
引用 | 編輯
冷場の飛天娘
2011-07-04 20:09 |
7樓
▲ ▼ |
我還是不太清楚這要怎麼使用.......
重生點在哪裡? 樓主提供的就是主插件? 如何使用? 需要他配其他插件嗎? 指令是什麼? .....................等等........... x0 |
引用 | 編輯
絕影華
2011-07-06 16:24 |
13樓
▲ ▼ |
下面是引用 husano896 於 2011-07-06 13:50 發表的 : 還是不明白-.- 例如我整了一個選單出來是 應該怎樣加上去 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 |
引用 | 編輯
tw2twtw
2011-07-06 18:52 |
16樓
▲ ▼ |
entity_set_float(ent,EV_FL_takedamage,0.0) //設定成不能被攻擊就好了....
x0 |
引用 | 編輯
honfai99
2011-07-08 21:05 |
20樓
▲ ▼ |
可能做出一個好 Think 還是不能做出災厄.. 我做的災厄的 NPC 們都很容易卡住..
只要是彎路就會卡住在牆角... 做 waypoints 又怕他們只會行同一路徑.. waypoints 的話就不會追蹤玩家來攻擊.. 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 |
引用 | 編輯
zxcvasd2
2011-07-09 23:36 |
25樓
▲ ▼ |
husano大大喔
為什麼在我學寫npc的時候你不發這個post, 現在我學成了就發出來了 0.0 話說這個post對新手npc入門還挺有用喔 x0 |