Skip to content

Commit

Permalink
Added GetBodygroup, SetBodygroup, GetSequenceInfo natives (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
dystopm committed Nov 26, 2023
1 parent 11ead5d commit cf757aa
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
42 changes: 42 additions & 0 deletions reapi/extra/amxmodx/scripting/include/reapi_engine.inc
Expand Up @@ -123,6 +123,48 @@ native GetBonePosition(const entity, const bone, Float:vecOrigin[3], Float:vecAn
*/
native GetAttachment(const entity, const attachment, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0});

/*
* Sets body group value based on entity's model group
*
* @param entity Entity index
* @param group Number of entity's model group index
* @param value Value to assign
*
* @return 1 on success, 0 otherwise
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
native SetBodygroup(const entity, const group, const value);

/*
* Gets body group value based on entity's model group
*
* @param entity Entity index
* @param group Number of entity's model group index
*
* @return Body group value
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
native GetBodygroup(const entity, const group);

/*
* Gets sequence information based on entity's model current sequence index
*
* @param entity Entity index
* @param piFlags Sequence flags (1 = sequence loops)
* @param pflFrameRate Sequence framerate
* @param pflGroundSpeed Sequence ground speed
*
* @return True on success, false otherwise
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
native bool:GetSequenceInfo(const entity, &piFlags, &Float:pflFrameRate, &Float:pflGroundSpeed);

/*
* Sets the name of the map.
*
Expand Down
104 changes: 104 additions & 0 deletions reapi/src/natives/natives_common.cpp
Expand Up @@ -312,6 +312,107 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params)
return TRUE;
}

/*
* Sets body group value based on entity's model group
*
* @param entity Entity index
* @param group Number of entity's model group index
* @param value Value to assign
*
* @return 1 on success, 0 otherwise
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
cell AMX_NATIVE_CALL amx_GetBodygroup(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_group };

CHECK_ISENTITY(arg_index);

CBaseEntity *pEntity = getPrivate<CBaseEntity>(params[arg_index]);
if (unlikely(pEntity == nullptr)) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__);
return 0;
}

if (FNullEnt(params[arg_index])) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__);
return 0;
}

return (cell)GetBodygroup(pEntity, params[arg_group]);
}

/*
* Gets body group value based on entity's model group
*
* @param entity Entity index
* @param group Number of entity's model group index
*
* @return Body group value
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
cell AMX_NATIVE_CALL amx_SetBodygroup(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_group, arg_value };

CHECK_ISENTITY(arg_index);

CBaseEntity *pEntity = getPrivate<CBaseEntity>(params[arg_index]);
if (unlikely(pEntity == nullptr)) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__);
return FALSE;
}

if (FNullEnt(params[arg_index])) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__);
return FALSE;
}

SetBodygroup(pEntity, params[arg_group], params[arg_value]);
return TRUE;
}

/*
* Gets sequence information based on entity's model current sequence index
*
* @param entity Entity index
* @param piFlags Sequence flags (1 = sequence loops)
* @param pflFrameRate Sequence framerate
* @param pflGroundSpeed Sequence ground speed
*
* @return True on success, false otherwise
* @error If the index is not within the range of 1 to maxEntities or
* the entity is not valid, an error will be thrown.
*
*/
cell AMX_NATIVE_CALL amx_GetSequenceInfo(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_flags, arg_framerate, arg_groundspeed };

CHECK_ISENTITY(arg_index);

CBaseEntity *pEntity = getPrivate<CBaseEntity>(params[arg_index]);
if (unlikely(pEntity == nullptr)) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__);
return FALSE;
}

if (FNullEnt(params[arg_index])) {
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__);
return FALSE;
}

int* pflags = reinterpret_cast<int*>(getAmxAddr(amx, params[arg_flags]));
float* pframerate = reinterpret_cast<float*>(getAmxAddr(amx, params[arg_framerate]));
float* pgroundspeed = reinterpret_cast<float*>(getAmxAddr(amx, params[arg_groundspeed]));

return (cell)GetSequenceInfo2(pEntity, pflags, pframerate, pgroundspeed);
}

