廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 331 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
11922911
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎
初露鋒芒
級別: 初露鋒芒 該用戶目前不上站
推文 x36 鮮花 x76
分享: 轉寄此文章 Facebook Plurk Twitter 版主評分版主評分版主評分 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x4
[插件] [OO] 資源管理器 API (避免寫死檔案位置在程式碼之中)  (model, sound, sprite, generic)
原創文章
【插件資訊】

插件來源:原創
使用指令:無
安裝路徑:addons/amxmodx

【插件介紹】


安裝需求:
* AMXX 1.9.0+
OO 模塊

我做了個 API 來避免寫死一些檔案的位置在程式碼之中 (簡單來說就是沒啥用的東西
有點像 ZP 5.0 的 amx_settings_api.sma
但我把它做得更方便使用並只針對資源檔案, 使用了 json 來讀取檔案位置

先來看個使用範例: (assets_example.sma)
複製程式
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <oo_assets>

new Assets:g_oAssets;

public plugin_precache()
{
       // 建立物件
       g_oAssets = oo_new("Assets");

       // 為這物件讀取 json (以下來說, 讀取的位置就是 configs/assets/example.json)
       oo_call(g_oAssets, "LoadJson", "assets/example.json");
}

public plugin_init()
{
       register_plugin("Assets Exmaple", "0.1", "holla");

       RegisterHam(Ham_Item_Deploy, "weapon_knife", "OnKnifeDeploy_Post", 1);
       RegisterHam(Ham_TraceAttack, "worldspawn", "OnWorldSpawnTraceAttack_Post", 1);

       register_forward(FM_EmitSound, "OnEmitSound");
}

public OnKnifeDeploy_Post(ent)
{
       // 檢查有效實體
       if (!pev_valid(ent))
              return;

       // 獲取小刀的主人 (玩家id)
       new player = get_ent_data_entity(ent, "CBasePlayerItem", "m_pPlayer");
       if (!player)
              return;

       // 從資源物件中獲取 "v_knife" 的模組檔位置
       static model[32];
       if (AssetsGetModel(g_oAssets, "v_knife", model, charsmax(model)))
       {
              // 改變玩家的小刀模組
              set_pev(player, pev_viewmodel2, model);
       }
}

public OnWorldSpawnTraceAttack_Post(ent, attacker, Float:damage, Float:direction[3], tr, damagebits)
{
       // 檢查有效攻擊者
       if (!is_user_alive(attacker))
              return;

       // 攻擊者正在使用小刀
       if (get_user_weapon(attacker) == CSW_KNIFE)
       {
              // 從資源物件中獲取 "shockwave" 的 spr
              new sprite = AssetsGetSprite(g_oAssets, "shockwave");
              if (sprite)
              {
                     // 獲取玩家身處的座標
                     static Float:origin[3];
                     pev(attacker, pev_origin, origin);

                     // 在玩家的位置製造一個衝擊波
                     message_begin_f(MSG_PVS, SVC_TEMPENTITY, origin);
                     write_byte(TE_BEAMCYLINDER); // TE id
                     write_coord_f(origin[0]); // x
                     write_coord_f(origin[1]); // y
                     write_coord_f(origin[2]); // z
                     write_coord_f(origin[0]); // x axis
                     write_coord_f(origin[1]); // y axis
                     write_coord_f(origin[2] + 250.0); // z axis
                     write_short(sprite); // sprite
                     write_byte(0); // startframe
                     write_byte(0); // framerate
                     write_byte(10); // life
                     write_byte(30); // width
                     write_byte(0); // noise
                     write_byte(200); // red
                     write_byte(200); // green
                     write_byte(200); // blue
                     write_byte(200); // brightness
                     write_byte(0); // speed
                     message_end();
              }
       }
}

public OnEmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
{
       // 檢查生存
       if (!is_user_alive(id))
              return FMRES_IGNORED;
       
       // weapons/
       if (strlen(sample) > 8)
       {
              // 小刀打到牆
              if (equal(sample[8], "knife_hitwall", 13))
              {
                     // 從資源物件在 "knife_hitwall" 中隨機獲取一個音效 (為何隨機? 因為音效可多於一個)
                     static sound[32];
                     if (AssetsGetRandomSound(g_oAssets, "knife_hitwall", sound, charsmax(sound)))
                     {
                            // 取代原本的音效
                            emit_sound(id, channel, sound, volume, attn, flags, pitch);
                            return FMRES_SUPERCEDE;
                     }
              }
              
              // 小刀揮空氣
              if (equal(sample[8], "knife_slash", 11))
              {
                     // 從資源物件在 "knife_spk" 中隨機獲取一個 generic 檔 (為何隨機? 因為音效可多於一個)
                     static spk[32];
                     if (AssetsGetRandomGeneric(g_oAssets, "knife_spk", spk, charsmax(spk)))
                     {
                            // 播放音效
                            client_cmd(0, "spk %s", spk);

                            // 阻止原本的聲音播放
                            return FMRES_SUPERCEDE;
                     }
              }
       }

       return FMRES_IGNORED;
}

JSON檔案設定: (configs/assets/example.json)
複製程式
{
    "models": {
        "v_knife" : "models/v_knife_r.mdl"
    },
    "sounds": {
        "knife_hitwall" : ["weapons/hegrenade-1.wav", "weapons/hegrenade-2.wav"]
    },
    "generics" : {
        "knife_spk" : ["sound/hostage/hos1.wav", "sound/hostage/hos2.wav", "sound/hostage/hos3.wav"]
    },
    "sprites" : {
        "shockwave" : "sprites/shockwave.spr"
    }
}


這裡注意:
* 每個 model 或 sprite 只能對應一個檔案
* 而每個 sound 或 generic 就可以對應多於一個檔案
* LoadJson 只能在 plugin_precache() 裡面呼叫


這個範例插件的作用就是先載入JSON來讀取資源檔案位置並自動precache預載,
然後小刀打牆會產生一個衝擊波(sprite) 和 爆炸音效(sound),
小刀揮空時播放人質音效(generic),
最後, 小刀模組改為CS1.5的樣式 (model),
四種資源都示範了一次

INC檔一覽 (oo_assets.inc)
複製程式
// 獲取 SPR 檔
stock AssetsGetSprite(any:this, const key[])

// 獲取 模組 檔
stock AssetsGetModel(any:this, const key[], model[], len)

// 隨機獲取一個 generic 檔 (為何隨機? 因為檔案可多於一個)[/color]
stock bool:AssetsGetRandomGeneric(any:this, const key[], sound[], len)

// 獲取 generic 檔的動態陣列 handle
stock Array:AssetsGetGeneric(any:this, const key[])

// 隨機獲取一個 音效 檔 (為何隨機? 因為檔案可多於一個)
stock bool:AssetsGetRandomSound(any:this, const key[], sound[], len)

// 獲取 音效 檔的動態陣列 handle
stock Array:AssetsGetSound(any:this, const key[])

oo_assets.sma 是核心API 插件

[此文章售價 1 雅幣已有 2 人購買]
若發現會員採用欺騙的方法獲取財富,請立刻舉報,我們會對會員處以2-N倍的罰金,嚴重者封掉ID!



[ 此文章被11922911在2024-05-16 16:54重新編輯 ]

此文章被評分,最近評分記錄
財富:500 (by amore12) | 理由: 辛苦了!!



YouTube: @holla16
獻花 x3 回到頂端 [樓 主] From:香港沒有資料 | Posted:2024-05-16 05:16 |
11922911
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎
初露鋒芒
級別: 初露鋒芒 該用戶目前不上站
推文 x36 鮮花 x76
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

看到以上的程式碼你可能會想, 那不是每一個插件也要弄一個 json? 表情
其實不是, 你可以只在一個插件中讀取一次json, 再把那個資源物件的id 分享給其他插件使用

以下是使用 XVar 把物件 id 分享給其他插件的方法

需要載入 json 的插件這樣寫:
複製程式
#include <amxmodx>
#include <oo_assets>

public Assets:AssetsObject;

public plugin_precache()
{
       AssetsObject = oo_new("Assets");
       oo_call(AssetsObject, "LoadJson", "assets/test.json");
}

用於簡化程序的一個stock function (可寫在你的自定義inc中)
複製程式
stock any:GetXVarObject(const name[])
{
       new xvar = get_xvar_id(name);
       if (xvar == -1)
              set_fail_state("XVar does not exist: %s", name);
       
       new any:object = get_xvar_num(xvar);
       if (!oo_object_exists(object))
              set_fail_state("Object does not exist: %d", object);

       return object;
}

這是其他插件A:
複製程式
new Assets:g_oAssets;

public plugin_init()
{
       g_oAssets = GetXVarObject("AssetsObject");
       register_clcmd("test_mp3", "CmdTestMp3");
}

public CmdTestMp3(id)
{
       static music[64];
       if (AssetsGetRandomGeneric(g_oAssets, "music", music, charsmax(music)))
              client_cmd(id, "mp3 play %s", music);
       
       return PLUGIN_HANDLED;
}

這是其他插件B:
複製程式
new Assets:g_oAssets;

public plugin_init()
{
       g_oAssets = GetXVarObject("AssetsObject");
       register_clcmd("test_spk", "CmdTestSpk");
}

public CmdTestSpk(id)
{
       static spk[64];
       if (AssetsGetRandomGeneric(g_oAssets, "spk", spk, charsmax(spk)))
              client_cmd(id, "spk %s", spk);
       
       return PLUGIN_HANDLED;
}

JSON檔案設定 (這只是個範例)
複製程式
{
       "generics" : {
              "music" : "sound/test/resident_evil.mp3",
              "spk" : "sound/test/door_stuck.wav"
       }
}

XVar 的詳細使用方法可以看看 a78 大的教學


[ 此文章被11922911在2024-05-16 18:52重新編輯 ]

此文章被評分,最近評分記錄
威望:5 (by amore12) | 理由: 辛苦了!!


YouTube: @holla16
獻花 x2 回到頂端 [1 樓] From:香港沒有資料 | Posted:2024-05-16 05:25 |
11922911
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎
初露鋒芒
級別: 初露鋒芒 該用戶目前不上站
推文 x36 鮮花 x76
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

如果擔心效能問題其實可以有一些應對方案
譬如在 plugin_init() 一開始就預先用一個變數來獲取某個檔案, 以後就用那個變數來設定 (只針對 model 或 sprite)
複製程式
new g_KnifeModel[64];
new g_ShockwaveSpr;
...
public plugin_init()
{
       ...
       AssetsGetModel(g_oAssets, "v_knife", g_KnifeModel, charsmax(g_KnifeModel));
       g_ShockwaveSpr = AssetsGetSprite(g_oAssets, "shockwave");
}

public OnKnifeDeploy_Post(ent)
{
       ...
       if (g_KnifeModel[0])
              set_pev(player, pev_viewmodel2, g_KnifeModel);
}

public OnWorldSpawnTraceAttack_Post(ent, attacker, Float:damage, Float:direction[3], tr, damagebits)
{
       ...
       if (g_ShockwaveSpr)
       {
              message_begin_f(MSG_PVS, SVC_TEMPENTITY, origin);
              write_byte(TE_BEAMCYLINDER); // TE id
              ...
              write_short(g_ShockwaveSpr);
              message_end();
       }
}

而 sound 及 generic 則可以預先獲取 Array 的 handle
複製程式
new Array:g_aHitWallSound;
new Array:g_aSlashSound;
...
public plugin_init()
{
       ...
       g_aHitWallSound = AssetsGetSound(g_oAssets, "knife_hitwall");
       g_aSlashSound = AssetsGetGeneric(g_oAssets, "knife_spk");
}

複製程式
public OnEmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
{
       ...
       if (equal(sample[8], "knife_hitwall", 13))
       {
              if (g_aHitWallSound != Invalid_Array)
              {
                     static sound[64];
                     ArrayGetRandomString(g_aHitWallSound, sound, charsmax(sound));
                     emit_sound(id, channel, sound, volume, attn, flags, pitch);
                     return FMRES_SUPERCEDE;
              }
       }
       if (equal(sample[8], "knife_slash", 11))
       {
              if (g_aSlashSound != Invalid_Array)
              {
                     static sound[64];
                     ArrayGetRandomString(g_aSlashSound, sound, charsmax(sound));
                     client_cmd(0, "spk %s", sound);
                     return FMRES_SUPERCEDE;
              }
       }
}

複製程式
stock ArrayGetRandomString(Array:handle, sound[], maxlen)
{
       ArrayGetString(handle, random(ArraySize(handle)), sound, maxlen);
}


[ 此文章被11922911在2024-05-16 18:55重新編輯 ]

此文章被評分,最近評分記錄
支持度:100 (by amore12) | 理由: 辛苦了!!


YouTube: @holla16
獻花 x2 回到頂端 [2 樓] From:香港沒有資料 | Posted:2024-05-16 13:23 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.022409 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言