引用 | 編輯
xhsu
2014-07-29 11:03 |
樓主
▼ |
||
x1
在AMXMODX1.80之後,似乎支持創建屬於自己的事件觸發接口了……那好,我今天就帶大家學習一下怎麽創造一個事件。 (抱歉各位,我是大陸人,翻牆慕名而來,語法錯誤敬請諒解!謝謝!) 1.什麽是“事件”? 這裏說的不是指ham模塊或者fm模塊的register forward,也不是register ham 而是inc裏直接由forward xxxxxx(any:...)觸發的 最常見的是啥?當然是每個插件都看得到的forward plugin_init()了 當然,plugin_native, plugin_precache等等都是 這裏要教的就是,怎麽用插件創造一個這樣的事件。 2.Pre事件與Post事件。 這兩個對於大部分人都很熟悉,我也不多說,能看懂上面文字的,也一定能明白Pre和Post事件的區別。 (簡單提一下,Pre事件就是“預”,可以打斷阻止其發生,Post事件打斷了也沒用,因爲已經發生過了) 但是對於forward來說,創造pre事件或者post事件都差不多,甚至沒有區別。(後面說) 3.第一步 首先肯定要#include <amxmodx>不必多說 即使是一個事件,我們也需要一個“容器”來承接返回值。 所以像這樣:(先以Post事件爲例) new g_fwDummyResult, Post_Gift 接下來,我們需要在plugin_init()裏面創造事件! Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) 這就是我們需要詳解的部分了! 前面的Post_Gift = CreateMultiForward()自然不必多說,獲取事件返回編號值。 第一項:"amx_event_head_shot"這個字符串,就是相當於字符串plugin_init——子插件裏的回調函數名,也是forward xxx(any:...)那個xxx的內容 第二項的內容,可以說是關鍵。讓我們看看amxconst.inc裏給的: #define ET_IGNORE 0 //ignore return val #define ET_STOP 1 //stop on PLUGIN_HANDLED #define ET_STOP2 2 //same, except return biggest #define ET_CONTINUE 3 //no stop, return biggest 一般來說,Post事件用ET_IGNORE,Pre事件用ET_CONTINUE 這裏我的例子是Post事件,故用ET_IGNORE 第三項,則是事件給的參數。例如這個,將來我要寫在子插件裏的是什麽? forward amx_event_head_shot(iVictim, iAttacker) 玩家是屬於1-32區間內的整數,所以——我們要用FP_CELL 再看看amxconst.inc給的。 #define FP_CELL 0 //整數 #define FP_FLOAT 1 //浮點數 #define FP_STRING 2 //字符串 #define FP_ARRAY 4 //數組 根據你的forward事件的需求,一個逗號一個逗號(據說可以無限延長)的填進這些FP_XXX (注:如果要觸發浮點數組,例如pev獲取的坐標,向量,角度等等,怎麽辦呢?很簡單,用FP_FLOAT | FP_ARRAY。參見多種傷害類型並存應該怎麽做,原理一樣) 這樣,我們的事件就算注冊完了! (抱歉,剛剛寫一半斷電了,趕緊先發第一部分。。) x2
|
引用 | 編輯
xhsu
2014-07-29 11:11 |
1樓
▲ ▼ |
4.第二步
事件注冊完了,但是我們並沒有規定什麽時候觸發啊?所以我們得觸發他。 (這裏我們以爆頭觸發爲例) public plugin_init() { register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR); Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) register_event("DeathMsg","EventDeath","a","3=1","5=0") //這樣過濾,就會僅僅觸發爆頭 } public EventDeath() { new iVictim = read_data(2) new iAttacker = read_data(1) fm_set_user_money(iAttacker, get_pdata_int(iAttacker, m_pdata_iMoney)+1000, 1) ExecuteForward(Post_Gift, g_fwDummyResult, iVictim, iAttacker) } 這樣,我們在給爆頭額外獎勵的同時,也會觸發一個事件。 (Post事件的特性也體現在這裏——所有東西都處理完畢,才觸發) 我們來講解一下ExecuteForward() 首先第一項,就是我們在注冊事件中的事件返回值了——Post_Gift = CreateMultiForward() 第二項……嗯,還記得我說過,即使一個事件也需要兩個變量嗎?就是這樣。即使你使用了ET_IGNORE,你也需要一個容器來盛放“0”這個沒用的返回值。 (g_fwDummyResult這個東西變成全局的其實也沒關係,因爲每觸發一個事件,就會被賦值一次,不會互相幹擾返回值) 然後第三項到第N項,就是我們的事件基本參數,也就是剛剛FP_CELL等等一一對應的數字。 (注意:剛剛你用了多少個FP_XXX,這裏就必須給滿所有參數,否則會出錯。) x0 |
引用 | 編輯
xhsu
2014-07-29 11:20 |
2樓
▲ ▼ |
5.結束了?沒有!Pre事件!
以上就是一個Post事件的來曆。 (以下部分選修~~) 那麽,有人要問,Pre事件呢? 其實對於插件來說,Pre事件和Post事件沒差多少。你讓不讓Pre事件打斷,都是你說了算的。 我們來看看: new g_fwDummyResult, Post_Gift, Pre_Gift public plugin_init() { register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR); Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) Pre_Gift = CreateMultiForward("amx_hook_head_shot", ET_CONTINUE) register_event("DeathMsg","EventDeath","a","3=1","5=0") } public EventDeath() { ExecuteForward(Pre_Gift, g_fwDummyResult) //執行Pre事件 if(g_fwDummyResult) return //如果Pre事件存在返回值,那麽主插件也返回 new iVictim = read_data(2) new iAttacker = read_data(1) fm_set_user_money(iAttacker, get_pdata_int(iAttacker, m_pdata_iMoney)+1000, 1) ExecuteForward(Post_Gift, g_fwDummyResult, iVictim, iAttacker) } 這樣一來,大家都明白了吧?在g_fwDummyResult被賦予返回值了以後,一旦不爲0,那就取消主插件內事件的執行。 所以,返回值其實可以做很多事……比如你要在一個think刷速度的插件內控制速度,可以選擇把速度設定爲返回值最高的那個插件。 等等等等……但總而言之,如果你不寫上if(g_fwDummyResult) return 那麽你的Pre事件也打不斷。所以,Pre到底能不能打斷,全看你。 這就是forward事件的創造,學會了嗎?如果還不會,可以回複我~ 以上 x0 |
引用 | 編輯
xhsu
2014-07-29 11:31 |
3樓
▲ ▼ |
順便說一下對本論壇的看法(個人)
1.插件都不開源……Allied Modders 的插件都必須開源,不開源還可能刪帖……(而且也無權限) 2.教學文都要威望……我有點懷疑這幾位是否真心想讓新人學習插件(哪怕是教怎麽用if,else,new的教學文也是如此) 3.能下載的插件都有一行討厭的字飄來飄去,下載者如果要做版本會直接pass,如果個人娛樂玩也愉快不到哪去,最終很可能會沒人用……當初你寫這個插件是讓大家都不用,還是希望廣爲流傳? 4.似乎以上都是爲了防止盜文啊?嗯……無論各位怎麽珍愛自己的勞動成果,這毫無錯誤。但是我要表明我的態度:我的插件沒有版權,歡迎改PLUGIN_AUTHOR或者顯示一行字說是某某人寫的;我的文章沒有版權,歡迎四處轉載不標明出處…… 以上 x3 |
引用 | 編輯
i-c0112
2014-08-01 20:49 |
4樓
▲ ▼ |
要不要再補齊一下 提醒大家 要發布 forward 的 宣告標頭.inc??
如果能再稍微花時間排版 整齊點 讓有心學習的人能更快看懂 除此之外 這篇已經確實發揮教學效果了 真的感謝分享 願意花時間幫助他人~~ 至於插件和教學文 存在不低的門檻 這樣的問題 說真的原因其實是缺乏正式管道讓創作人保護自己的權利 所以才會靠這種 不分好壞 一概把 有意獲得源碼的人 排擠在外 這種下下策 其實大家沒有一個不喜歡討論自己的成果 尤其各位應該都是滿腔熱血的在coding吧 x0 |
引用 | 編輯
xhsu
2014-08-04 09:05 |
5樓
▲ ▼ |
抱歉忘了這一段~關於forward的,感謝樓上提醒~
6.在inc裡面: 既然事件已經存在了,那麼我們怎麼讓別的插件調用它呢? 當然就是我們最初提到的forward啦! 我們還是以上面為例! (我原來還不會用code呢,感謝Nailaz教我!) 複製程式 forward amx_hook_head_shot() forward amx_event_head_shot(iVictim, iAttacker) 還記得我們上面的CreateMultiForward("amx_hook_head_shot", ET_CONTINUE)嗎? forward裡面的主要部分就是註冊事件時引號內的內容,括弧裡面的對應法則就是ExecuteForward裡面除了返回值以外的部分,按順序寫下來~ 這樣,整個事件就算是完成了~ (注:forward可以放在inc里然後用#include;當然也可以放在插件頭!) x0 |
引用 | 編輯
xuqiang52133
2014-11-26 21:51 |
6樓
▲ |
我有一个代码,能帮我加个东西吗?我的 QQ373734484。加我可以吗/我想问你点问题
x0 |