Few additions to fakemeta:
Implemented amb632 - lookup_sequence, also added set_controller (since it dealt with models). Implemented set_pev_string, for setting with an already allocated string handle. Also added pev_serial, to get the entity serial number.
This commit is contained in:
parent
2cbf7fca08
commit
a28a80e45f
|
@ -1,4 +1,5 @@
|
|||
#include "fakemeta_amxx.h"
|
||||
#include <studio.h> // HLSDK, for the animation natives
|
||||
|
||||
static cell AMX_NATIVE_CALL copy_infokey_buffer(AMX *amx, cell *params)
|
||||
{
|
||||
|
@ -7,7 +8,154 @@ static cell AMX_NATIVE_CALL copy_infokey_buffer(AMX *amx, cell *params)
|
|||
return MF_SetAmxString(amx, params[2], infobuffer, params[3]);
|
||||
}
|
||||
|
||||
int UTIL_stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
unsigned char c1, c2;
|
||||
|
||||
for (;;) {
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if (!c1 || !c2)
|
||||
break;
|
||||
|
||||
if (c1 == c2)
|
||||
continue;
|
||||
|
||||
if ((c1 = tolower(c1)) != (c2 = tolower(c2)))
|
||||
break;
|
||||
}
|
||||
return (int)c1 - (int)c2;
|
||||
}
|
||||
|
||||
// lookup_sequence(entid, "sequence name", &Float:framerate = 0.0, &bool:loops = false, &Float:groundspeed = 0.0);
|
||||
static cell AMX_NATIVE_CALL lookup_sequence(AMX* amx, cell* params)
|
||||
{
|
||||
int index = params[1];
|
||||
|
||||
CHECK_ENTITY(index);
|
||||
|
||||
edict_t* ent = INDEXENT(index);
|
||||
|
||||
studiohdr_t* pstudiohdr = static_cast<studiohdr_t*>(GET_MODEL_PTR(ent));
|
||||
|
||||
if (pstudiohdr == NULL)
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Could not retrieve the model pointer from the entity provided.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mstudioseqdesc_t* pseqdesc;
|
||||
|
||||
pseqdesc = reinterpret_cast<mstudioseqdesc_t*>(
|
||||
reinterpret_cast<char*>(pstudiohdr) + pstudiohdr->seqindex);
|
||||
|
||||
char* label = MF_GetAmxString(amx, params[2], 0, NULL);
|
||||
|
||||
for (int i = 0; i < pstudiohdr->numseq; i++)
|
||||
{
|
||||
if (UTIL_stricmp( pseqdesc[i].label, label ) == 0)
|
||||
{
|
||||
REAL* FrameRate = reinterpret_cast<REAL*>(MF_GetAmxAddr(amx, params[3]));
|
||||
cell* Loops = MF_GetAmxAddr(amx, params[4]);
|
||||
REAL* GroundSpeed = reinterpret_cast<REAL*>(MF_GetAmxAddr(amx, params[5]));
|
||||
|
||||
// Taken from HLSDK: animation & animating.cpp
|
||||
pseqdesc = &pseqdesc[i];
|
||||
*FrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1);
|
||||
|
||||
*GroundSpeed = sqrt( pseqdesc->linearmovement[0]*pseqdesc->linearmovement[0]+ pseqdesc->linearmovement[1]*pseqdesc->linearmovement[1]+ pseqdesc->linearmovement[2]*pseqdesc->linearmovement[2] );
|
||||
*GroundSpeed = *GroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1);
|
||||
|
||||
*Loops = pseqdesc->flags & STUDIO_LOOPING;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
};
|
||||
// Float:set_controller(entid, controllerid, Float:value);
|
||||
static cell AMX_NATIVE_CALL set_controller(AMX* amx, cell* params)
|
||||
{
|
||||
// From animation.cpp from the HLSDK
|
||||
// SetController( void *pmodel, entvars_t *pev, int iController, float flValue )
|
||||
int entindex = params[1];
|
||||
CHECK_ENTITY(entindex);
|
||||
edict_t* entity = INDEXENT(entindex);
|
||||
|
||||
int iController = params[2];
|
||||
|
||||
if (iController < 0 || iController > 3)
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid controller id passed. Expected 0 through 3, got %d.", iController);
|
||||
return 0;
|
||||
}
|
||||
entvars_t* pev = &entity->v;
|
||||
|
||||
float flValue = amx_ctof(params[3]);
|
||||
|
||||
studiohdr_t* pstudiohdr = static_cast<studiohdr_t*>(GET_MODEL_PTR(entity));
|
||||
|
||||
if (! pstudiohdr)
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Could not find the model pointer for the entity.");
|
||||
return amx_ftoc(flValue);
|
||||
}
|
||||
|
||||
mstudiobonecontroller_t *pbonecontroller = (mstudiobonecontroller_t *)((byte *)pstudiohdr + pstudiohdr->bonecontrollerindex);
|
||||
|
||||
int i = 0;
|
||||
|
||||
// find first controller that matches the index
|
||||
for (i = 0; i < pstudiohdr->numbonecontrollers; i++, pbonecontroller++)
|
||||
{
|
||||
if (pbonecontroller->index == iController)
|
||||
break;
|
||||
}
|
||||
if (i >= pstudiohdr->numbonecontrollers)
|
||||
return amx_ftoc(flValue);
|
||||
|
||||
// wrap 0..360 if it's a rotational controller
|
||||
|
||||
if (pbonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR))
|
||||
{
|
||||
// ugly hack, invert value if end < start
|
||||
if (pbonecontroller->end < pbonecontroller->start)
|
||||
flValue = -flValue;
|
||||
|
||||
// does the controller not wrap?
|
||||
if (pbonecontroller->start + 359.0 >= pbonecontroller->end)
|
||||
{
|
||||
if (flValue > ((pbonecontroller->start + pbonecontroller->end) / 2.0) + 180)
|
||||
flValue = flValue - 360;
|
||||
if (flValue < ((pbonecontroller->start + pbonecontroller->end) / 2.0) - 180)
|
||||
flValue = flValue + 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flValue > 360)
|
||||
flValue = flValue - (int)(flValue / 360.0) * 360.0;
|
||||
else if (flValue < 0)
|
||||
flValue = flValue + (int)((flValue / -360.0) + 1) * 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
int setting = static_cast<int>(255 * (flValue - pbonecontroller->start) / (pbonecontroller->end - pbonecontroller->start));
|
||||
|
||||
if (setting < 0) setting = 0;
|
||||
if (setting > 255) setting = 255;
|
||||
pev->controller[iController] = setting;
|
||||
|
||||
return amx_ftoc(setting * (1.0 / 255.0) * (pbonecontroller->end - pbonecontroller->start) + pbonecontroller->start);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AMX_NATIVE_INFO misc_natives[] = {
|
||||
{ "copy_infokey_buffer", copy_infokey_buffer },
|
||||
{ "lookup_sequence", lookup_sequence },
|
||||
{ "set_controller", set_controller },
|
||||
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
|
|
@ -398,6 +398,45 @@ static cell AMX_NATIVE_CALL amx_set_pev(AMX *amx, cell *params)
|
|||
|
||||
return 0;
|
||||
}
|
||||
static cell AMX_NATIVE_CALL amx_set_pev_string(AMX *amx, cell *params)
|
||||
{
|
||||
// index, pevdata
|
||||
int index = params[1];
|
||||
CHECK_ENTITY(index);
|
||||
edict_t *pEdict = INDEXENT2(index);
|
||||
int iSwitch = params[2];
|
||||
|
||||
//onto normal cases - sanity check
|
||||
if (iSwitch <= pev_string_start || iSwitch >= pev_absolute_end)
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Undefined pev index: %d", iSwitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int offs = g_offset_table[iSwitch];
|
||||
|
||||
//sanity check #2
|
||||
if (offs == -1)
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Undefined pev index: %d", iSwitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
entvars_t *v = &(pEdict->v);
|
||||
|
||||
if ( (iSwitch > pev_string_start && iSwitch < pev_string_end)
|
||||
|| (iSwitch > pev_string2_begin && iSwitch < pev_string2_end) )
|
||||
{
|
||||
*(string_t *)EDICT_OFFS(v, offs) = params[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Non-string field passed to set_pev_string!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL amx_pev_valid(AMX *amx, cell *params)
|
||||
{
|
||||
|
@ -413,10 +452,20 @@ static cell AMX_NATIVE_CALL amx_pev_valid(AMX *amx, cell *params)
|
|||
|
||||
return 1;
|
||||
}
|
||||
static cell AMX_NATIVE_CALL amx_pev_serial(AMX* amx, cell* params)
|
||||
{
|
||||
int id = static_cast<int>(params[1]);
|
||||
|
||||
CHECK_ENTITY(id);
|
||||
edict_t* ent = INDEXENT(id);
|
||||
|
||||
return ent->serialnumber;
|
||||
}
|
||||
AMX_NATIVE_INFO pev_natives[] = {
|
||||
{ "pev", amx_pev },
|
||||
{ "set_pev", amx_set_pev },
|
||||
{ "set_pev_string", amx_set_pev_string },
|
||||
{ "pev_valid", amx_pev_valid },
|
||||
{ "pev_serial", amx_pev_serial },
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
|
|
@ -21,26 +21,72 @@
|
|||
#pragma library fakemeta
|
||||
#endif
|
||||
|
||||
/* Returns entvar data from an entity Use the pev_* enum to specify which form of data you want returned.
|
||||
/**
|
||||
* Returns entvar data from an entity. Use the pev_* enum (in fakemeta_const.inc) to specify which data you want retrieved.
|
||||
*
|
||||
* If retrieving strings, you may optionally get a pointer into the global string table. Depending on
|
||||
* @note This function uses "read_data" style data syntax. It returns integer values,
|
||||
* by-references float data, and sets a buffer for string data.
|
||||
*
|
||||
* @note If retrieving strings, you may optionally get a pointer into the global string table. Depending on
|
||||
* your situation, there are two ways to do this.
|
||||
* 1: This simply gets the pointer.
|
||||
* new ptr = pev(entid, pev_classname)
|
||||
* 2: The pointer will be stored in ptr AND the actual string is retrieved.
|
||||
* new ptr, classname[32]
|
||||
* pev(entid, pev_classname, ptr, classname, 31)
|
||||
*
|
||||
* @param _index The entity index to lookup.
|
||||
* @param _value The pev field to lookup (look in fakemeta_const.inc)
|
||||
*/
|
||||
native pev(_index,_value,any:...);
|
||||
|
||||
/* Sets entvar data for an entity. Use the pev_* enum */
|
||||
/**
|
||||
* Sets entvar data for an entity. Use the pev_* enum from fakemeta_const.inc for reference.
|
||||
*
|
||||
* @note Setting string data will automatically allocate a new string (via AllocString)
|
||||
* If you have a string already allocated with your own call to AllocString, use
|
||||
* set_pev_string_ptr instead.
|
||||
*
|
||||
* @param _index The entity index to set the value on.
|
||||
* @param _value The pev field to set, (look in fakemeta_const.inc)
|
||||
*/
|
||||
native set_pev(_index,_value,any:...);
|
||||
|
||||
/* returns 0 if ent is invalid, >0 if valid
|
||||
* (1 == valid, 2 == valid+pvPrivateData valid)
|
||||
/**
|
||||
* Use this native to set a pev field to a string that is already allocated (via a function such
|
||||
* as EngFunc_AllocString).
|
||||
*
|
||||
* @note If you specify _value as anything other than string fields, an error will be thrown.
|
||||
* @note Pass 0 as the _string field to set it to an empty string.
|
||||
*
|
||||
* @param _index The entity index to set the value on.
|
||||
* @param _value The pev field to set - MUST be a string field.
|
||||
* @param _string The string handle, retrieved from places like AllocString.
|
||||
*/
|
||||
native set_pev_string(_index, _value, _string)
|
||||
|
||||
|
||||
/**
|
||||
* Checks the validity of an entity.
|
||||
*
|
||||
* @param entindex The entity id to check.
|
||||
*
|
||||
* @return 0 on invalid entity
|
||||
* 1 on entity is valid
|
||||
* 2 on entity is valid and it has private data (safe to use pdata natives on).
|
||||
*/
|
||||
native pev_valid(entindex);
|
||||
|
||||
/**
|
||||
* Returns the serial number for each entity. The serial number is a unique identity
|
||||
* generated when an entity is created.
|
||||
*
|
||||
* @param entindex The entity id.
|
||||
*
|
||||
* @return The serial number for the entity.
|
||||
*/
|
||||
native pev_serial(entindex);
|
||||
|
||||
/* Returns any global variable inside globalvars_t structure. Use the glb_* enum.
|
||||
*
|
||||
* When returning data from glb_pStringBase (the global string table), you may give a pointer into that table
|
||||
|
@ -168,3 +214,26 @@ native set_pdata_string(entity, offset, const source[], realloc=2, linux=-5);
|
|||
// Copies the given infoBuffer pointer into out[]
|
||||
// An infoBuffer pointer is returned by EngFunc_GetInfoKeyBuffer
|
||||
native copy_infokey_buffer(infoBuffer, out[], maxlen);
|
||||
|
||||
|
||||
/**
|
||||
* Looks up the sequence for the entity.
|
||||
*
|
||||
* @param entity The entity id to lookup.
|
||||
* @param name The sequence name to lookup, case insensitive. ("JUMP" would match "jump")
|
||||
* @param framerate The framerate of the sequence, if found.
|
||||
* @param loops Whether or not the sequence loops.
|
||||
* @param groundspeed The groundspeed setting of the sequence.
|
||||
* @return -1 on failed lookup, the sequence number on successful lookup.
|
||||
*/
|
||||
native lookup_sequence(entity, const name[], &Float:framerate = 0.0, &bool:loops = false, &Float:groundspeed = 0.0)
|
||||
|
||||
/**
|
||||
* Sets a bone controller with the specified value.
|
||||
*
|
||||
* @param entity The entity id to set the value on.
|
||||
* @param controller Which controller to set (0 through 3).
|
||||
* @param value The value to set it to.
|
||||
* @return The percentage that the controller is extended (0.0 through 1.0)
|
||||
*/
|
||||
native Float:set_controller(entity, controller, Float:value)
|
Loading…
Reference in New Issue
Block a user