A Counter-Strike 2 server plugin that replaces weapon fire sounds based on equipped custom subclasses or official weapon definitions
- Custom weapon override: play a custom soundevent when a player fires a store-equipped subclass
- Official weapon fallback: map normal weapons by
item_def_indexto duplicated soundevents - Silencer aware: optional
target_event_unsilencedfor M4A1-S / USP-S - Low overhead: constant-time lookups per fire event
- CounterStrikeSharp
- Store API (required for custom weapon mapping)
- Resource Precacher (required when using custom .vsndevts names)
- Download the latest release
- Extract to
game/csgo/addons/counterstrikesharp/plugins/EmitSoundEditor - Restart the server or load the plugin
Path .\counterstrikesharp\configs\plugins\EmitSoundEditor\EmitSoundEditor.json:
{
"overrides": [
{
"subclass": "weapon_ak47+13",
"target_event": "weapon.example.fire"
},
{
"subclass": "weapon_m4a1_silencer+25",
"target_event": "weapon.example.fire_silenced",
"target_event_unsilenced": "weapon.example.fire"
}
],
"official_overrides": [
{
"item_def_index": 7,
"target_event": "dup.Weapon_AK47.Single"
},
{
"item_def_index": 60,
"target_event": "dup.Weapon_M4A1.Silenced",
"target_event_unsilenced": "dup.Weapon_M4A4.Single"
}
],
"force_mute_all_firebullets": false,
"custom_sound_default_enabled": true,
"mysql": {
"enabled": false,
"host": "127.0.0.1",
"port": 3306,
"database": "cs2",
"user": "root",
"password": "",
"table": "emsound_settings"
}
}| Field | Type | Description |
|---|---|---|
overrides |
array | Custom weapon subclass overrides. |
overrides[].subclass |
string | Right side of weapon_base:subclass |
overrides[].target_event |
string | Soundevent to play on fire |
overrides[].target_event_unsilenced |
string | Optional; used when the silencer is off |
official_overrides |
array | Fallback mapping by item_def_index to duplicated soundevents (example prefix: dup.) |
official_overrides[].item_def_index |
number | Official weapon item definition index |
official_overrides[].target_event |
string | Duplicated soundevent to play on fire |
official_overrides[].target_event_unsilenced |
string | Optional; used when the silencer is off |
force_mute_all_firebullets |
boolean | Optional global mute for native firebullet sounds |
custom_sound_default_enabled |
boolean | Default state for !emsound (custom sounds on/off) |
mysql |
object | Optional persistence for the !emsound toggle |
mysql.enabled |
boolean | Enable MySQL storage for per-player toggle |
mysql.host |
string | MySQL host |
mysql.port |
number | MySQL port |
mysql.database |
string | MySQL database name |
mysql.user |
string | MySQL user |
mysql.password |
string | MySQL password |
mysql.table |
string | Table name for toggle storage |
!emsoundtoggles custom sounds for the caller only and prints a localized message- If MySQL is enabled, the toggle is saved per SteamID and restored on reconnect
Short version (see Wiki for the full guide):
- Store uses
base:subclassin theweaponfield (e.g.,weapon_knife:weapon_knife_karambit+1550) weapons.vdatadefines the subclass only (e.g.,weapon_knife_karambit+1550)EmitSoundEditor.jsonuses subclass only inoverrides[].subclass
How it works:
- On equip or entity creation, the Store plugin parses
base:subclassand callsChangeSubclasswhen the active base matches - Inspect temporarily swaps the active weapon's subclass and then resets it
- Only one skin is equipped per weapon base to avoid conflicts
Store config example:
"Custom Weapon": {
"karambit": {
"karambit_custom": {
"uniqueid": "karambitcustom",
"type": "customweapon",
"weapon": "weapon_knife:weapon_knife_karambit+1550",
"price": "1000",
"slot": "1"
}
}
}Note
- Add a subclass entry like
weapon_knife_karambit+1550and pointm_szModel_AG2to your model - Ensure the
.vmdl_cexists under your addon path (uploaded/compiled)
- Author your soundevents (use any naming scheme you like)
- Compile sounds and
.vsndevts - Package to VPK / Workshop and distribute to clients
- Configure
EmitSoundEditor.json
AG2 ignores subclass fire-sound changes in weapons.vdata, so you must mute the original fire events and replay sounds via the plugin.
mute_sounds.vsndevts: contains the official parent fire events (e.g.,Weapon_AK47.Single, silenced variants) but withvolume = 0. These are referenced byweapons.vdata, so muting them prevents double sound.dup_sounds.vsndevts: exact copies of those events, but with new names (example prefix:dup.) and normal volume. The plugin uses these for non-custom weapons so default guns still sound normal.- your custom file (example:
custom_sounds.vsndevts): contains your custom fire events.
If you only mute without duplicates, all default weapons become silent. All three files must be compiled and packaged together, and their event names must match your plugin config.
- If you do not use
soundevents_addon.vsndevts, the engine will not auto-register your soundevents file. You must precache the custom.vsndevtsvia Resource Precacher, otherwise events may not play.
Recommended: use a custom filename to avoid map conflicts, and always precache it
target_event_unsilencedonly applies to silencer-capable weapons (M4A1-S / USP-S)- If a custom subclass is equipped, it takes priority over
official_overrides
Full Guide:
一个用于 CS2 服务器的枪声替换插件,可根据商店自定义武器或官方武器类型播放指定音效事件
- 自定义武器替换:根据商店装备的 subclass 播放指定音效
- 官方武器回退:按
item_def_index映射官方武器事件副本 - 消音器识别:支持
target_event_unsilenced分支 - 性能友好:开火事件使用常量时间查找
- CounterStrikeSharp
- Store API(自定义武器映射所需)
- Resource Precacher(当使用自定义 .vsndevts 名称时必需)
- 下载最新版本
- 解压到
game/csgo/addons/counterstrikesharp/plugins/EmitSoundEditor - 重启服务器或加载插件
路径 .\counterstrikesharp\configs\plugins\EmitSoundEditor\EmitSoundEditor.json:
{
"overrides": [
{
"subclass": "weapon_ak47+13",
"target_event": "weapon.example.fire"
},
{
"subclass": "weapon_m4a1_silencer+25",
"target_event": "weapon.example.fire_silenced",
"target_event_unsilenced": "weapon.example.fire"
}
],
"official_overrides": [
{
"item_def_index": 7,
"target_event": "dup.Weapon_AK47.Single"
},
{
"item_def_index": 60,
"target_event": "dup.Weapon_M4A1.Silenced",
"target_event_unsilenced": "dup.Weapon_M4A4.Single"
}
],
"force_mute_all_firebullets": false,
"custom_sound_default_enabled": true,
"mysql": {
"enabled": false,
"host": "127.0.0.1",
"port": 3306,
"database": "cs2",
"user": "root",
"password": "",
"table": "emsound_settings"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
overrides |
array | 自定义武器替换列表 |
overrides[].subclass |
string | weapon_base:subclass 的右侧部分 |
overrides[].target_event |
string | 开火时播放的音效事件 |
overrides[].target_event_unsilenced |
string | 可选,不消音时使用。 |
official_overrides |
array | 官方武器事件副本映射(建议使用 dup. 之类的前缀) |
official_overrides[].item_def_index |
number | 官方武器定义索引 |
official_overrides[].target_event |
string | 对应的副本音效事件 |
official_overrides[].target_event_unsilenced |
string | 可选,不消音时使用 |
force_mute_all_firebullets |
boolean | 可选,全局静音原始开火音效 |
custom_sound_default_enabled |
boolean | !emsound 的默认状态(自定义音效开/关) |
mysql |
object | 可选,!emsound 开关的持久化存储配置 |
mysql.enabled |
boolean | 是否启用 MySQL 存储玩家开关状态 |
mysql.host |
string | MySQL地址 |
mysql.port |
number | MySQL端口 |
mysql.database |
string | 数据库名称 |
mysql.user |
string | 数据库用户名 |
mysql.password |
string | 数据库密码 |
mysql.table |
string | 保存开关状态的表名 |
!emsound用于切换是否播放自定义音效(只对自己生效)- 如果启用了 MySQL,则开关状态会按 SteamID 保存在数据库中,并在重新连接时读取
简版说明(完整内容见 Wiki):
- 商店
weapon使用base:subclass(例如weapon_knife:weapon_knife_karambit+1550) weapons.vdata只定义 subclass(例如weapon_knife_karambit+1550)EmitSoundEditor.json的overrides[].subclass也只填 subclass
工作流程:
- 装备或实体创建时,商店插件解析
base:subclass,当武器 base 匹配时调用ChangeSubclass - 检视会临时切换当前武器的 subclass,之后恢复
- 同一 base 只允许装备一个皮肤,避免冲突
商店配置示例:
"Custom Weapon": {
"karambit": {
"karambit_custom": {
"uniqueid": "karambitcustom",
"type": "customweapon",
"weapon": "weapon_knife:weapon_knife_karambit+1550",
"price": "1000",
"slot": "1"
}
}
}Note
- 添加 subclass 条目,例如
weapon_knife_karambit+1550,并将m_szModel_AG2指向你的模型路径 - 确保
.vmdl_c已在 addon 路径中(已上传/编译)
- 编写音效事件文件
- 编译 sounds 与
.vsndevts - 打包并分发资源
- 配置
EmitSoundEditor.json
AG2 下 weapons.vdata 的 subclass 开火音效不会生效,因此必须先静音原始事件,再由插件播放
mute_sounds.vsndevts:写入父级官方开火事件(例如Weapon_AK47.Single及消音变体),但把volume = 0。这些事件被weapons.vdata引用,静音可避免原声叠加dup_sounds.vsndevts:上述事件的副本,名称改成新前缀(示例:dup.),音量正常。插件用它来给非自定义武器播放默认音效- 自定义音效文件(如
custom_sounds.vsndevts):放你的自定义开火事件
只静音而不做副本,会导致所有默认武器无声。三份文件必须一起编译与打包,事件名称必须与插件配置保持一致
- 如果不使用
soundevents_addon.vsndevts,引擎不会自动注册你的 soundevents 文件,此时必须通过 Resource Precacher 预载该自定义.vsndevts,否则事件可能无法播放
建议使用自定义文件名以避免与地图冲突,并务必进行预载
target_event_unsilenced仅适用于可装消音器的武器(M4A1-S / USP-S)- 若装备了自定义 subclass,将优先生效,覆盖
official_overrides
详情见: