|
前言:
自動槍塔本來打壞之後不能搜刮,因為角色檔案內加上了“不能偷竊”的旗標,等於它死後鼠標移到它上頭也不會有“使用/拿取”的圖示。在不用sfall腳本的情況下,需要用16進位編輯器修改自動槍塔的proto檔案(00000480.pro)把“不能偷竊”旗標移除。
但光是這樣還不算完美,因為會變成可以拿到它們本來不該給玩家拿到的武器(裝800發子彈的多管機槍),就算不管沒有正常的武器圖像,光是打壞一個自動槍塔就有多管機槍和一卡車子彈可拿也太不平衡了點,所以還得修改角色對應腳本,在死亡後執行把武器移除與加上適當數量子彈的部份。
這種做法缺點一是得修改個別的proto檔案、二是每種角色有自己的腳本,至少自動槍塔就分成山嶺軍事基地和鑽油平台兩種。同理要是想把哨兵機器人也改成可以搜刮,要動的檔案數量就更多了,還別提可能會和其他mod衝突到,得手動合併修改的部份。
當然這種時候就是需要方便的sfall腳本了,用兩個hook script一個global script就可以把全部細節都顧到,還可以擴充適用對象。
事前準備:
腳本源碼:
global script的部份是修改內存中的proto檔案資料,省去直接修改實際檔案的功夫:
- // gl_loot_bots.ssl
- procedure start;
- #include ".\HEADERS\DEFINE.H"
- #include ".\HEADERS\define_extra.h"
- procedure start begin
- if(game_loaded) then begin
- set_global_script_repeat(60);
- end else begin
- // Auto-Cannon
- set_proto_data(16777696, PROTO_CR_ACTION_FLAGS, (CFLG_NODROP + CFLG_NOLIMBS + CFLG_NOAGES + CFLG_NOHEAL + CFLG_FLATTN + CFLG_NOKNOCKDOWN));
- end
- end
复制代码
define_extra.h要從modders pack裡面取得,set_proto_data後面那堆加起來的玩意兒需要特別解說一下。如果你用16進位編輯器打開自動槍塔的proto檔案(00000480.pro)會看到這樣:
反白的部份就是可對該角色進行動作的旗標,數值是0x00004BE0,而define_extra.h內關於旗標的描述是:
- #define CFLG_BARTER 2 //0x00000002 - Barter (can trade with)
- #define CFLG_NOSTEAL 32 //0x00000020 - Steal (cannot steal from)
- #define CFLG_NODROP 64 //0x00000040 - Drop (doesn't drop items)
- #define CFLG_NOLIMBS 128 //0x00000080 - Limbs (cannot lose limbs)
- #define CFLG_NOAGES 256 //0x00000100 - Ages (dead body does not disappear)
- #define CFLG_NOHEAL 512 //0x00000200 - Heal (damage is not cured with time)
- #define CFLG_INVULN 1024 //0x00000400 - Invulnerable (cannot be hurt)
- #define CFLG_FLATTN 2048 //0x00000800 - Flatten (leaves no dead body)
- #define CFLG_SPECIAL 4096 //0x00001000 - Special (there is a special type of death)
- #define CFLG_RANGED 8192 //0x00002000 - Range (melee attack is possible at a distance)
- #define CFLG_NOKNOCKDOWN 16384 //0x00004000 - Knock (cannot be knocked down)
复制代码
0x00004BE0可以拆成0x00004000 + 0x00000800 + 0x00000200 + 0x00000100 + 0x00000080 + 0x00000040 + 0x00000020(16進位加法請自行參考相關資料),等於Knock、Flatten、Heal、Ages、Limbs、Drop、Steal七個旗標有被設定起來。
我們想讓自動槍塔可以被執行“使用/拿取”的動作就得把Steal旗標取消,所以新的數值應該要是(0x00004000 + 0x00000800 + 0x00000200 + 0x00000100 + 0x00000080 + 0x00000040) = 0x00004BC0
當然現在用上腳本就不需要自己手動把那些旗標值加總,直接把定義好的旗標變數扔進去用加號兜一起就好。
上面的global script讓自動槍塔可以被偷竊,死後就像一般屍體一樣可以搜刮。不過如果你有辦法摸近山嶺軍事基地槍塔旁邊對它們使用偷竊的話,你會發現可以直接偷到它們的多管機槍,因為它們一開始沒把武器放到手上(原本不可能被偷,自然就隨便些了),鑽油平台上的有特別在角色腳本內寫上地圖一載入就直接裝備武器,所以像你一進大廳才會看到它們執行舉起雙手多管機槍的動作。
當然你可以在山嶺軍事基地槍塔的腳本(WCTURRET.SSL)內也加上同樣自動裝備武器的部份,或是修改地圖檔把它們在背包內的武器放到左手(NPC要使用它們時會切換到右手物品格,你在NPC死前偷不了),不過修改地圖檔要生效得在還沒進入過該地圖才行。
這邊我用第三種方式:限制它們還活著時不能被偷竊。
sfall 3.5版加上了hs_useskill這個hook script,在使用任何技能時都會觸發腳本,所以腳本內容可以簡單這樣寫:
- // hs_useskill.ssl
- procedure start;
- #include ".\HEADERS\DEFINE.H"
- #include ".\HEADERS\define_extra.h"
- procedure start begin
- variable user, target, skill;
- if not init_hook then begin
- user := get_sfall_arg;
- target := get_sfall_arg;
- skill := get_sfall_arg;
- if ((user == dude_obj) and (skill == SKILL_STEAL)) then begin
- if ((obj_pid(target) == 16777696) and (not (is_critter_dead(target)))) then begin
- set_sfall_return(0);
- end
- end
- end
- end
复制代码
邏輯本身很簡單,如果使用技能者是玩家(dude_obj)而且使用技能是偷竊,就檢查被使用技能的對象,如果對方是自動槍塔(PID為16777696)而且沒有死,腳本就回傳0值。hs_useskill只要回傳數值不是-1,就會擋下角色使用技能後本來該正常執行的其他部份。在遊戲內實際情況是你對它們進行偷竊只會看到自己角色雙手動一動就沒了,不會開啟雙方物品欄。
OK,現在自動槍塔是死後才可以搜刮了,不過這樣你還是會拿到它們的多管機槍,前面已經提過我覺得這樣太不平衡,於是得再動些手腳讓它們死後武器被移除,另外加上一些子彈在它們物品欄內。
舊的正規作法是修改角色各別腳本(WCTURRET.SSL/QCTURRET.SSL)加上destroy_p_proc程序,它們死後會執行destroy_p_proc內的指令。不過可以用一個腳本就能解決的事,何必用上兩個呢?
sfall 1.46版開始就有hs_ondeath這個hook script,在任何角色死亡時都會觸發腳本,不過這腳本就比較複雜了:
- // hs_ondeath.ssl
- procedure start;
- #include ".\HEADERS\DEFINE.H"
- #include ".\HEADERS\define_extra.h"
- procedure start begin
- variable critter, removed_item, ammo, ammo_count;
- if not init_hook then begin
- critter := get_sfall_arg;
- // Auto-Cannon
- if (obj_pid(critter) == 16777696) then begin
- if (obj_is_carrying_obj_pid(critter, PID_DUAL_MINIGUN)) then begin
- if (random(0, 1) == 1) then begin
- ammo := create_object(PID_5MM_AP, 0, 0);
- ammo_count := random(1, 2);
- add_mult_objs_to_inven(critter, ammo, ammo_count);
- end else begin
- ammo := create_object(PID_5MM_JHP, 0, 0);
- ammo_count := random(1, 2);
- add_mult_objs_to_inven(critter, ammo, ammo_count);
- end
- end
- if ((obj_is_carrying_obj_pid(critter, PID_HEAVY_DUAL_MINIGUN)) and (random(0, 1) == 1)) then begin
- ammo := create_object(PID_223_FMJ, 0, 0);
- ammo_count := random(1, 2);
- add_mult_objs_to_inven(critter, ammo, ammo_count);
- end
- while ((obj_is_carrying_obj_pid(critter, PID_DUAL_MINIGUN)) or (obj_is_carrying_obj_pid(critter, PID_HEAVY_DUAL_MINIGUN))) do begin
- removed_item := obj_carrying_pid_obj(critter, PID_DUAL_MINIGUN);
- rm_obj_from_inven(critter, removed_item);
- destroy_object(removed_item);
- removed_item := obj_carrying_pid_obj(critter, PID_HEAVY_DUAL_MINIGUN);
- rm_obj_from_inven(critter, removed_item);
- destroy_object(removed_item);
- end
- end
- end
- end
复制代码
遊戲內自動槍塔拿的武器有兩種,山嶺軍事基地的是拿Dual Minigun,傷害屬性等同復仇者機槍,鑽油平台的是拿傷害更高一級、用.223 FMJ的Heavy Dual Minigun,所以得照不同武器給不同種類彈藥。
我在腳本中寫的方式是拿Dual Minigun的會有50%機率身上放5mm JHP、50%機率是放5mm AP,彈藥數量是隨機1至2份。拿Heavy Dual Minigun的會有50%機率在身上放.223 FMJ,另外50%機率是沒子彈,彈藥數量同樣隨機1至2份。
其實可以不需要用到while ... do迴圈來移除武器,因為它們基本上就只會有一把,那樣只是做得徹底一點保證完全移除。
這三個腳本可以繼續擴充,像是把哨兵機器人也納入,拿多管機槍的死後可以拿到5mm,或是對玩家角色進行修理或科學檢定,加個機率讓你有機會能“拆下”武器(其實是塞一把武器給它們)等等。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|