/*
* Sets Think callback for entity
*
Expand Down Expand Up @@ -545,6 +646,9 @@ AMX_NATIVE_INFO Natives_Common[] =
{ "set_key_value_buffer", amx_set_key_value_buffer },
{ "GetBonePosition", amx_GetBonePosition },
{ "GetAttachment", amx_GetAttachment },
{ "GetBodygroup", amx_GetBodygroup },
{ "SetBodygroup", amx_SetBodygroup },
{ "GetSequenceInfo", amx_GetSequenceInfo },
{ "SetThink", amx_SetThink },
{ "SetTouch", amx_SetTouch },
{ "SetUse", amx_SetUse },
Expand Down
68 changes: 68 additions & 0 deletions reapi/src/reapi_utils.cpp
Expand Up @@ -223,6 +223,74 @@ void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Ve
}
}

void SetBodygroup(CBaseEntity *pEntity, int iGroup, int iValue)
{
studiohdr_t *pstudiohdr = static_cast<studiohdr_t *>(GET_MODEL_PTR(pEntity->edict()));
if (!pstudiohdr || iGroup > pstudiohdr->numbodyparts)
{
return;
}

mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup;

if (iValue >= pbodypart->nummodels)
{
return;
}

int iCurrent = (pEntity->pev->body / pbodypart->base) % pbodypart->nummodels;
pEntity->pev->body += (iValue - iCurrent) * pbodypart->base;
}

int GetBodygroup(CBaseEntity *pEntity, int iGroup)
{
studiohdr_t *pstudiohdr = static_cast<studiohdr_t *>(GET_MODEL_PTR(pEntity->edict()));

if (!pstudiohdr || iGroup > pstudiohdr->numbodyparts)
{
return 0;
}

mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((byte *)pstudiohdr + pstudiohdr->bodypartindex) + iGroup;

if (pbodypart->nummodels <= 1)
{
return 0;
}

int iCurrent = (pEntity->pev->body / pbodypart->base) % pbodypart->nummodels;
return iCurrent;
}

bool GetSequenceInfo2(CBaseEntity *pEntity, int *piFlags, float *pflFrameRate, float *pflGroundSpeed)
{
studiohdr_t *pstudiohdr = static_cast<studiohdr_t *>(GET_MODEL_PTR(pEntity->edict()));

if (!pstudiohdr || pEntity->pev->sequence >= pstudiohdr->numseq)
{
*piFlags = 0;
*pflFrameRate = 0;
*pflGroundSpeed = 0;
return false;
}

mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pEntity->pev->sequence);
*piFlags = pseqdesc->flags;
if (pseqdesc->numframes <= 1)
{
*pflFrameRate = 256.0f;
*pflGroundSpeed = 0.0f;
}
else
{
*pflFrameRate = pseqdesc->fps * 256.0f / (pseqdesc->numframes - 1);
*pflGroundSpeed = Q_sqrt(pseqdesc->linearmovement[0] * pseqdesc->linearmovement[0] + pseqdesc->linearmovement[1] * pseqdesc->linearmovement[1] + pseqdesc->linearmovement[2] * pseqdesc->linearmovement[2]);
*pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
}

return true;
}

void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType type)
{
switch (type)
Expand Down
3 changes: 3 additions & 0 deletions reapi/src/reapi_utils.h
Expand Up @@ -55,6 +55,9 @@ CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *p

void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles);
void GetAttachment(CBaseEntity *pEntity, int iAttachment, Vector *pVecOrigin, Vector *pVecAngles);
void SetBodygroup(CBaseEntity *pEntity, int iGroup, int iValue);
int GetBodygroup(CBaseEntity *pEntity, int iGroup);
bool GetSequenceInfo2(CBaseEntity *pEntity, int *piFlags, float *pflFrameRate, float *pflGroundSpeed);
void RemoveOrDropItem(CBasePlayer *pPlayer, CBasePlayerItem *pItem, GiveType type);

const char *getATypeStr(AType type);
Expand Down

0 comments on commit cf757aa

Please sign in to comment.