Raised This Month: $51 Target: $400
 12% 

Need help with SDKCall thingy


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
headingWest
Junior Member
Join Date: Jan 2020
Old 01-05-2020 , 09:46   Need help with SDKCall thingy
Reply With Quote #1

I'm trying to make a small script which allows player to get themselves up using Adrenaline. Well, it seems that I've already got to this part, my script now revives player with the CTerrorPlayer::OnRevived function. But what I want to do next is make it so a player gets a speed boost after getting themselves up, pretty much like a normal use of adrenaline with all the effects afterwards. And now I'm stuck on it. I'm guessing CItem_Adrenaline::CompleteUse is just what I'm looking for, but it requires CTerrorPlayer* as a parameter and I have no idea how to pass that parameter to it. I've tried CBaseEntity::GetBaseEntity, but whatever, plugin just refuses to load and every single time shines with an "<Error>" prefix in console.

In error logs I get something like "CompleteUse requires pointer to an entity; none specified" or "Invalid handle", it varies, I'm confused already.

I have this gamedata file.

Code:
"Games"
{
	"left4dead2"
    	{
		"Offsets"
		{
			"CBaseEntity_GetBaseEntity"
			{
				"windows"	"5"
				"linux"		"6"
			}
			"CTerrorPlayer_OnRevived"
			{
				"windows"	"582"
				"linux"		"584"
			}
			"CItem_Adrenaline_CompleteUse"
			{
				"windows"	"446"
				"linux"		"448"
			}
		}
    	}
}
And this script.

Code:
        // CBaseEntity_GetBaseEntity
	StartPrepSDKCall (SDKCall_Player)
	if (!PrepSDKCall_SetFromConf (config, SDKConf_Virtual, "CBaseEntity_GetBaseEntity")) {
		
		CloseHandle (config);
		SetFailState ("There's been an error.");
		
	}
	PrepSDKCall_SetReturnInfo (SDKType_CBaseEntity, SDKPass_ByRef);
	CloseHandle (config);
	getBaseEntity = EndPrepSDKCall ();
	if (getBaseEntity == INVALID_HANDLE) SetFailState ("There's been an error.");
	
	// CTerrorPlayer_OnRevived
	StartPrepSDKCall (SDKCall_Player);
	if (!PrepSDKCall_SetFromConf (config, SDKConf_Virtual, "CTerrorPlayer_OnRevived")) {
		
		CloseHandle (config);
		SetFailState ("There's been an error.");
		
	}
	CloseHandle (config);
	revive = EndPrepSDKCall ();
	if (revive == INVALID_HANDLE) SetFailState ("There's been an error.");
	
	// CItem_Adrenaline_CompleteUse
	StartPrepSDKCall (SDKCall_Entity);
	if (!PrepSDKCall_SetFromConf (config, SDKConf_Virtual, "CItem_Adrenaline_CompleteUse")) {
		
		CloseHandle (config);
		SetFailState ("There's been an error.");
		
	}
	PrepSDKCall_AddParameter (SDKType_CBaseEntity, SDKPass_Pointer);
	CloseHandle (config);
	useAdrenaline = EndPrepSDKCall ();
	if (useAdrenaline == INVALID_HANDLE) SetFailState ("There's been an error.");
And here I'm calling SDKCall's.

Code:
public Action OnPlayerRunCmd (int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon) {
	
	if (!IsSurvivor (client) /*|| !IsSurvivorIncapacitated (client)*/) return Plugin_Continue;

	//new medkit = GetPlayerWeaponSlot (client, KIT_SLOT);
	if (buttons & IN_USE /*&& medkit != -1*/) {

		// RemoveEdict (medkit);
		// if (CVAR_SetDyingState) SetEntProp (client, Prop_Send, "m_currentReviveCount", 2);
		// SDKCall (revive, client);
		SDKCall (useAdrenaline, client, SDKCall (getBaseEntity, client));
		
	}
	
	return Plugin_Continue;
	
}
headingWest is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 01-05-2020 , 10:32   Re: Need help with SDKCall thingy
Reply With Quote #2

