2014-08-04 10:21:40 +00:00
|
|
|
// vim: set ts=4 sw=4 tw=99 noet:
|
|
|
|
//
|
|
|
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
|
|
|
// Copyright (C) The AMX Mod X Development Team.
|
|
|
|
//
|
|
|
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
|
|
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
|
|
|
// https://alliedmods.net/amxmodx-license
|
|
|
|
|
|
|
|
//
|
|
|
|
// Ham Sandwich Module
|
|
|
|
//
|
|
|
|
|
2014-04-09 14:35:46 +00:00
|
|
|
#ifndef RETURNHANDLER_H
|
|
|
|
#define RETURNHANDLER_H
|
|
|
|
|
|
|
|
#include "ham_utils.h"
|
2015-09-30 17:08:39 +00:00
|
|
|
#include <amtl/am-vector.h>
|
|
|
|
#include <amtl/am-string.h>
|
2014-08-10 09:48:06 +00:00
|
|
|
#include <sh_stack.h>
|
2014-04-09 14:35:46 +00:00
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
RET_VOID,
|
2015-03-10 15:51:45 +00:00
|
|
|
RET_BOOL,
|
2014-04-09 14:35:46 +00:00
|
|
|
RET_INTEGER,
|
2015-03-10 15:51:45 +00:00
|
|
|
RET_SHORT,
|
2014-04-09 14:35:46 +00:00
|
|
|
RET_FLOAT,
|
|
|
|
RET_VECTOR,
|
|
|
|
RET_STRING,
|
|
|
|
RET_CBASE,
|
|
|
|
RET_ENTVAR,
|
2015-03-10 15:51:45 +00:00
|
|
|
RET_EDICT,
|
2014-04-09 14:35:46 +00:00
|
|
|
RET_TRACE,
|
|
|
|
RET_ITEMINFO
|
|
|
|
};
|
|
|
|
|
2015-03-10 15:51:45 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int iSlot;
|
|
|
|
int iPosition;
|
|
|
|
const char *pszAmmo1;
|
|
|
|
int iMaxAmmo1;
|
|
|
|
const char *pszAmmo2;
|
|
|
|
int iMaxAmmo2;
|
|
|
|
const char *pszName;
|
|
|
|
int iMaxClip;
|
|
|
|
int iId;
|
|
|
|
int iFlags;
|
|
|
|
int iWeight;
|
|
|
|
}
|
2014-04-09 14:35:46 +00:00
|
|
|
ItemInfo;
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
2015-03-10 15:51:45 +00:00
|
|
|
ItemInfo_iSlot,
|
|
|
|
ItemInfo_iPosition,
|
|
|
|
ItemInfo_pszAmmo1,
|
|
|
|
ItemInfo_iMaxAmmo1,
|
|
|
|
ItemInfo_pszAmmo2,
|
|
|
|
ItemInfo_iMaxAmmo2,
|
|
|
|
ItemInfo_pszName,
|
|
|
|
ItemInfo_iMaxClip,
|
|
|
|
ItemInfo_iId,
|
|
|
|
ItemInfo_iFlags,
|
2014-04-09 14:35:46 +00:00
|
|
|
ItemInfo_iWeight
|
|
|
|
};
|
|
|
|
|
|
|
|
// Container for return and parameter data.
|
|
|
|
// Contains a void pointer, and a flag telling what it contains.
|
|
|
|
class Data
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
void *m_data;
|
|
|
|
int *m_index;
|
|
|
|
int m_type;
|
|
|
|
|
|
|
|
bool IsSet(void)
|
|
|
|
{
|
|
|
|
return (m_type != RET_VOID &&
|
|
|
|
m_data != NULL);
|
|
|
|
};
|
|
|
|
bool IsType(const int type)
|
|
|
|
{
|
|
|
|
return (m_type == type);
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
Data() : m_data(NULL), m_index(NULL), m_type(RET_VOID)
|
|
|
|
{ /* nothing */ };
|
|
|
|
|
|
|
|
Data(int type, void *ptr) : m_data(ptr), m_index(NULL), m_type(type)
|
|
|
|
{ /* nothing */ };
|
|
|
|
|
|
|
|
Data(int type, void *ptr, int *cptr) : m_data(ptr), m_index(NULL), m_type(type)
|
|
|
|
{ /* nothing */ };
|
|
|
|
|
|
|
|
~Data()
|
|
|
|
{ /* nothing */ };
|
|
|
|
|
|
|
|
int GetType()
|
|
|
|
{
|
|
|
|
return m_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
// All Get/Set value natives return < 0 on failure.
|
|
|
|
// -1: Wrong type
|
|
|
|
// -2: Bad data pointer (void, etc).
|
|
|
|
int SetInt(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (IsType(RET_INTEGER))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<int *>(m_data))=*data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_BOOL))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<bool *>(m_data)) = *data > 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_SHORT))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<short *>(m_data)) = *data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_ITEMINFO))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<int *>(m_data)) = *data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_TRACE))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<int *>(m_data))=*data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
int SetFloat(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_FLOAT))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*(reinterpret_cast<REAL *>(m_data))=amx_ctof2(*data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
int SetVector(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_VECTOR))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
Vector *vec=reinterpret_cast<Vector *>(m_data);
|
|
|
|
|
|
|
|
vec->x=amx_ctof2(data[0]);
|
|
|
|
vec->y=amx_ctof2(data[1]);
|
|
|
|
vec->z=amx_ctof2(data[2]);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
int SetString(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_STRING))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-08-10 09:48:06 +00:00
|
|
|
ke::AString *str=reinterpret_cast<ke::AString *>(m_data);
|
2014-04-09 14:35:46 +00:00
|
|
|
|
|
|
|
cell *i=data;
|
|
|
|
size_t len=0;
|
|
|
|
|
|
|
|
while (*i!=0)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
len++;
|
|
|
|
};
|
|
|
|
char *temp=new char[len+1];
|
|
|
|
i=data;
|
|
|
|
char *j=temp;
|
|
|
|
|
|
|
|
while ((*j++=*i++)!=0)
|
|
|
|
{
|
|
|
|
/* nothing */
|
|
|
|
}
|
|
|
|
|
2014-08-10 09:48:06 +00:00
|
|
|
*str = temp;
|
2014-04-09 14:35:46 +00:00
|
|
|
|
|
|
|
delete[] temp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
int SetEntity(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (IsType(RET_CBASE))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<void **>(m_data))=IndexToPrivate(*data);
|
|
|
|
if (m_index != 0)
|
|
|
|
{
|
|
|
|
*m_index=*data;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_ENTVAR))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<entvars_t **>(m_data))=IndexToEntvar(*data);
|
|
|
|
if (m_index != 0)
|
|
|
|
{
|
|
|
|
*m_index=*data;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_EDICT))
|
|
|
|
{
|
|
|
|
*(reinterpret_cast<edict_t **>(m_data)) = IndexToEdict(*data);
|
|
|
|
if (m_index != 0)
|
|
|
|
{
|
|
|
|
*m_index = *data;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
int GetInt(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (IsType(RET_INTEGER))
|
|
|
|
{
|
|
|
|
*data=*(reinterpret_cast<int *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_BOOL))
|
|
|
|
{
|
|
|
|
*data = *(reinterpret_cast<bool *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (IsType(RET_SHORT))
|
|
|
|
{
|
|
|
|
*data = *(reinterpret_cast<short *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_ITEMINFO))
|
|
|
|
{
|
|
|
|
*data = *(reinterpret_cast<int *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_TRACE))
|
|
|
|
{
|
|
|
|
*data=*(reinterpret_cast<int *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
int GetFloat(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_FLOAT))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*data=amx_ftoc2(*(reinterpret_cast<REAL *>(m_data)));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
int GetVector(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_VECTOR))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
Vector *vec=reinterpret_cast<Vector *>(m_data);
|
|
|
|
data[0]=amx_ftoc2(vec->x);
|
|
|
|
data[1]=amx_ftoc2(vec->y);
|
|
|
|
data[2]=amx_ftoc2(vec->z);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
int GetString(cell *data, int len)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (!IsType(RET_STRING))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2014-08-10 09:48:06 +00:00
|
|
|
const char *i=(reinterpret_cast<ke::AString *>(m_data)->chars());
|
2014-04-09 14:35:46 +00:00
|
|
|
|
|
|
|
while (len-- &&
|
|
|
|
(*data++=*i++)!='\0')
|
|
|
|
{
|
|
|
|
/* nothing */
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
int GetEntity(cell *data)
|
|
|
|
{
|
|
|
|
if (!IsSet())
|
|
|
|
{
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (IsType(RET_CBASE))
|
|
|
|
{
|
|
|
|
*data=PrivateToIndex(m_data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_ENTVAR))
|
|
|
|
{
|
|
|
|
*data=EntvarToIndex(reinterpret_cast<entvars_t *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (IsType(RET_EDICT))
|
|
|
|
{
|
|
|
|
*data = EdictToIndex(reinterpret_cast<edict_t *>(m_data));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
extern CStack< Data * > ReturnStack;
|
|
|
|
extern CStack< Data * > OrigReturnStack;
|
2014-08-10 09:48:06 +00:00
|
|
|
extern CStack< ke::Vector< Data * > * > ParamStack;
|
2014-04-09 14:35:46 +00:00
|
|
|
extern CStack< int * > ReturnStatus;
|
|
|
|
#endif
|