diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index c1009b0..02e1d85 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -653,6 +653,8 @@ #define FCAP_ONOFF_USE 0x00000020 // Can be used by the player #define FCAP_DIRECTIONAL_USE 0x00000040 // Player sends +/- 1 when using (currently only tracktrains) #define FCAP_MASTER 0x00000080 // Can be used to "master" other entities (like multisource) +#define FCAP_MUST_RESET 0x00000100 // Should reset on the new round +#define FCAP_MUST_RELEASE 0x00000200 // Should release on the new round #define FCAP_DONT_SAVE 0x80000000 // Don't save this // UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!! @@ -713,7 +715,18 @@ enum ArmouryItemPack ARMOURY_HEGRENADE, ARMOURY_KEVLAR, ARMOURY_ASSAULT, - ARMOURY_SMOKEGRENADE + ARMOURY_SMOKEGRENADE, + ARMOURY_SHIELD, + ARMOURY_FAMAS, + ARMOURY_SG550, + ARMOURY_GALIL, + ARMOURY_UMP45, + ARMOURY_GLOCK18, + ARMOURY_USP, + ARMOURY_ELITE, + ARMOURY_FIVESEVEN, + ARMOURY_P228, + ARMOURY_DEAGLE, }; enum RewardType diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index 1c64826..32194ec 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -55,6 +55,34 @@ native get_key_value(const pbuffer, const key[], const value[], const maxlen); */ native set_key_value(const pbuffer, const key[], const value[]); +/* +* Gets the position of the bone +* +* @param entity Entity index +* @param bone Number of the bone +* @param vecOrigin Array to store origin in +* @param vecAngles Array to store angles in +* +* @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 GetBonePosition(const entity, const bone, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0}); + +/* +* Gets the position of the attachment +* +* @param entity Entity index +* @param attachment Number of the attachment +* @param vecOrigin Array to store origin in +* @param vecAngles Array to store angles in +* +* @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 GetAttachment(const entity, const attachment, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0}); + /* * Sets the name of the map. * diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index aa381b1..784ac98 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -181,14 +181,90 @@ cell AMX_NATIVE_CALL amx_set_key_value(AMX *amx, cell *params) return TRUE; } +/* +* Gets the position of the bone +* +* @param entity Entity index +* @param bone Number of the bone +* @param vecOrigin Array to store origin in +* @param vecAngles Array to store angles in +* +* @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 GetBonePosition(const entity, const bone, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0}); +*/ +cell AMX_NATIVE_CALL amx_GetBonePosition(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_bone, arg_origin, arg_angles }; + + CHECK_ISENTITY(arg_index); + + CBaseEntity *pEntity = getPrivate(params[arg_index]); + if (unlikely(pEntity == nullptr)) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (FNullEnt(params[arg_index])) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__); + return FALSE; + } + + Vector *pVecOrigin = (Vector *)getAmxAddr(amx, params[arg_origin]); + Vector *pVecAngles = (PARAMS_COUNT == 4) ? (Vector *)getAmxAddr(amx, params[arg_angles]) : nullptr; + GetBonePosition(pEntity, params[arg_bone], pVecOrigin, pVecAngles); + return TRUE; +} + +/* +* Gets the position of the attachment +* +* @param entity Entity index +* @param attachment Number of the attachment +* @param vecOrigin Array to store origin in +* @param vecAngles Array to store angles in +* +* @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 GetAttachment(const entity, const attachment, Float:vecOrigin[3], Float:vecAngles[3] = {0.0, 0.0, 0.0}); +*/ +cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_bone, arg_attachment, arg_angles }; + + CHECK_ISENTITY(arg_index); + + CBaseEntity *pEntity = getPrivate(params[arg_index]); + if (unlikely(pEntity == nullptr)) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__); + return FALSE; + } + + if (FNullEnt(params[arg_index])) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: worldspawn not allowed", __FUNCTION__); + return FALSE; + } + + Vector *pVecOrigin = (Vector *)getAmxAddr(amx, params[arg_attachment]); + Vector *pVecAngles = (PARAMS_COUNT == 4) ? (Vector *)getAmxAddr(amx, params[arg_angles]) : nullptr; + GetAttachment(pEntity, params[arg_bone], pVecOrigin, pVecAngles); + return TRUE; +} + AMX_NATIVE_INFO Natives_Common[] = { - { "FClassnameIs", amx_FClassnameIs }, - { "GetGrenadeType", amx_GetGrenadeType }, - { "engset_view", amx_engset_view }, - { "get_viewent", amx_get_viewent }, - { "get_key_value", amx_get_key_value }, - { "set_key_value", amx_set_key_value }, + { "FClassnameIs", amx_FClassnameIs }, + { "GetGrenadeType", amx_GetGrenadeType }, + { "engset_view", amx_engset_view }, + { "get_viewent", amx_get_viewent }, + { "get_key_value", amx_get_key_value }, + { "set_key_value", amx_set_key_value }, + { "GetBonePosition", amx_GetBonePosition }, + { "GetAttachment", amx_GetAttachment }, { nullptr, nullptr } }; diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index 677dd97..288c165 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -618,7 +618,7 @@ void RegisterNatives_Members() g_amxxapi.AddNatives(EngineVars_Natives); } -BOOL set_member(void* pdata, const member_t *member, cell* value, size_t element) +cell set_member(void* pdata, const member_t *member, cell* value, size_t element) { switch (member->type) { case MEMBER_CLASSPTR: @@ -674,7 +674,7 @@ BOOL set_member(void* pdata, const member_t *member, cell* value, size_t element char *source = getAmxString(value); string_t newstr = (source && source[0] != '\0') ? ALLOC_STRING(source) : iStringNull; set_member(pdata, member->offset, newstr, element); - return TRUE; + return (cell)newstr; } case MEMBER_FLOAT: case MEMBER_INTEGER: @@ -806,7 +806,7 @@ cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, } setAmxString(dest, STRING(str), length); - return 1; + return (cell)str; } case MEMBER_FLOAT: case MEMBER_INTEGER: diff --git a/reapi/src/natives/natives_members.h b/reapi/src/natives/natives_members.h index b327244..d643ae9 100644 --- a/reapi/src/natives/natives_members.h +++ b/reapi/src/natives/natives_members.h @@ -2,7 +2,7 @@ void RegisterNatives_Members(); -BOOL set_member(void* pdata, const member_t *member, cell* value, size_t element); +cell set_member(void* pdata, const member_t *member, cell* value, size_t element); cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, size_t length = 0); bool isTypeReturnable(MType type); diff --git a/reapi/src/precompiled.h b/reapi/src/precompiled.h index 82ff883..84b7b6a 100644 --- a/reapi/src/precompiled.h +++ b/reapi/src/precompiled.h @@ -26,6 +26,7 @@ #include #include #include +#include // metamod SDK #include diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 5c5e032..75f0333 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -92,3 +92,109 @@ CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *p return pEntity; } + +void StudioFrameAdvanceEnt(edict_t *pEdict) +{ + float flInterval = gpGlobals->time - pEdict->v.animtime; + if (flInterval <= 0.001f) { + pEdict->v.animtime = gpGlobals->time; + return; + } + + if (pEdict->v.animtime == 0.0f) { + flInterval = 0.0f; + } + + studiohdr_t *pstudiohdr = static_cast(GET_MODEL_PTR(pEdict)); + if (!pstudiohdr) { + return; + } + + if (pEdict->v.sequence >= pstudiohdr->numseq || pEdict->v.sequence < 0) { + return; + } + + float flFrameRate = 256.0f; + mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + int(pEdict->v.sequence); + if (pseqdesc->numframes > 1) + { + flFrameRate = pseqdesc->fps * 256.0f / (pseqdesc->numframes - 1); + } + + pEdict->v.frame += flInterval * flFrameRate * pEdict->v.framerate; + pEdict->v.animtime = gpGlobals->time; + + if (pEdict->v.frame < 0.0f || pEdict->v.frame >= 256.0f) + { + // true if the sequence loops + if (pseqdesc->flags & STUDIO_LOOPING) + pEdict->v.frame -= int(pEdict->v.frame / 256.0f) * 256.0f; + else + pEdict->v.frame = (pEdict->v.frame < 0.0f) ? 0.0f : 255.0f; + } +} + +void FixupAngles(edict_t *pEdict, Vector &vecSrc) +{ + vecSrc.x -= pEdict->v.origin.x; + vecSrc.y -= pEdict->v.origin.y; + + float x = vecSrc.x; + float y = vecSrc.y; + float c = cos((pEdict->v.angles.y * M_PI / 180.0)); + float s = sin((pEdict->v.angles.y * M_PI / 180.0)); + + vecSrc.x = x * c - y * s; + vecSrc.y = y * c + x * s; + + vecSrc.x += pEdict->v.origin.x; + vecSrc.y += pEdict->v.origin.y; +} + +void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles) +{ + Vector vecOrigin, vecAngles; + edict_t *pEdict = pEntity->edict(); + + // force to update frame + StudioFrameAdvanceEnt(pEdict); + + pEntity->pev->angles.x = -pEntity->pev->angles.x; + GET_BONE_POSITION(pEdict, iBone, vecOrigin, vecAngles); + pEntity->pev->angles.x = -pEntity->pev->angles.x; + + if (!pEntity->IsPlayer()) { + FixupAngles(pEdict, vecOrigin); + } + + if (pVecOrigin) { + *pVecOrigin = vecOrigin; + } + + if (pVecAngles) { + *pVecAngles = vecAngles; + } +} + +void GetAttachment(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles) +{ + Vector vecOrigin, vecAngles; + edict_t *pEdict = pEntity->edict(); + + // force to update frame + StudioFrameAdvanceEnt(pEdict); + + GET_ATTACHMENT(pEdict, iBone, vecOrigin, vecAngles); + + if (!pEntity->IsPlayer()) { + FixupAngles(pEdict, vecOrigin); + } + + if (pVecOrigin) { + *pVecOrigin = vecOrigin; + } + + if (pVecAngles) { + *pVecAngles = vecAngles; + } +} diff --git a/reapi/src/reapi_utils.h b/reapi/src/reapi_utils.h index b9d760e..ea1a12f 100644 --- a/reapi/src/reapi_utils.h +++ b/reapi/src/reapi_utils.h @@ -53,4 +53,7 @@ ModelName GetModelAuto(TeamName team); void UTIL_ServerPrint(const char *fmt, ...); CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *pszItemName); +void GetBonePosition(CBaseEntity *pEntity, int iBone, Vector *vecOrigin, Vector *vecAngles); +void GetAttachment(CBaseEntity *pEntity, int iBone, Vector *pVecOrigin, Vector *pVecAngles); + extern void __declspec(noreturn) UTIL_SysError(const char *fmt, ...);