求助,如何调用CBaseEntity_EmitSoundFilter

laoshi1337 一级用户组 20天前 153

 

inline SndOpEventGuid_t(FASTCALL *CBaseEntity_EmitSoundFilter)(IRecipientFilter &filter, CEntityIndex ent, const EmitSound_t &params);

我参考cs2fix里的实现,尝试在counterstrikesharp中添加类似的实现,但是遇见了2个问题,IRecipientFilter和EmitSound_t是counterstrikesharp没有的对象,没法获取,试了很多办法都不行。不知道有没有大佬解决了这个问题?

var func = VirtualFunction.CreateVoid<nint, uint,IntPtr>(GameData.GetSignature("CBaseEntity_EmitSoundFilter"));
func.Invoke(...);

ps:不是不想用play指令,某些场景下必须配合filter播放指定名单生效的实体声音


CSGO插件分享-申明 1、本网站名称:CSGO插件分享-中文站  网址:https://bbs.csgocn.net
2、本站的宗旨在于为CSGO玩家提供一个插件分享的中文资源平台,多数插件来源于SourceMod论坛,并配以中文介绍和安装教程。
3、欢迎有能力的朋友共享有趣的CSGO插件资源。
4、本站资源大多为百度网盘,如发现链接失效,可以点: 这里进行反馈,我们会第一时间更新。
最新回复 (9)
  • Ambr0se 一级用户组@Ta 19天前 0
    引用 2
    首先CSSharp有  [IRecipientFilter](https://docs.cssharp.dev/api/CounterStrikeSharp.API.Modules.Utils.RecipientFilter.html)
    其次EmitSound_t也只是一个很简单的结构体  你可以自己构建
  • 小男娘Treas~ 一级用户组@Ta 19天前 0
    引用 3
    Ambr0se 首先CSSharp有 [IRecipientFilter](https://docs.cssharp.dev/api/CounterStrikeSharp.API.Modules.Utils.Reci ...
    牛逼
  • laoshi1337 楼主 一级用户组@Ta 19天前 0
    引用 4
    Ambr0se 首先CSSharp有 [IRecipientFilter](https://docs.cssharp.dev/api/CounterStrikeSharp.API.Modules.Utils.Reci ...


    这个Utils.RecipientFilter不是c#的托管对象吗,不能直接通过VirtualFunction传递,我看到github里对这个的用法也只是限于usermessage里添加filter,也没有调用签名函数的例子,那这个要如何传到接口签名函数里去。。。
    我查看了UserMessageSend的源码,官方的做法也只是在c++里重新造一个filter

    static  void  UserMessageSend(ScriptContext&  scriptContext)
    {
            auto  message  =  scriptContext.GetArgument<UserMessage*>(0);
    
            CRecipientFilter  filter{};
            filter.AddRecipientsFromMask(message->GetRecipientMask()  ?  *message->GetRecipientMask()  :  0);
            ....
    }


    总不可能修改c++的代码自己传递slot通过NativeAPI返回CRecipientFilter吧

  • Ambr0se 一级用户组@Ta 19天前 0
    引用 5
    laoshi1337 Ambr0se 首先CSSharp有 [IRecipientFilter](https://docs.cssharp.dev/api/CounterStrikeSharp.API.Modules ...
    嗯确实是托管对象  我想的是用GC获取到对象地址  但我确实是说错了这个类中有List  所以不行
    但你可以试试(windows平台)
    private  MemoryFunctionVoid<nint>  sub_180751090  =  new("48  89  5C  24  ?  57  48  83  EC  ?  48  8D  79  ?  C6  41");
    private  MemoryFunctionVoid<nint>  sub_180752AC0  =  new("E9  ?  ?  ?  ?  CC  CC  CC  CC  CC  CC  CC  CC  CC  CC  CC  40  53  48  83  EC  ?  48  8B  05");

    nint  buffer  =  Marshal.AllocHGlobal(336);
    sub_180751090.Invoke(buffer);
    sub_180752AC0.Invoke(buffer);
  • Ambr0se 一级用户组@Ta 19天前 0
    引用 6
    Ambr0se 嗯确实是托管对象 我想的是用GC获取到对象地址 但我确实是说错了这个类中有List 所以不行 但你可以试试(windows平台) private MemoryFunctionVoid sub_18 ...
    这个是添加所有玩家
  • laoshi1337 楼主 一级用户组@Ta 19天前 0
    引用 7
    Ambr0se 这个是添加所有玩家

    我通过修改cs#的c++层的源码通过拿到了IRecipientFilter和EmitSound_t,但是调用CBaseEntity_EmitSoundFilter还是不成功

    struct EmitSound_t是从cs2fix复制的,CSingleRecipientFilter则是cs#自带的

    void* GetCSigleRecipientFilter(ScriptContext& script_context)
    {
        auto slot = script_context.GetArgument<int>(0);
        auto filter = new CSingleRecipientFilter(slot);
        return filter;
    }
    
    void* GetEmitSoundT(ScriptContext& script_context)
    {
        auto pszSound = script_context.GetArgument<const char*>(0);
        auto flVolume = script_context.GetArgument<float>(1);
        auto flPitch = script_context.GetArgument<float>(2);
    
        auto params = new EmitSound_t();
        params->m_pSoundName = pszSound;
        params->m_flVolume = flVolume;
        params->m_nPitch = flPitch;
        params->m_SoundLevel = SNDLVL_20dB;
    
        return params;
    }
            public static void EmitSoundFilter(CCSPlayerController entity, string pszSound, float flVolume = 1.0f, float flPitch = 1.0f)
            {
                if (entity == null || string.IsNullOrEmpty(pszSound))
                    return;
                var filter = NativeAPI.GetCSigleRecipientFilter(entity.Slot);
                var emit = NativeAPI.GetEmitSoundT(pszSound, flVolume, flPitch);
                var index = NativeAPI.GetCEntityIndex((int)entity.Index);
                MemoryFunctionWithReturn<IntPtr, uint, IntPtr, IntPtr> func = new(GameData.GetSignature("CBaseEntity_EmitSoundFilter"));
                _ = func.Invoke(filter, entity.EntityHandle.Value!.Index, emit);
            }

    这样调用会出现
    Exception Info: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
    Stack:
       at CounterStrikeSharp.API.Core.Helpers.InvokeNative(IntPtr)
       at CounterStrikeSharp.API.Core.Helpers.InvokeNative(IntPtr)
       at CounterStrikeSharp.API.Core.ScriptContext.InvokeNativeInternal()
       at CounterStrikeSharp.API.Core.ScriptContext.Invoke()
    于是我尝试直接从c++层调用

    void EmitSoundFilter(ScriptContext& script_context)
    {
        auto pszSound = script_context.GetArgument<const char*>(0);
        auto flVolume = script_context.GetArgument<float>(1);
        auto flPitch = script_context.GetArgument<float>(2);
    
        EmitSound_t params;
        params.m_pSoundName = pszSound;
        params.m_flVolume = flVolume;
        params.m_nPitch = flPitch;
        params.m_SoundLevel = SNDLVL_20dB;
    
        auto slot = script_context.GetArgument<int>(3);
        CRecipientFilter filter{};
        filter.AddRecipient(slot);
    
        int index = script_context.GetArgument<int>(4);
        //CEntityIndex entIndex(index);
    
        auto binary_name = script_context.GetArgument<const char*>(5);
        auto signature_hex_string = script_context.GetArgument<const char*>(6);
    
        auto* function_addr = FindSignature(binary_name, signature_hex_string);
        auto* pFunc = new ValveFunction(function_addr, 
                                        CONV_CDECL,
                                        { DATA_TYPE_POINTER, DATA_TYPE_INT, DATA_TYPE_POINTER },
                                        DATA_TYPE_POINTER
        );
    
        script_context.Push(&filter); 
        script_context.Push(index);
        script_context.Push(&params);
        pFunc->Call(script_context, 7);
    }
    NativeAPI.EmitSoundFilter(pszSound, flVolume, flPitch, entity.Slot, entity.Entity!.EntityInstance.Index, Addresses.ServerPath, GameData.GetSignature("CBaseEntity_EmitSoundFilter"));

    这个调用不会有上面的报错,但是也会导致服务端闪退,系统日志提示是server.dll的问题,但是没有说明原因
    经过我自己的测试,我得到的filter是可以使用的,我通过DispatchParticleEffect传递filter可以正常生成粒子
    所以我不知道是不是emitsound_t的原因还是调用方式错了

  • Ambr0se 一级用户组@Ta 19天前 0
    引用 8
    laoshi1337 我通过修改cs#的c++层的源码通过拿到了IRecipientFilter和EmitSound_t,但是调用CBaseEntity_EmitSoundFilter还是不成功
    你调用的是cs2fixes提到的吗
  • laoshi1337 楼主 一级用户组@Ta 19天前 0
    引用 9
    Ambr0se 你调用的是cs2fixes提到的吗
    重新编辑了下7L
  • laoshi1337 楼主 一级用户组@Ta 19天前 0
    引用 10
    Ambr0se 你调用的是cs2fixes提到的吗
    DispatchParticleEffect和EmitSoundFilter的签名均是复制最新的cs2fix的windows签名,在cs2fix里是可以正常调用,所以应该不是签名的问题
返回