11922911
|
分享:
▼
x4
|
[插件] [OO] 資源管理器 API v0.3 (避免寫死檔案位置在程式碼之中) [2024-6-19 更新]
(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)
AssetsLoadJson(g_oAssets, "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() 裡面呼叫 * 在一些情況中, 你可能需要將 spr 視為 model, 舉個例子你要弄一個 env_sprite 的實體
這個範例插件的作用就是先載入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 檔 (為何隨機? 因為檔案可多於一個)
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[])
// 複製物件內容到另一個物件
// other 複製到 this
stock AssetsClone(any:this, any:other)
// 載入 JSON
// @return
// true 為成功, false 是失敗
stock bool:AssetsLoadJson(any:this, const filename[])
oo_assets.sma 是核心API 插件
[此文章售價 1 雅幣已有 2 人購買]
若發現會員採用欺騙的方法獲取財富,請立刻舉報,我們會對會員處以2-N倍的罰金,嚴重者封掉ID!
[ 此文章被11922911在2024-10-13 21:45重新編輯 ]
此文章被評分,最近評分記錄財富:500 (by amore12) | 理由: 辛苦了!! | |
|
|
|
YouTube: @holla16
|
x3
[樓 主]
From:香港沒有資料 | Posted:2024-05-16 05:16 |
|
|
11922911
|
分享:
▲
▼
看到以上的程式碼你可能會想, 那不是每一個插件也要弄一個 json? 其實不是, 你可以只在一個插件中讀取一次json, 再把那個資源物件的id 分享給其他插件使用
以下是使用 XVar 把物件 id 分享給其他插件的方法
需要載入 json 的插件這樣寫: 複製程式
#include <amxmodx>
#include <oo_assets>
public Assets:AssetsObject;
public plugin_precache()
{
AssetsObject = oo_new("Assets");
AssetsLoadJson(AssetsObject, "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-06-19 15:03重新編輯 ]
此文章被評分,最近評分記錄威望:5 (by amore12) | 理由: 辛苦了!! | |
|
|
|
YouTube: @holla16
|
x2
[1 樓]
From:香港沒有資料 | Posted:2024-05-16 05:25 |
|
|
11922911
|
分享:
▲
▼
如果擔心效能問題其實可以有一些應對方案 譬如在 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 |
|
|
|