amxmodx/amxmodx/CEvent.cpp

586 lines
12 KiB
C++
Raw Normal View History

2014-08-04 12:36:20 +04: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
2004-01-31 23:56:22 +03:00
2004-03-24 04:35:44 +03:00
#include "amxmodx.h"
2004-01-31 23:56:22 +03:00
#include "CEvent.h"
// *****************************************************
// class ClEvent
2004-01-31 23:56:22 +03:00
// *****************************************************
EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
{
m_Plugin = plugin;
m_Func = func;
// flags
2004-03-11 17:22:06 +03:00
m_FlagAlive = true;
m_FlagDead = true;
m_FlagWorld = (flags & 1) ? true : false; // flag a
m_FlagClient = (flags & 2) ? true : false; // flag b
m_FlagOnce = (flags & 4) ? true : false; // flag c
if (flags & 24)
{
m_FlagAlive = (flags & 16) ? true : false; // flag e
m_FlagDead = (flags & 8) ? true : false; // flag d
}
if (m_FlagClient)
{
m_FlagPlayer = true;
m_FlagBot = true;
if (flags & 96)
{
m_FlagPlayer = (flags & 32) ? true : false; // flag f
m_FlagBot = (flags & 64) ? true : false; // flag g
}
}
m_Stamp = 0.0f;
m_Done = false;
2004-03-14 16:57:27 +03:00
m_Conditions = NULL;
}
EventsMngr::ClEvent::~ClEvent()
{
2004-03-14 16:57:27 +03:00
cond_t *tmp1 = m_Conditions;
cond_t *tmp2 = NULL;
2004-03-14 16:57:27 +03:00
while (tmp1)
{
tmp2 = tmp1->next;
delete tmp1;
tmp1 = tmp2;
}
2004-03-14 16:57:27 +03:00
m_Conditions = NULL;
}
void EventsMngr::NextParam()
{
const int INITIAL_PARSEVAULT_SIZE = 32;
if (m_ParsePos < m_ParseVaultSize)
return;
2004-03-14 16:57:27 +03:00
MsgDataEntry *tmp = NULL;
int tmpSize = 0;
2004-03-14 16:57:27 +03:00
if (m_ParseVault)
{
// copy to tmp
tmp = new MsgDataEntry[m_ParseVaultSize];
if (!tmp)
{
return; // :TODO: Error report !!
}
2004-03-14 16:57:27 +03:00
memcpy(tmp, m_ParseVault, m_ParseVaultSize * sizeof(MsgDataEntry));
tmpSize = m_ParseVaultSize;
delete [] m_ParseVault;
m_ParseVault = NULL;
}
if (m_ParseVaultSize > 0)
m_ParseVaultSize *= 2;
else
m_ParseVaultSize = INITIAL_PARSEVAULT_SIZE;
m_ParseVault = new MsgDataEntry[m_ParseVaultSize];
2004-03-14 16:57:27 +03:00
if (tmp)
{
memcpy(m_ParseVault, tmp, tmpSize * sizeof(MsgDataEntry));
delete [] tmp;
tmp = NULL;
}
}
int EventsMngr::ClEvent::getFunction()
{
return m_Func;
}
EventsMngr::EventsMngr()
{
2004-03-14 16:57:27 +03:00
m_ParseVault = NULL;
m_ParseVaultSize = 0;
m_ParseMsgType = -1;
m_ReadVault = NULL;
m_ReadVaultSize = 0;
m_ReadPos = -1;
m_ReadMsgType = -1;
clearEvents();
2004-01-31 23:56:22 +03:00
}
2004-01-31 23:56:22 +03:00
EventsMngr::~EventsMngr()
{
2004-01-31 23:56:22 +03:00
clearEvents();
}
CPluginMngr::CPlugin * EventsMngr::ClEvent::getPlugin()
{
return m_Plugin;
2004-01-31 23:56:22 +03:00
}
// *****************************************************
// class EventsMngr
// *****************************************************
void EventsMngr::ClEvent::registerFilter(char *filter)
2004-01-31 23:56:22 +03:00
{
// filters (conditions) have the form x&y
// x is the param number
// & may also be other characters
// y is a string or a number
if (!filter)
return;
2004-01-31 23:56:22 +03:00
char* value = filter;
// get the first numbr
while (isdigit(*value))
2004-01-31 23:56:22 +03:00
++value;
// end of string => ignore
if (!*value)
return;
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
cond_t *tmpCond = new cond_t;
if (!tmpCond)
return;
2004-01-31 23:56:22 +03:00
// type character
2004-03-14 16:57:27 +03:00
tmpCond->type = *value;
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
// set a null here so param id can be recognized, and save it
2004-01-31 23:56:22 +03:00
*value++ = 0;
2004-03-14 16:57:27 +03:00
tmpCond->paramId = atoi(filter);
2004-01-31 23:56:22 +03:00
// rest of line
2004-08-13 12:46:04 +04:00
tmpCond->sValue.assign(value);
tmpCond->fValue = static_cast<float>(atof(value));
2004-03-14 16:57:27 +03:00
tmpCond->iValue = atoi(value);
tmpCond->next = NULL;
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
if (m_Conditions)
{
cond_t *tmp = m_Conditions;
2004-03-14 16:57:27 +03:00
while (tmp->next)
tmp = tmp->next;
2004-03-14 16:57:27 +03:00
tmp->next = tmpCond;
}
else
m_Conditions = tmpCond;
2004-01-31 23:56:22 +03:00
}
EventsMngr::ClEvent* EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid)
2004-01-31 23:56:22 +03:00
{
// validate parameter
if (msgid < 0 || msgid >= MAX_AMX_REG_MSG)
return NULL;
2004-01-31 23:56:22 +03:00
ClEvent *event = new ClEvent(plugin, func, flags);
if (!event)
return NULL;
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
m_Events[msgid].put(event);
2004-01-31 23:56:22 +03:00
return event;
}
void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index)
2004-01-31 23:56:22 +03:00
{
if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG)
return;
m_ParseNotDone = false;
// don't parse if nothing to do
2004-03-14 16:57:27 +03:00
if (!m_Events[msg_type].size())
return;
m_ParseMsgType = msg_type;
m_Timer = timer;
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
{
2004-03-14 16:57:27 +03:00
if ((*iter).m_Done)
continue;
2004-03-14 16:57:27 +03:00
if (!(*iter).m_Plugin->isExecutable((*iter).m_Func))
{
2004-03-14 16:57:27 +03:00
(*iter).m_Done = true;
continue;
}
if (pPlayer)
{
if (!(*iter).m_FlagClient || (pPlayer->IsBot() ? !(*iter).m_FlagBot : !(*iter).m_FlagPlayer) || (pPlayer->IsAlive() ? !(*iter).m_FlagAlive : !(*iter).m_FlagDead))
{
2004-03-14 16:57:27 +03:00
(*iter).m_Done = true;
continue;
}
}
2004-03-14 16:57:27 +03:00
else if (!(*iter).m_FlagWorld)
{
2004-03-14 16:57:27 +03:00
(*iter).m_Done = true;
continue;
}
2004-03-14 16:57:27 +03:00
if ((*iter).m_FlagOnce && (*iter).m_Stamp == (float)(*timer))
{
2004-03-14 16:57:27 +03:00
(*iter).m_Done = true;
continue;
}
m_ParseNotDone = true;
}
if (m_ParseNotDone)
{
m_ParsePos = 0;
2004-03-14 16:57:27 +03:00
NextParam();
2004-03-17 21:57:36 +03:00
m_ParseVault[0].type = MSG_INTEGER;
m_ParseVault[0].iValue = index;
2004-03-11 16:48:57 +03:00
}
2004-03-14 16:57:27 +03:00
m_ParseFun = &m_Events[msg_type];
2004-01-31 23:56:22 +03:00
}
void EventsMngr::parseValue(int iValue)
2004-01-31 23:56:22 +03:00
{
// not parsing
if (!m_ParseNotDone || !m_ParseFun)
return;
// grow if needed
2004-03-14 16:57:27 +03:00
++m_ParsePos;
NextParam();
m_ParseVault[m_ParsePos].type = MSG_INTEGER;
m_ParseVault[m_ParsePos].iValue = iValue;
2004-03-14 16:57:27 +03:00
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{
2004-03-14 16:57:27 +03:00
if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing
2004-03-14 16:57:27 +03:00
// loop through conditions
2004-03-17 21:57:36 +03:00
bool execute = false;
bool anyConditions = false;
2004-03-14 16:57:27 +03:00
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{
2004-03-14 16:57:27 +03:00
if (condIter->paramId == m_ParsePos)
{
2004-03-17 21:57:36 +03:00
anyConditions = true;
2005-09-11 00:09:14 +04:00
switch (condIter->type)
2004-03-14 16:57:27 +03:00
{
case '=': if (condIter->iValue == iValue) execute = true; break;
case '!': if (condIter->iValue != iValue) execute = true; break;
case '&': if (iValue & condIter->iValue) execute = true; break;
case '<': if (iValue < condIter->iValue) execute = true; break;
case '>': if (iValue > condIter->iValue) execute = true; break;
2004-03-14 16:57:27 +03:00
}
if (execute)
2004-03-17 21:57:36 +03:00
break;
2004-03-14 16:57:27 +03:00
}
}
2005-09-17 03:48:51 +04:00
2004-03-17 21:57:36 +03:00
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
2004-01-31 23:56:22 +03:00
}
}
void EventsMngr::parseValue(float fValue)
2004-01-31 23:56:22 +03:00
{
// not parsing
if (!m_ParseNotDone || !m_ParseFun)
return;
// grow if needed
2004-03-14 16:57:27 +03:00
++m_ParsePos;
NextParam();
m_ParseVault[m_ParsePos].type = MSG_FLOAT;
m_ParseVault[m_ParsePos].fValue = fValue;
2004-03-14 16:57:27 +03:00
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{
2004-03-14 16:57:27 +03:00
if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing
2004-03-14 16:57:27 +03:00
// loop through conditions
2004-03-17 21:57:36 +03:00
bool execute = false;
bool anyConditions = false;
2004-03-14 16:57:27 +03:00
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{
2004-03-14 16:57:27 +03:00
if (condIter->paramId == m_ParsePos)
{
2004-03-17 21:57:36 +03:00
anyConditions = true;
2005-09-11 00:09:14 +04:00
switch (condIter->type)
2004-03-14 16:57:27 +03:00
{
case '=': if (condIter->fValue == fValue) execute = true; break;
case '!': if (condIter->fValue != fValue) execute = true; break;
case '<': if (fValue < condIter->fValue) execute = true; break;
case '>': if (fValue > condIter->fValue) execute = true; break;
2004-03-14 16:57:27 +03:00
}
2005-09-17 03:48:51 +04:00
2004-03-14 16:57:27 +03:00
if (execute)
2004-03-17 21:57:36 +03:00
break;
2004-03-14 16:57:27 +03:00
}
}
2005-09-17 03:48:51 +04:00
2004-03-17 21:57:36 +03:00
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
2004-01-31 23:56:22 +03:00
}
}
void EventsMngr::parseValue(const char *sz)
{
// not parsing
if (!m_ParseNotDone || !m_ParseFun)
return;
// grow if needed
2004-03-14 16:57:27 +03:00
++m_ParsePos;
NextParam();
m_ParseVault[m_ParsePos].type = MSG_STRING;
m_ParseVault[m_ParsePos].sValue = sz;
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
// loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{
2004-03-14 16:57:27 +03:00
if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing
2004-01-31 23:56:22 +03:00
2004-03-14 16:57:27 +03:00
// loop through conditions
2004-03-17 21:57:36 +03:00
bool execute = false;
bool anyConditions = false;
2004-03-14 16:57:27 +03:00
for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{
2004-03-14 16:57:27 +03:00
if (condIter->paramId == m_ParsePos)
{
2004-03-17 21:57:36 +03:00
anyConditions = true;
2005-09-11 00:09:14 +04:00
switch (condIter->type)
2004-03-14 16:57:27 +03:00
{
case '=': if (!strcmp(sz, condIter->sValue.c_str())) execute = true; break;
case '!': if (strcmp(sz, condIter->sValue.c_str())) execute = true; break;
case '&': if (strstr(sz, condIter->sValue.c_str())) execute = true; break;
2004-03-14 16:57:27 +03:00
}
2005-09-17 03:48:51 +04:00
2004-03-14 16:57:27 +03:00
if (execute)
2004-03-17 21:57:36 +03:00
break;
2004-03-14 16:57:27 +03:00
}
}
2005-09-17 03:48:51 +04:00
2004-03-17 21:57:36 +03:00
if (anyConditions && !execute)
(*iter).m_Done = true; // don't execute
}
}
void EventsMngr::executeEvents()
{
static unsigned int reentrant = 0;
if (!m_ParseFun)
{
return;
}
// Store old read data, which are either default values or previous event data
int oldMsgType = m_ReadMsgType, oldReadPos = m_ReadPos;
MsgDataEntry *oldReadVault = m_ReadVault, *readVault = NULL;
// We have a re-entrant call
if (reentrant++)
{
// Create temporary read vault
readVault = new MsgDataEntry[m_ParsePos + 1];
m_ReadVault = readVault;
} else if (m_ReadVaultSize != m_ParseVaultSize) {
// Extend read vault size if necessary
delete [] m_ReadVault;
m_ReadVault = new MsgDataEntry[m_ParseVaultSize];
m_ReadVaultSize = m_ParseVaultSize;
// Update old read vault so we don't restore to a wrong pointer
oldReadVault = m_ReadVault;
}
// Copy data over to readvault
m_ReadPos = m_ParsePos;
m_ReadMsgType = m_ParseMsgType;
if (m_ParseVault)
{
memcpy(m_ReadVault, m_ParseVault, (m_ParsePos + 1) * sizeof(MsgDataEntry));
}
// Reset this here so we don't trigger re-entrancy for unregistered messages
ClEventVec *parseFun = m_ParseFun;
m_ParseFun = NULL;
for (ClEventVecIter iter = parseFun->begin(); iter; ++iter)
2004-01-31 23:56:22 +03:00
{
if ((*iter).m_Done)
2004-01-31 23:56:22 +03:00
{
(*iter).m_Done = false;
continue;
2004-01-31 23:56:22 +03:00
}
(*iter).m_Stamp = (float)*m_Timer;
executeForwards((*iter).m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
2004-01-31 23:56:22 +03:00
}
// Restore old read data, either resetting to default or to previous event data
m_ReadMsgType = oldMsgType;
m_ReadPos = oldReadPos;
m_ReadVault = oldReadVault;
delete [] readVault;
2004-03-11 15:35:13 +03:00
--reentrant;
2004-01-31 23:56:22 +03:00
}
2004-03-31 22:05:07 +04:00
int EventsMngr::getArgNum() const
{
return m_ReadPos + 1;
2004-01-31 23:56:22 +03:00
}
2004-03-31 22:05:07 +04:00
const char* EventsMngr::getArgString(int a) const
{
if (a < 0 || a > m_ReadPos)
return "";
2004-01-31 23:56:22 +03:00
static char var[32];
switch (m_ReadVault[a].type)
{
case MSG_INTEGER:
sprintf(var, "%d", m_ReadVault[a].iValue);
return var;
case MSG_STRING:
return m_ReadVault[a].sValue;
default:
sprintf(var, "%g", m_ReadVault[a].fValue);
return var;
}
2004-01-31 23:56:22 +03:00
}
2004-03-31 22:05:07 +04:00
int EventsMngr::getArgInteger(int a) const
2004-01-31 23:56:22 +03:00
{
if (a < 0 || a > m_ReadPos)
return 0;
switch (m_ReadVault[a].type)
{
case MSG_INTEGER:
return m_ReadVault[a].iValue;
case MSG_STRING:
return atoi(m_ReadVault[a].sValue);
default:
return (int)m_ReadVault[a].fValue;
2004-01-31 23:56:22 +03:00
}
}
2004-03-31 22:05:07 +04:00
float EventsMngr::getArgFloat(int a) const
{
if (a < 0 || a > m_ReadPos)
return 0.0f;
switch (m_ReadVault[a].type)
{
case MSG_INTEGER:
return static_cast<float>(m_ReadVault[a].iValue);
case MSG_STRING:
return static_cast<float>(atof(m_ReadVault[a].sValue));
default:
return m_ReadVault[a].fValue;
2004-01-31 23:56:22 +03:00
}
}
void EventsMngr::clearEvents(void)
{
for (int i = 0; i < MAX_AMX_REG_MSG; ++i)
{
m_Events[i].clear();
2004-01-31 23:56:22 +03:00
}
2004-03-17 21:57:36 +03:00
// delete parsevault
if (m_ParseVault)
{
delete [] m_ParseVault;
m_ParseVault = NULL;
m_ParseVaultSize = 0;
}
if (m_ReadVault)
{
delete [] m_ReadVault;
m_ReadVault = NULL;
m_ReadVaultSize = 0;
m_ReadPos = -1;
}
2004-01-31 23:56:22 +03:00
}
int EventsMngr::getEventId(const char* msg)
{
// :TODO: Remove this somehow!!! :)
const struct CS_Events
{
2004-01-31 23:56:22 +03:00
const char* name;
CS_EventsIds id;
} table[] =
{
{"CS_DeathMsg", CS_DeathMsg},
// {"CS_RoundEnd", CS_RoundEnd},
// {"CS_RoundStart", CS_RoundStart},
// {"CS_Restart", CS_Restart},
{"", CS_Null}
2004-01-31 23:56:22 +03:00
};
// if msg is a number, return it
int pos = atoi(msg);
if (pos != 0)
2004-01-31 23:56:22 +03:00
return pos;
// try to find in table first
for (pos = 0; table[pos].id != CS_Null; ++pos)
if (!strcmp(table[pos].name, msg))
return table[pos].id;
// find the id of the message
return pos = GET_USER_MSG_ID(PLID, msg, 0);
2004-01-31 23:56:22 +03:00
}
2004-04-03 23:15:43 +04:00
int EventsMngr::getCurrentMsgType()
{
return m_ReadMsgType;
2004-04-03 23:15:43 +04:00
}