Open kir68k opened 8 months ago
It's possible, though I'm not at all sure that I'd be motivated to implement and maintain support for it at this time. I'll leave this issue open in case it's revisited in the future.
Did you have a particular use case in mind? It doesn't sound like you're certain that TraceAttack
would be appropriate for your needs.
If nothing else, it wouldn't be too difficult to set up the hooks yourself — headshot_damage_modify
is a unique string used for CTFPlayer::TraceAttack
(this would be called when a player is hit). If you need more information on the hook setup (signatures, DHooks options), feel free to ask here.
I see. I want to specifically use this on my slightly modified version of a plugin for headshots on any hitscan weapon. This plugins uses TraceAttack to register whether a hit was landed on the head hitbox, if I understand correctly.
Ideally I'd have a convar to switch between normal crit and minicrit, but I primarily wanted to change it from simply using DMG_CRIT
for full crits to a minicrit, as to not be too overpowered.
Learning how the game handles crits and how it's DMG_CRIT for both, I found this plugin.
Also, I'd try setting up the hooks myself, but as said my knowledge is very limited, as in I started very recently. After learning more myself about how this plugin works I could try implementing this, possibly.
If you need more information on the hook setup (signatures, DHooks options), feel free to ask here.
As far as I understand, in classdefs.h there would have to be another struct for TraceAttack, right? I would try to add one to complete other parts that use that struct, but I don't quite understand where to get the values of the struct like m_iAmmoType
from. Is there a list anywhere of all these values? I don't know all their names.
The trace_t
struct is an alias for CGameTrace
.
In the context of implementing a TraceAttack
hook, you can just define it as an objectptr
in DHooks and not worry about creating a structure definition for it.
If you do care about the details, keep in mind that it inherits from CBaseTrace
so you'd need to define the members of each property you're interested in manipulating.
For the sake of prototyping for your own case, you'd probably be better off not dealing with classdefs.h
and the codegen stuff. Instead, you can calculate the offsets by hand, e.g.:
int offs_CBaseTrace_startpos = 0;
int offs_CBaseTrace_endpos = 12; // a vector is 3 float values and each float is 4 bytes each
int offs_CBaseTrace_plane = 24; // keep in mind that this value is the start position (the size of the previous member is added to it)
int offs_CBaseTrace_fraction = 44; // + size of cplane_t
int offs_CGameTrace_fractionleftsolid; // rest of the owl... (because this inherits from CBaseTrace, this starts at the end of that struct)
It's been a while, but I currently have time to implement this if I understand everything correctly, so far I understand:
g_TraceAttack(Post)
and a DynamicDetour g_DHookTraceAttack
need to be made
g_DHookOnTakeDamage
, e.g. g_DHookTraceAttack.SetFromConf
For clarity, a plugin with this could have TF2_TraceAttack
instead of TraceAttack
, like so:
public Action TF2_TraceAttack(int iVictim, int &iAttacker, int &iInflictor, float &flDamage,
int &iDamageType, int &iAmmoType, int iHitBox, int iHitgroup,
CritType &critType) {
if (iHitgroup == 1) {
critType = view_as<CritType>(1);
return Plugin_Changed;
}
return Plugin_Continue;
}
Would an implementation like this, where in this case if the value of iHitgroup
from the action is 1, set the crit type to a mini-crit, make sense, or am I misunderstanding something? I'm not exactly sure how the crit type could be modified in TraceAttack, but some weapons can do this, so it must be possible.
Sorry for all the questions, just a bit confused on how this could be achieved. If I understand everything right, I could try to implement it and make a PR if it works and doesn't crash. Thanks in advance.
I'm not exactly sure how the crit type could be modified in TraceAttack, but some weapons can do this, so it must be possible.
CTFPlayer::TraceAttack
receives a const CTakeDamageInfo
instance, so you should be able to modify that information in the pre-hook. It seems sound, though I don't know how that all plays out in reality (i.e. whether the game correctly handles this).
Note that a pre-hook on that function is before checks on whether or not player can take damage in the first place and hitgroups are updated, and the function passes a copy of CTakeDamageInfo
to AddMultiDamage
, so a post hook isn't really effective in mutating that.
Bonus aside: If your goal is to modify damage per-bullet for a shotgun, that won't fly — crits scale the aggregate damage of all bullets that land.
Otherwise, there is a plugin that modifies crits based on last hitgroup, but I believe that's only good if the last bullet to apply damage is on the desired hitgroup. If you want to apply minicrits if any bullet lands, then yes, a TF2_TraceAttack
would make sense.
Okay, I have the proper signature:
_ZN9CTFPlayer11TraceAttackERK15CTakeDamageInfoRK6VectorP10CGameTraceP15CDmgAccumulator
I've tried setting up a DynamicDetour
for it, like so:
g_DHookTraceAttack = new DynamicDetour(Address_Null, CallConv_THISCALL,
ReturnType_Void, ThisPointer_CBaseEntity);
g_DHookTraceAttack.SetFromConf(hGameConf, SDKConf_Signature, "CTFPlayer::TraceAttack()");
g_DHookTraceAttack.AddParam(HookParamType_CBaseEntity);
g_DHookTraceAttack.Enable(Hook_Pre, Internal_TraceAttack);
g_DHookTraceAttack.Enable(Hook_Post, Internal_TraceAttackPost);
The function is a void
, per sdkhooks/extension.cpp and the disassembler I got signatures from, so not sure what HookParamType
would be.
Then g_FwdTraceAttack
with ET_Ignore
(as TraceAttack is a void), and parameters according to how I defined it in the include file, so far so good?
The server reports "Exception reported: Invalid Handle 0" for Internal_TraceAttack
which looks like Internal_OnTakeDamage
, but for g_FwdTraceAttack
. Why would hParams
be invalid?
I can try modifying CallTakeDamageInfoForward
and the struct to include m_nHitbox
, m_hitGroup
, which are needed.
This feels more complicated than I expected, but my approach might be wrong. I'll read more about hooks later this week. Asking to know if I fully misunderstand this, or if it's at least somewhat right.
Thanks for helping so far.
Wanted to continue tomorrow, but tried now. Created a struct CTraceAttackInfo
, CallTraceAttackInfoForward
and a post hook forward. I'm a bit confused about the build process now, spcomp can't find the new created CTraceAttackInfo
, so it can't be compiled.
I did add it to the configure script, removed the Ninja file/build dir just in case, and the new sp file is in the generated
dir... Shouldn't this work, or am I missing something to add?
If you've defined CTraceAttackInfo
in classdefs/classdefs.h
then you'd need to add it to the list here.
Depending on how it's set up you may want to look at misc/generate_classes.py
, but it's admittedly hacked up for this project since I didn't expect other people to stray from the happy path of only trying to build it as-is.
Have you built a CTraceAttackInfo
hook outside of the plugin? I think you'd make better progress prototyping the whole thing without wrestling with the code generation tooling in this plugin and other quirks of class property alignment.
Hey, I have to wonder if it'd be possible to add this to ontakedamage.sp and .inc. I have limited sourcepawn knowledge currently so don't feel confident trying myself yet, but would really like this feature for a different plugin.