amxmodx/dlls/fakemeta/glb.cpp
2006-03-14 16:55:06 +00:00

166 lines
3.7 KiB
C++

#include "fakemeta_amxx.h"
static int g_glob_offset_table[glb_end_pchar] = {-1};
#define DO_OFFSET_GLB(offset) g_glob_offset_table[offset] = offsetof(globalvars_t, offset)
void initialize_glb_offsets()
{
DO_OFFSET_GLB(trace_hitgroup);
DO_OFFSET_GLB(trace_flags);
DO_OFFSET_GLB(msg_entity);
DO_OFFSET_GLB(cdAudioTrack);
DO_OFFSET_GLB(maxClients);
DO_OFFSET_GLB(maxEntities);
DO_OFFSET_GLB(time);
DO_OFFSET_GLB(frametime);
DO_OFFSET_GLB(force_retouch);
DO_OFFSET_GLB(deathmatch);
DO_OFFSET_GLB(coop);
DO_OFFSET_GLB(teamplay);
DO_OFFSET_GLB(serverflags);
DO_OFFSET_GLB(found_secrets);
DO_OFFSET_GLB(trace_allsolid);
DO_OFFSET_GLB(trace_startsolid);
DO_OFFSET_GLB(trace_fraction);
DO_OFFSET_GLB(trace_plane_dist);
DO_OFFSET_GLB(trace_inopen);
DO_OFFSET_GLB(trace_inwater);
DO_OFFSET_GLB(trace_ent);
DO_OFFSET_GLB(v_forward);
DO_OFFSET_GLB(v_up);
DO_OFFSET_GLB(v_right);
DO_OFFSET_GLB(trace_endpos);
DO_OFFSET_GLB(trace_plane_normal);
DO_OFFSET_GLB(vecLandmarkOffset);
DO_OFFSET_GLB(mapname);
DO_OFFSET_GLB(startspot);
DO_OFFSET_GLB(pStringBase);
}
#define GET_OFFS(v,o) ((char *)v + o)
static cell AMX_NATIVE_CALL amx_glb(AMX *amx, cell *params)
{
int iSwitch = params[1];
if (iSwitch <= glb_start_int || iSwitch >= glb_end_pchar)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Undefined global index: %d", iSwitch);
return 0;
}
int offset = g_glob_offset_table[iSwitch];
if (offset == -1)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Undefined global index: %d", iSwitch);
return 0;
}
enum
{
Ret_Int = (1<<0),
Ret_Float = (1<<1),
Ret_Vec = (1<<2),
Ret_Edict = (1<<3),
Ret_PChar = (1<<4)
};
union
{
int i;
float f;
const char *c;
} rets;
Vector vec;
int Valtype = 0;
if (iSwitch > glb_start_int && iSwitch < glb_end_int)
{
rets.i = *(int *)GET_OFFS(gpGlobals, offset);
Valtype = Ret_Int;
}
else if (iSwitch > glb_start_float && iSwitch < glb_end_float)
{
rets.f = *(float *)GET_OFFS(gpGlobals, offset);
Valtype = Ret_Float;
}
else if (iSwitch > glb_start_edict && iSwitch < glb_end_edict)
{
edict_t *e = *(edict_t **)GET_OFFS(gpGlobals, offset);
rets.i = ENTINDEX(e);
Valtype = Ret_Int | Ret_Edict;
}
else if (iSwitch > glb_start_vector && iSwitch < glb_end_vector)
{
vec = *(vec3_t *)GET_OFFS(gpGlobals, offset);
Valtype = Ret_Vec;
}
else if (iSwitch > glb_start_string && iSwitch < glb_end_string)
{
rets.c = STRING(*(string_t *)GET_OFFS(gpGlobals, offset));
Valtype = Ret_PChar;
}
else if (iSwitch > glb_start_pchar && iSwitch < glb_end_pchar)
{
rets.c = *(const char **)GET_OFFS(gpGlobals, offset);
Valtype = Ret_PChar;
}
size_t paramnum = params[0] / sizeof(cell) - 1;
if (paramnum == 0)
{
//return an int
if (Valtype & Ret_Int)
{
return rets.i;
} else {
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid return type");
return 0;
}
}
else if (paramnum == 1)
{
//return a byref float - usually
cell *addr = MF_GetAmxAddr(amx, params[2]);
if (Valtype == Ret_Float)
{
*addr = amx_ftoc(rets.f);
}
else if (Valtype == Ret_Vec)
{
addr[0] = amx_ftoc(vec.x);
addr[1] = amx_ftoc(vec.y);
addr[2] = amx_ftoc(vec.z);
} else {
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid return type");
return 0;
}
return 1;
}
else if (paramnum == 2)
{
cell size = *(MF_GetAmxAddr(amx, params[3]));
if (Valtype == Ret_PChar)
{
const char *str = rets.c;
if (!str)
str = "";
return MF_SetAmxString(amx, params[2], str, size);
}
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid return type");
}
//if we got here, something happened
MF_LogError(amx, AMX_ERR_NATIVE, "Unknown global index or return combination %d", iSwitch);
return 0;
}
AMX_NATIVE_INFO glb_natives[] =
{
{"global_get", amx_glb},
{NULL, NULL},
};