CChoreoScene::ParseEvent
0x00bb5510 · 4476 bytes · __thiscall
_ZN12CChoreoScene10ParseEventEP12CChoreoActorP14CChoreoChannel
Decompiled
undefined (3 params)
/* CChoreoScene::ParseEvent(CChoreoActor*, CChoreoChannel*) */
CChoreoEvent * __thiscall
CChoreoScene::ParseEvent(CChoreoScene *this,CChoreoActor *param_1,CChoreoChannel *param_2)
{
CCurveData *this_00;
int *piVar1;
bool bVar2;
char cVar3;
CChoreoEvent *this_01;
char *pcVar4;
undefined4 uVar5;
int iVar6;
long lVar7;
int iVar8;
int in_GS_OFFSET;
longdouble lVar9;
float fVar10;
double dVar11;
double dVar12;
float local_14c;
float local_144;
float local_140;
char local_120 [128];
char local_a0 [128];
int local_20;
local_20 = *(int *)(in_GS_OFFSET + 0x14);
this_01 = (CChoreoEvent *)AllocEvent(this);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
uVar5 = CChoreoEvent::TypeForName(pcVar4);
CChoreoEvent::SetType(this_01,uVar5);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
CChoreoEvent::SetName(this_01,pcVar4);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"{");
if (iVar6 != 0) {
(**(code **)(**(int **)(this + 0xa4) + 0xc))(*(int **)(this + 0xa4),"expecting {\n");
}
local_14c = 1.0;
bVar2 = false;
local_144 = 1.0;
local_140 = 1.0;
LAB_00bb5610:
do {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"}");
if (iVar6 == 0) {
LAB_00bb5936:
if (param_2 != (CChoreoChannel *)0x0) {
CChoreoChannel::AddEvent((CChoreoEvent *)param_2);
}
CChoreoEvent::SetActor(this_01,param_1);
CChoreoEvent::SetChannel(this_01,param_2);
if (bVar2) {
this_00 = (CCurveData *)(this_01 + 0x5c);
iVar6 = CCurveData::GetCount(this_00);
if ((iVar6 == 0) && (((local_140 != 1.0 || (local_144 != 1.0)) || (local_14c != 1.0)))) {
lVar9 = (longdouble)(*(code *)**(undefined4 **)this_01)(this_01);
fVar10 = (float)lVar9 * (1.0 - local_140);
lVar9 = (longdouble)(*(code *)**(undefined4 **)this_01)(this_01);
CCurveData::Add(this_00,fVar10,local_144,false);
CCurveData::Add(this_00,(fVar10 + (float)lVar9 * local_14c) * 0.5,local_144,false);
CCurveData::Add(this_00,(float)lVar9 * local_14c,local_144,false);
CCurveData::Resort(this_00,(ICurveDataAccessor *)this_01);
}
}
if (local_20 == *(int *)(in_GS_OFFSET + 0x14)) {
return this_01;
}
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
piVar1 = *(int **)(this + 0xa4);
if (*pcVar4 == '\0') {
(*(code *)((undefined4 *)*piVar1)[3])(piVar1,"expecting more tokens!");
goto LAB_00bb5936;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"time");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
cVar3 = (**(code **)(**(int **)(this + 0xa4) + 8))(*(int **)(this + 0xa4));
fVar10 = 1.0;
if (cVar3 != '\0') {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
dVar12 = strtod(pcVar4,(char **)0x0);
fVar10 = (float)dVar12;
}
CChoreoEvent::SetStartTime(this_01,(float)dVar11);
CChoreoEvent::SetEndTime(this_01,fVar10);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"ramp");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
local_140 = (float)dVar11;
cVar3 = (**(code **)(**(int **)(this + 0xa4) + 8))(*(int **)(this + 0xa4));
if (cVar3 != '\0') {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
local_144 = (float)dVar11;
}
bVar2 = true;
cVar3 = (**(code **)(**(int **)(this + 0xa4) + 8))(*(int **)(this + 0xa4));
if (cVar3 != '\0') {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
local_14c = (float)dVar11;
}
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"param");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
CChoreoEvent::SetParameters(this_01,pcVar4);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"param2");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
CChoreoEvent::SetParameters2(this_01,pcVar4);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"param3");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
CChoreoEvent::SetParameters3(this_01,pcVar4);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"pitch");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 != 0) {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"yaw");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
lVar7 = strtol(pcVar4,(char **)0x0,10);
CChoreoEvent::SetYaw(this_01,lVar7);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"loopcount");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 != 0) {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"resumecondition");
if (iVar6 == 0) {
CChoreoEvent::SetResumeCondition(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"fixedlength");
if (iVar6 == 0) {
CChoreoEvent::SetFixedLength(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"lockbodyfacing");
if (iVar6 == 0) {
CChoreoEvent::SetLockBodyFacing(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"distancetotarget");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
CChoreoEvent::SetDistanceToTarget(this_01,(float)dVar11);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"forceshortmovement");
if (iVar6 == 0) {
CChoreoEvent::SetForceShortMovement(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"synctofollowinggesture");
if (iVar6 == 0) {
CChoreoEvent::SetSyncToFollowingGesture(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"active");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
lVar7 = strtol(pcVar4,(char **)0x0,10);
CChoreoEvent::SetActive(this_01,lVar7 != 0);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"playoverscript");
if (iVar6 == 0) {
CChoreoEvent::SetPlayOverScript(this_01,true);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"tags");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"{");
if (iVar6 != 0) {
(**(code **)(**(int **)(this + 0xa4) + 0xc))(*(int **)(this + 0xa4),"expecting {\n");
}
while( true ) {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
if (*pcVar4 == '\0') break;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"}");
if (iVar6 == 0) goto LAB_00bb5610;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
V_strncpy(local_a0,pcVar4,0x80);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
CChoreoEvent::AddRelativeTag(this_01,local_a0,(float)dVar11);
}
}
else {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"sequenceduration");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
CChoreoEvent::SetGestureSequenceDuration(this_01,(float)dVar11);
goto LAB_00bb5610;
}
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"absolutetags");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = CChoreoEvent::TypeForAbsoluteTagName(pcVar4);
if (iVar6 == -1) {
(**(code **)(**(int **)(this + 0xa4) + 0xc))
(*(int **)(this + 0xa4),"expecting valid tag type!!!");
}
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar8 = _V_stricmp(pcVar4,"{");
if (iVar8 != 0) {
(**(code **)(**(int **)(this + 0xa4) + 0xc))(*(int **)(this + 0xa4),"expecting {\n");
}
while( true ) {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
if (*pcVar4 == '\0') break;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar8 = _V_stricmp(pcVar4,"}");
if (iVar8 == 0) goto LAB_00bb5610;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
V_strncpy(local_a0,pcVar4,0x80);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
CChoreoEvent::AddAbsoluteTag(this_01,iVar6,local_a0,(float)dVar11);
}
}
else {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"flextimingtags");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 != 0) {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"relativetag");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
V_strncpy(local_120,pcVar4,0x80);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
V_strncpy(local_a0,pcVar4,0x80);
CChoreoEvent::SetUsingRelativeTag(this_01,true,local_120,local_a0);
}
else {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"flexanimations");
if (iVar6 == 0) {
ParseFlexAnimations(*(ISceneTokenProcessor **)(this + 0xa4),this_01,true);
}
else {
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"event_ramp");
if (iVar6 == 0) {
CCurveData::Parse((CCurveData *)(this_01 + 0x5c),
*(ISceneTokenProcessor **)(this + 0xa4),
(ICurveDataAccessor *)this_01);
}
else {
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"cctype");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
uVar5 = CChoreoEvent::CCTypeForName(pcVar4);
CChoreoEvent::SetCloseCaptionType(this_01,uVar5);
}
else {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"cctoken");
piVar1 = *(int **)(this + 0xa4);
if (iVar6 == 0) {
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
CChoreoEvent::SetCloseCaptionToken(this_01,pcVar4);
}
else {
pcVar4 = (char *)(**(code **)*piVar1)(piVar1);
iVar6 = _V_stricmp(pcVar4,"cc_usingcombinedfile");
if (iVar6 == 0) {
CChoreoEvent::SetUsingCombinedFile(this_01,true);
}
else {
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"cc_combinedusesgender");
if (iVar6 == 0) {
CChoreoEvent::SetCombinedUsingGenderToken(this_01,true);
}
else {
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"cc_noattenuate");
if (iVar6 == 0) {
CChoreoEvent::SetSuppressingCaptionAttenuation(this_01,true);
}
}
}
}
}
}
}
}
goto LAB_00bb5610;
}
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"{");
if (iVar6 != 0) {
(**(code **)(**(int **)(this + 0xa4) + 0xc))(*(int **)(this + 0xa4),"expecting {\n");
}
while( true ) {
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),1);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
if (*pcVar4 == '\0') break;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
iVar6 = _V_stricmp(pcVar4,"}");
if (iVar6 == 0) goto LAB_00bb5610;
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
V_strncpy(local_a0,pcVar4,0x80);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
dVar11 = strtod(pcVar4,(char **)0x0);
(**(code **)(**(int **)(this + 0xa4) + 4))(*(int **)(this + 0xa4),0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))
(*(undefined4 **)(this + 0xa4));
lVar7 = strtol(pcVar4,(char **)0x0,10);
CChoreoEvent::AddTimingTag(this_01,local_a0,(float)dVar11,lVar7 != 0);
}
}
}
(**(code **)(**(int **)(this + 0xa4) + 0xc))
(*(int **)(this + 0xa4),"expecting relative tag\n");
goto LAB_00bb5610;
}
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
lVar7 = strtol(pcVar4,(char **)0x0,10);
CChoreoEvent::SetLoopCount(this_01,lVar7);
goto LAB_00bb5610;
}
(*(code *)((undefined4 *)*piVar1)[1])(piVar1,0);
pcVar4 = (char *)(**(code **)**(undefined4 **)(this + 0xa4))(*(undefined4 **)(this + 0xa4));
lVar7 = strtol(pcVar4,(char **)0x0,10);
CChoreoEvent::SetPitch(this_01,lVar7);
} while( true );
}
SourceMod gamedata
paste intoaddons/sourcemod/gamedata/<your_plugin>.txt
used as the SourceMod key — change to fit your plugin's convention
SourceMod library name (server / engine / matchmaking)
Just a Signatures{} block, ready to drop into a gamedata
file. Wire it up in your plugin however you like - SDKCall, DHooks,
raw memory ops, or anything else.
Signatures + Functions block. The plugin uses
DHookCreateFromConf - DHooks reads return type, this-type,
calling convention, and argument types straight from the gamedata. Less
boilerplate in the plugin, types travel with the gamedata.
Gamedata KeyValues
DHooks plugin example
Type inference is best-effort from the C signature - sanity-check the DHooks types before shipping.