CItem_Adrenaline::CompleteUse is a method of CItem_Adrenaline and thus needs to be called with an instance of CItem_Adrenaline (which is a weapon_adrenaline entity) - the function doesn't actually appear to use anything from the this ptr, but it'll be needed by SM to find the function when calling it by index - at the moment you're actually calling whatever function happens to be at the same offset on CTerrorPlayer as that is what you're passing as this (the 2nd param you're calling the SDKCall function with).

As the function itself doesn't actually read the value, you could look it up by signature instead to avoid needing to create a weapon_adrenaline entity (then just use the Raw call type and pass 0 as the this ptr).

You don't need any of the GetBaseEntity stuff, just using SDKType_CBasePlayer for the param type and passing the client index will do the right thing.
__________________
asherkin is offline
headingWest
Junior Member
Join Date: Jan 2020
Old 01-05-2020 , 11:28   Re: Need help with SDKCall thingy
Reply With Quote #3

Quote:
Originally Posted by asherkin View Post
As the function itself doesn't actually read the value, you could look it up by signature instead to avoid needing to create a weapon_adrenaline entity (then just use the Raw call type and pass 0 as the this ptr).
I've changed my code like this. It doesn't work, server crashes, but at least it doesn't give out any plugin errors either. I thought there was no difference between looking up for the function by offset and by signature, since it's the same function? Is this difference the reason why it still doesn't work? If it is, that's unfortunate because it's kind of a problem for me to find out a function's signature.

Code:
        StartPrepSDKCall (SDKCall_Raw);
	if (!PrepSDKCall_SetFromConf (config, SDKConf_Virtual, "CItem_Adrenaline_CompleteUse")) {
		
		CloseHandle (config);
		SetFailState ("There's been an error.");
		
	}
	PrepSDKCall_AddParameter (SDKType_CBasePlayer, SDKPass_Pointer);
	CloseHandle (config);
	useAdrenaline = EndPrepSDKCall ();
	if (useAdrenaline == INVALID_HANDLE) SetFailState ("There's been an error.");
Code:
SDKCall (useAdrenaline, 0, client);
headingWest is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 01-05-2020 , 12:22   Re: Need help with SDKCall thingy
Reply With Quote #4

Quote:
Originally Posted by headingWest View Post
I thought there was no difference between looking up for the function by offset and by signature, since it's the same function?
They find the same function so have the same end result, but looking it up via a vtable offset requires finding the virtual function table, which requires having a valid pointer to an instance.

You should be able to just create a weapon_adrenaline entity briefly to make the call with, that'll be easiest.
__________________

Last edited by asherkin; 01-05-2020 at 12:22.
asherkin is offline
Lux
Veteran Member
Join Date: Jan 2015
Location: Cat
Old 01-05-2020 , 12:31   Re: Need help with SDKCall thingy
Reply With Quote #5

You still need to call the function with the Adrenaline entity as the this pointer.


PHP Code:
    StartPrepSDKCall (SDKCall_Entity);
    if (!
PrepSDKCall_SetFromConf (configSDKConf_Virtual"CItem_Adrenaline_CompleteUse")) {
        
        
CloseHandle (config);
        
SetFailState ("There's been an error.");
        
    }
    
PrepSDKCall_AddParameter (SDKType_CBasePlayerSDKPass_Pointer);
    
CloseHandle (config);
    
useAdrenaline EndPrepSDKCall ();
    if (
useAdrenaline == INVALID_HANDLESetFailState ("There's been an error."); 
//as example you pass adrenaline entity index(AdrenalineEntityIndex) to the virtual call
PHP Code:
SDKCall(useAdrenalineAdrenalineEntityIndexclient); 

Quote:
Originally Posted by asherkin View Post
As the function itself doesn't actually read the value, you could look it up by signature instead to avoid needing to create a weapon_adrenaline entity (then just use the Raw call type and pass 0 as the this ptr).
Asherkin ment calling the function directly with using the function address not a vtable call with SDKCall_Raw here is the signiture to use that.
PHP Code:
"Signatures"
{
    
"CItem_Adrenaline_CompleteUse"
    
{
        
"library"        "server"
        "linux"            "@_ZN16CItem_Adrenaline11CompleteUseEP13CTerrorPlayer"
        "windows"        "\x55\x8B\xEC\x81\xEC\x14\x01\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xA1\x2A\x2A\x2A\x2A\xD9\x40\x2C"
                            
/* 55 8B EC 81 EC 14 01 00 00 A1 ? ? ? ? 33 C5 89 45 FC A1 ? ? ? ? D9 40 2C */
    
}

Setting up sig SDKCall we use this "SDKConf_Signature"
PHP Code:
    StartPrepSDKCall (SDKCall_Raw);
    if (!
PrepSDKCall_SetFromConf (configSDKConf_Signature"CItem_Adrenaline_CompleteUse")) {
        
        
CloseHandle (config);
        
SetFailState ("There's been an error.");
        
    }
    
PrepSDKCall_AddParameter (SDKType_CBasePlayerSDKPass_Pointer);
    
CloseHandle (config);
    
useAdrenaline EndPrepSDKCall ();
    if (
useAdrenaline == INVALID_HANDLESetFailState ("There's been an error."); 
Calling sdkcall using sig would be like this, since it don't look like it needs the this ptr just pass 0 like asherkin mentioned.
PHP Code:
SDKCall(useAdrenaline0client); 
__________________
Connect
My Plugins: KlickME
[My GitHub]

Commission me for L4D
Lux is offline
headingWest
Junior Member
Join Date: Jan 2020
Old 01-06-2020 , 12:12   Re: Need help with SDKCall thingy
Reply With Quote #6

Both cases worked, thanks a lot!
headingWest is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 02:40.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode