2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// listener.cpp : Listener.
|
|
|
|
|
2023-06-17 01:24:20 +02:00
|
|
|
#include "../script/scriptvariable.h"
|
|
|
|
#include "../script/scriptexception.h"
|
2023-02-01 19:29:13 +01:00
|
|
|
#include "Linklist.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2023-06-17 01:24:20 +02:00
|
|
|
#include "../fgame/archive.h"
|
|
|
|
#include "../fgame/scriptmaster.h"
|
|
|
|
#include "../fgame/scriptthread.h"
|
|
|
|
#include "../script/scriptclass.h"
|
2016-03-27 11:49:47 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined( GAME_DLL )
|
2023-05-01 15:15:01 +02:00
|
|
|
|
2023-06-15 23:44:02 +02:00
|
|
|
#include "../fgame/player.h"
|
|
|
|
#include "../fgame/consoleevent.h"
|
2023-08-11 21:48:25 +02:00
|
|
|
#include "../fgame/animationevent.h"
|
2023-05-01 15:15:01 +02:00
|
|
|
|
|
|
|
#define LISTENER_Cvar_Get gi.Cvar_Get
|
|
|
|
|
|
|
|
#elif defined(CGAME_DLL)
|
|
|
|
|
|
|
|
#define LISTENER_Cvar_Get cgi.Cvar_Get
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
#elif defined ( UI_LIB )
|
|
|
|
#else
|
2023-05-01 15:15:01 +02:00
|
|
|
|
|
|
|
#define LISTENER_Cvar_Get Cvar_Get
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
#include "../client/client.h"
|
|
|
|
#endif
|
|
|
|
|
2023-08-01 19:30:28 +02:00
|
|
|
// std::move
|
|
|
|
#include <utility>
|
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
DataNode* Event::DataNodeList = NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
con_map< Event *, EventDef > Event::eventDefList;
|
|
|
|
con_arrayset< command_t, command_t > Event::commandList;
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
con_map< const_str, unsigned int > Event::normalCommandList;
|
|
|
|
con_map< const_str, unsigned int > Event::returnCommandList;
|
|
|
|
con_map< const_str, unsigned int > Event::getterCommandList;
|
|
|
|
con_map< const_str, unsigned int > Event::setterCommandList;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
EventQueueNode Event::EventQueue;
|
|
|
|
|
|
|
|
int DisableListenerNotify = 0;
|
|
|
|
|
|
|
|
bool Listener::EventSystemStarted = 0;
|
|
|
|
|
|
|
|
int Event::totalevents = 1;
|
|
|
|
|
|
|
|
Event EV_Listener_CancelFor
|
|
|
|
(
|
|
|
|
"cancelFor",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Cancel for event of type name.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_CommandDelay
|
|
|
|
(
|
|
|
|
"commanddelay",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fsSSSSSS",
|
|
|
|
"delay command arg1 arg2 arg3 arg4 arg5 arg6",
|
|
|
|
"executes a command after the given delay.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_Classname
|
|
|
|
(
|
|
|
|
"classname",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"classname variable",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_SetClassname
|
|
|
|
(
|
|
|
|
"classname",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"classname",
|
|
|
|
"classname variable",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_CreateReturnThread
|
|
|
|
(
|
|
|
|
"thread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Creates a thread starting at label.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_CreateThread
|
|
|
|
(
|
|
|
|
"thread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Creates a thread starting at label.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_ExecuteReturnScript
|
|
|
|
(
|
|
|
|
"exec",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"script",
|
|
|
|
"Executes the specified script.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_ExecuteScript
|
|
|
|
(
|
|
|
|
"exec",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"script",
|
|
|
|
"Executes the specified script.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Delete
|
|
|
|
(
|
|
|
|
"delete",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Removes this listener immediately.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Remove
|
|
|
|
(
|
2023-08-17 03:03:08 +02:00
|
|
|
"immediateremove",
|
2016-03-27 11:49:47 +02:00
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Removes this listener immediately.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_ScriptRemove
|
|
|
|
(
|
|
|
|
"remove",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Removes this listener the next time events are processed.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_EndOn
|
|
|
|
(
|
|
|
|
"endon",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Ends the function when the specified event is triggered.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_InheritsFrom
|
|
|
|
(
|
|
|
|
"inheritsfrom",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"class",
|
|
|
|
"Returns 1 if the class inherits from the specified class. 0 otherwise.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_IsInheritedBy
|
|
|
|
(
|
|
|
|
"isinheritedby",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"class",
|
|
|
|
"Returns 1 if the class is inherited by the specified class. 0 otherwise.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_Notify
|
|
|
|
(
|
|
|
|
"notify",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Triggers an event. An undefined event will be automatically created by calling waittill or endon.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_GetOwner
|
|
|
|
(
|
|
|
|
"owner",
|
|
|
|
EV_DEFAULT,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
"Returns the owner.",
|
|
|
|
EV_GETTER
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_DelayThrow
|
|
|
|
(
|
|
|
|
"delaythrow",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Internal usage.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Throw
|
|
|
|
(
|
|
|
|
"throw",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Throws to the specified label.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_Unregister
|
|
|
|
(
|
|
|
|
"unregister",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Unregisters the label from the event of the same name.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitCreateReturnThread
|
|
|
|
(
|
|
|
|
"waitthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Creates a thread starting at label and waits until the called thread is finished.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitCreateThread
|
|
|
|
(
|
|
|
|
"waitthread",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"label",
|
|
|
|
"Creates a thread starting at label and waits until the called thread is finished.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitExecuteReturnScript
|
|
|
|
(
|
|
|
|
"waitexec",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"script",
|
|
|
|
"Executes the specified script and waits until the called thread group is finished.",
|
|
|
|
EV_RETURN
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitExecuteScript
|
|
|
|
(
|
|
|
|
"waitexec",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"script",
|
|
|
|
"Executes the specified script and waits until the called thread group is finished.",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitTill
|
|
|
|
(
|
|
|
|
"waitTill",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"s",
|
|
|
|
"name",
|
|
|
|
"Wait until event of type name",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitTillTimeout
|
|
|
|
(
|
|
|
|
"waittill_timeout",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fs",
|
|
|
|
"timeout_time name",
|
|
|
|
"Wait until event of type name with a timeout time",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitTillAny
|
|
|
|
(
|
|
|
|
"waittill_any",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"sS",
|
|
|
|
"name1 ...",
|
|
|
|
"Wait until any event of type name",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
|
|
|
Event EV_Listener_WaitTillAnyTimeout
|
|
|
|
(
|
|
|
|
"waittill_any_timeout",
|
|
|
|
EV_DEFAULT,
|
|
|
|
"fsS",
|
|
|
|
"timeout_time name1 ...",
|
|
|
|
"Wait until any event of type name with a timeout time",
|
|
|
|
EV_NORMAL
|
|
|
|
);
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
CLASS_DECLARATION( Class, Listener, NULL )
|
|
|
|
{
|
|
|
|
{ &EV_Listener_CommandDelay, &Listener::CommandDelay },
|
|
|
|
{ &EV_Delete, &Listener::EventDelete },
|
|
|
|
{ &EV_Remove, &Listener::EventDelete },
|
|
|
|
{ &EV_ScriptRemove, &Listener::EventDelete },
|
|
|
|
{ &EV_Listener_Classname, &Listener::GetClassname },
|
|
|
|
{ &EV_Listener_InheritsFrom, &Listener::EventInheritsFrom },
|
|
|
|
{ &EV_Listener_IsInheritedBy, &Listener::EventIsInheritedBy },
|
|
|
|
|
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
|
|
|
{ &EV_Listener_CancelFor, &Listener::CancelFor },
|
|
|
|
{ &EV_Listener_CreateReturnThread, &Listener::CreateReturnThread },
|
|
|
|
{ &EV_Listener_CreateThread, &Listener::CreateThread },
|
|
|
|
{ &EV_Listener_ExecuteReturnScript, &Listener::ExecuteReturnScript },
|
|
|
|
{ &EV_Listener_ExecuteScript, &Listener::ExecuteScript },
|
|
|
|
{ &EV_Listener_EndOn, &Listener::EventEndOn },
|
|
|
|
{ &EV_Listener_GetOwner, &Listener::EventGetOwner },
|
|
|
|
{ &EV_Listener_Notify, &Listener::EventNotify },
|
|
|
|
{ &EV_DelayThrow, &Listener::EventDelayThrow },
|
|
|
|
{ &EV_Throw, &Listener::EventThrow },
|
|
|
|
{ &EV_Listener_Unregister, &Listener::EventUnregister },
|
|
|
|
{ &EV_Listener_WaitCreateReturnThread, &Listener::WaitCreateReturnThread },
|
|
|
|
{ &EV_Listener_WaitCreateThread, &Listener::WaitCreateThread },
|
|
|
|
{ &EV_Listener_WaitExecuteReturnScript, &Listener::WaitExecuteReturnScript },
|
|
|
|
{ &EV_Listener_WaitExecuteScript, &Listener::WaitExecuteScript },
|
|
|
|
{ &EV_Listener_WaitTill, &Listener::WaitTill },
|
|
|
|
{ &EV_Listener_WaitTillTimeout, &Listener::WaitTillTimeout },
|
|
|
|
{ &EV_Listener_WaitTillAny, &Listener::WaitTillAny },
|
|
|
|
{ &EV_Listener_WaitTillAnyTimeout, &Listener::WaitTillAnyTimeout },
|
|
|
|
#endif
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
cvar_t *g_showevents;
|
|
|
|
cvar_t *g_eventlimit;
|
|
|
|
cvar_t *g_timeevents;
|
|
|
|
cvar_t *g_watch;
|
|
|
|
cvar_t *g_eventstats;
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int HashCode< Event * >( Event * const& key )
|
|
|
|
{
|
|
|
|
// can't use key->eventnum because eventnum will be assigned from con_set
|
2023-01-30 00:24:07 +01:00
|
|
|
return (int)(size_t)key;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int HashCode< command_t >( const command_t& key )
|
|
|
|
{
|
|
|
|
return HashCode< str >( key.command );
|
|
|
|
}
|
|
|
|
|
2023-01-29 20:59:31 +01:00
|
|
|
#if defined(ARCHIVE_SUPPORTED)
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
void ArchiveListenerPtr
|
|
|
|
(
|
|
|
|
Archiver& arc,
|
|
|
|
SafePtr< Listener > *obj
|
|
|
|
)
|
|
|
|
{
|
|
|
|
arc.ArchiveSafePointer( obj );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
void ConList::Archive
|
|
|
|
(
|
|
|
|
Archiver& arc
|
|
|
|
)
|
|
|
|
{
|
|
|
|
value.Archive( arc, ArchiveListenerPtr );
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2023-08-19 02:56:51 +02:00
|
|
|
void con_set< const_str, ConList >::Entry::Archive
|
2016-03-27 11:49:47 +02:00
|
|
|
(
|
|
|
|
Archiver& arc
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Director.ArchiveString( arc, key );
|
|
|
|
value.Archive( arc );
|
|
|
|
}
|
|
|
|
|
2023-01-29 20:59:31 +01:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Archive
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::Archive( Archiver &arc )
|
|
|
|
{
|
|
|
|
if( arc.Loading() ) {
|
|
|
|
fromScript = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class::Archive( arc );
|
|
|
|
|
|
|
|
arc.ArchiveUnsignedShort( &eventnum );
|
|
|
|
arc.ArchiveUnsignedShort( &dataSize );
|
|
|
|
|
|
|
|
if( arc.Loading() )
|
|
|
|
{
|
|
|
|
data = new ScriptVariable[ dataSize + 1 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = dataSize; i > 0; i-- )
|
|
|
|
{
|
|
|
|
data[ i ].ArchiveInternal( arc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void L_ArchiveEvents
|
|
|
|
(
|
|
|
|
Archiver& arc
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EventQueueNode* event;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
for (event = Event::EventQueue.next; event != &Event::EventQueue; event = event->next)
|
|
|
|
{
|
|
|
|
Listener* obj;
|
|
|
|
|
|
|
|
assert(event);
|
|
|
|
|
|
|
|
obj = event->GetSourceObject();
|
|
|
|
|
|
|
|
assert(obj);
|
|
|
|
|
|
|
|
#if defined ( GAME_DLL )
|
|
|
|
if (obj->isSubclassOf(Entity) &&
|
|
|
|
(((Entity*)obj)->flags & FL_DONTSAVE))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
|
|
|
|
arc.ArchiveInteger(&num);
|
|
|
|
for (event = Event::EventQueue.next; event != &Event::EventQueue; event = event->next)
|
|
|
|
{
|
|
|
|
Listener* obj;
|
|
|
|
|
|
|
|
assert(event);
|
|
|
|
|
|
|
|
obj = event->GetSourceObject();
|
|
|
|
|
|
|
|
assert(obj);
|
|
|
|
|
|
|
|
#if defined ( GAME_DLL )
|
|
|
|
if (obj->isSubclassOf(Entity) &&
|
|
|
|
(((Entity*)obj)->flags & FL_DONTSAVE))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
event->event->Archive(arc);
|
|
|
|
arc.ArchiveInteger(&event->inttime);
|
|
|
|
arc.ArchiveInteger(&event->flags);
|
|
|
|
arc.ArchiveSafePointer(&event->m_sourceobject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void L_UnarchiveEvents
|
|
|
|
(
|
|
|
|
Archiver& arc
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EventQueueNode* node;
|
|
|
|
int i, numEvents;
|
|
|
|
|
|
|
|
// the FreeEvents list would already be allocated at this point
|
|
|
|
// clear out any events that may exist
|
|
|
|
L_ClearEventList();
|
|
|
|
|
|
|
|
arc.ArchiveInteger(&numEvents);
|
|
|
|
for (i = 0; i < numEvents; i++)
|
|
|
|
{
|
|
|
|
node = new EventQueueNode();
|
2023-08-16 19:13:52 +02:00
|
|
|
node->event = new Event();
|
|
|
|
node->event->Archive(arc);
|
2023-01-29 20:59:31 +01:00
|
|
|
|
|
|
|
arc.ArchiveInteger(&node->inttime);
|
|
|
|
arc.ArchiveInteger(&node->flags);
|
|
|
|
arc.ArchiveSafePointer(&node->m_sourceobject);
|
|
|
|
|
|
|
|
LL_Add(&Event::EventQueue, node, next, prev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
void L_ClearEventList()
|
|
|
|
{
|
|
|
|
EventQueueNode *node = Event::EventQueue.next, *tmp;
|
|
|
|
|
|
|
|
while( node != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
tmp = node->next;
|
|
|
|
|
|
|
|
delete node->event;
|
|
|
|
delete node;
|
|
|
|
|
|
|
|
node = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
LL_Reset( &Event::EventQueue, next, prev );
|
|
|
|
|
|
|
|
Event_allocator.FreeAll();
|
|
|
|
|
|
|
|
#if defined( GAME_DLL )
|
|
|
|
AnimationEvent_allocator.FreeAll();
|
|
|
|
ConsoleEvent_allocator.FreeAll();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool L_EventSystemStarted( void )
|
|
|
|
{
|
|
|
|
return Listener::EventSystemStarted;
|
|
|
|
}
|
|
|
|
|
|
|
|
void L_InitEvents( void )
|
|
|
|
{
|
2023-05-01 15:15:01 +02:00
|
|
|
g_showevents = LISTENER_Cvar_Get( "g_showevents", "0", 0 );
|
|
|
|
g_eventlimit = LISTENER_Cvar_Get( "g_eventlimit", "5000", 0 );
|
|
|
|
g_timeevents = LISTENER_Cvar_Get( "g_timeevents", "0", 0 );
|
|
|
|
g_watch = LISTENER_Cvar_Get( "g_watch", "0", 0 );
|
|
|
|
g_eventstats = LISTENER_Cvar_Get( "g_eventstats", "0", 0 );
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
Event::LoadEvents();
|
|
|
|
ClassDef::BuildEventResponses();
|
|
|
|
|
|
|
|
LL_Reset( &Event::EventQueue, next, prev );
|
|
|
|
|
|
|
|
L_ClearEventList();
|
|
|
|
Listener::EventSystemStarted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void L_ProcessPendingEvents()
|
|
|
|
{
|
|
|
|
EventQueueNode *node;
|
|
|
|
|
2023-05-16 20:18:43 +02:00
|
|
|
int t = EVENT_msec;
|
2016-03-27 11:49:47 +02:00
|
|
|
while( !LL_Empty( &Event::EventQueue, next, prev ) )
|
|
|
|
{
|
|
|
|
Listener *obj;
|
|
|
|
|
|
|
|
node = Event::EventQueue.next;
|
|
|
|
|
|
|
|
assert( node );
|
|
|
|
|
|
|
|
obj = node->GetSourceObject();
|
|
|
|
|
|
|
|
assert( obj );
|
|
|
|
|
2023-05-16 20:18:43 +02:00
|
|
|
if( node->inttime > t)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the event is removed from its list
|
|
|
|
LL_Remove( node, next, prev );
|
2018-09-17 23:50:38 +02:00
|
|
|
//gi.DPrintf2("Event: %s\n", node->event->getName().c_str());
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
// ProcessEvent will dispose of this event when it is done
|
|
|
|
obj->ProcessEvent( node->event );
|
|
|
|
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void L_ShutdownEvents( void )
|
|
|
|
{
|
|
|
|
if( !Listener::EventSystemStarted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
L_ClearEventList();
|
|
|
|
|
|
|
|
Event::commandList.clear();
|
|
|
|
Event::eventDefList.clear();
|
|
|
|
|
|
|
|
Listener::EventSystemStarted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
// EventArgDef
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
void EventArgDef::Setup( const char *eventName, const char *argName, const char *argType, const char *argRange )
|
|
|
|
{
|
|
|
|
char scratch[ 256 ];
|
|
|
|
const char *ptr;
|
|
|
|
char *tokptr;
|
|
|
|
const char *endptr;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
// set name
|
|
|
|
name = argName;
|
|
|
|
|
|
|
|
// set optionality
|
|
|
|
if ( isupper( argType[ 0 ] ) )
|
|
|
|
{
|
|
|
|
optional = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
optional = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// grab the ranges
|
|
|
|
index = 0;
|
|
|
|
memset( minRangeDefault, true, sizeof( minRangeDefault ) );
|
|
|
|
memset( minRange, 0, sizeof( minRange ) );
|
|
|
|
memset( maxRangeDefault, true, sizeof( maxRangeDefault ) );
|
|
|
|
memset( maxRange, 0, sizeof( maxRange ) );
|
|
|
|
|
|
|
|
if( argRange && argRange[ 0 ] )
|
|
|
|
{
|
|
|
|
ptr = argRange;
|
|
|
|
while( 1 )
|
|
|
|
{
|
|
|
|
// find opening '['
|
|
|
|
tokptr = ( char * )strchr( ptr, '[' );
|
|
|
|
if( !tokptr )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// find closing ']'
|
|
|
|
endptr = strchr( tokptr, ']' );
|
|
|
|
if( !endptr )
|
|
|
|
{
|
|
|
|
assert( 0 );
|
|
|
|
EVENT_Printf( "Argument defintion %s, no matching ']' found for range spec in event %s.\n", name.c_str(), eventName );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// point to the next range
|
|
|
|
ptr = endptr;
|
|
|
|
// skip the '['
|
|
|
|
tokptr++;
|
|
|
|
// copy off the range spec
|
|
|
|
// skip the ']'
|
|
|
|
strncpy( scratch, tokptr, endptr - tokptr );
|
|
|
|
// terminate the range
|
|
|
|
scratch[ endptr - tokptr ] = 0;
|
|
|
|
// see if there is one or two parameters here
|
|
|
|
tokptr = strchr( scratch, ',' );
|
|
|
|
if( !tokptr )
|
|
|
|
{
|
|
|
|
// just one parameter
|
|
|
|
minRange[ index >> 1 ] = ( float )atof( scratch );
|
|
|
|
minRangeDefault[ index >> 1 ] = false;
|
|
|
|
index++;
|
|
|
|
// skip the second parameter
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
else if( tokptr == scratch )
|
|
|
|
{
|
|
|
|
// just second parameter
|
|
|
|
// skip the first paremeter
|
|
|
|
index++;
|
|
|
|
tokptr++;
|
|
|
|
maxRange[ index >> 1 ] = ( float )atof( scratch );
|
|
|
|
maxRangeDefault[ index >> 1 ] = false;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qboolean second;
|
|
|
|
// one or two parameters
|
|
|
|
// see if there is anything behind the ','
|
|
|
|
if( strlen( scratch ) > ( tokptr - scratch + 1 ) )
|
|
|
|
second = true;
|
|
|
|
else
|
|
|
|
second = false;
|
|
|
|
// zero out the ','
|
|
|
|
*tokptr = 0;
|
|
|
|
minRange[ index >> 1 ] = ( float )atof( scratch );
|
|
|
|
minRangeDefault[ index >> 1 ] = false;
|
|
|
|
index++;
|
|
|
|
// skip over the nul character
|
|
|
|
tokptr++;
|
|
|
|
if( second )
|
|
|
|
{
|
|
|
|
maxRange[ index >> 1 ] = ( float )atof( tokptr );
|
|
|
|
maxRangeDefault[ index >> 1 ] = false;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// figure out the type of variable it is
|
|
|
|
switch( tolower( argType[ 0 ] ) )
|
|
|
|
{
|
|
|
|
case 'e':
|
|
|
|
type = IS_ENTITY;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
type = IS_VECTOR;
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
type = IS_INTEGER;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
type = IS_FLOAT;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
type = IS_STRING;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
type = IS_BOOLEAN;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
type = IS_LISTENER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EV_Print( FILE *stream, const char *format, ... )
|
|
|
|
{
|
|
|
|
char buffer[ 1000 ];
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
va_start( va, format );
|
|
|
|
|
|
|
|
vsprintf( buffer, format, va );
|
|
|
|
|
|
|
|
if( stream )
|
|
|
|
{
|
2023-01-31 19:28:10 +01:00
|
|
|
fprintf(stream, "%s", buffer);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
EVENT_DPrintf("%s", buffer);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
va_end( va );
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventArgDef::PrintRange( FILE *event_file )
|
|
|
|
{
|
|
|
|
qboolean integer;
|
|
|
|
qboolean single;
|
|
|
|
int numRanges;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
single = false;
|
|
|
|
integer = true;
|
|
|
|
numRanges = 1;
|
|
|
|
switch( type )
|
|
|
|
{
|
|
|
|
case IS_VECTOR:
|
|
|
|
integer = false;
|
|
|
|
numRanges = 3;
|
|
|
|
break;
|
|
|
|
case IS_FLOAT:
|
|
|
|
integer = false;
|
|
|
|
break;
|
|
|
|
case IS_STRING:
|
|
|
|
single = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for( i = 0; i < numRanges; i++ )
|
|
|
|
{
|
|
|
|
if ( single )
|
|
|
|
{
|
|
|
|
if ( !minRangeDefault[ i ] )
|
|
|
|
{
|
|
|
|
if ( integer )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%d>", ( int )minRange[ i ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%.2f>", minRange[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// both non-default
|
|
|
|
if ( !minRangeDefault[ i ] && !maxRangeDefault[ i ] )
|
|
|
|
{
|
|
|
|
if ( integer )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%d...%d>", ( int )minRange[ i ], ( int )maxRange[ i ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%.2f...%.2f>", minRange[ i ], maxRange[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// max default
|
|
|
|
else if ( !minRangeDefault[ i ] && maxRangeDefault[ i ] )
|
|
|
|
{
|
|
|
|
if ( integer )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%d...max_integer>", ( int )minRange[ i ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<%.2f...max_float>", minRange[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// min default
|
|
|
|
else if ( minRangeDefault[ i ] && !maxRangeDefault[ i ] )
|
|
|
|
{
|
|
|
|
if ( integer )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<min_integer...%d>", ( int )maxRange[ i ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<min_float...%.2f>", maxRange[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventArgDef::PrintArgument( FILE *event_file )
|
|
|
|
{
|
|
|
|
if( optional )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "[ " );
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( type )
|
|
|
|
{
|
|
|
|
case IS_ENTITY:
|
|
|
|
EV_Print( event_file, "Entity " );
|
|
|
|
break;
|
|
|
|
case IS_VECTOR:
|
|
|
|
EV_Print( event_file, "Vector " );
|
|
|
|
break;
|
|
|
|
case IS_INTEGER:
|
|
|
|
EV_Print( event_file, "Integer " );
|
|
|
|
break;
|
|
|
|
case IS_FLOAT:
|
|
|
|
EV_Print( event_file, "Float " );
|
|
|
|
break;
|
|
|
|
case IS_STRING:
|
|
|
|
EV_Print( event_file, "String " );
|
|
|
|
break;
|
|
|
|
case IS_BOOLEAN:
|
|
|
|
EV_Print( event_file, "Boolean " );
|
|
|
|
break;
|
|
|
|
case IS_LISTENER:
|
|
|
|
EV_Print( event_file, "Listener " );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EV_Print( event_file, "%s", name.c_str() );
|
|
|
|
|
|
|
|
PrintRange( event_file );
|
|
|
|
|
|
|
|
if ( optional )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, " ]" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventDef::Error( const char *format, ... )
|
|
|
|
{
|
|
|
|
char buffer[ 1000 ];
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
va_start( va, format );
|
|
|
|
vsprintf( buffer, format, va );
|
|
|
|
va_end( va );
|
|
|
|
|
|
|
|
EVENT_Printf( "^~^~^ Game: '%s' : %s\n", command.c_str(), buffer );
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventDef::PrintDocumentation( FILE *event_file, bool html )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int p;
|
|
|
|
str text;
|
|
|
|
const char *name = command.c_str();
|
|
|
|
|
|
|
|
if ( !html )
|
|
|
|
{
|
|
|
|
text = " ";
|
|
|
|
p = 0;
|
|
|
|
|
|
|
|
if ( flags & EV_CONSOLE )
|
|
|
|
{
|
|
|
|
text[ p++ ] = '*';
|
|
|
|
}
|
|
|
|
if ( flags & EV_CHEAT )
|
|
|
|
{
|
|
|
|
text[ p++ ] = 'C';
|
|
|
|
}
|
|
|
|
if ( flags & EV_CACHE )
|
|
|
|
{
|
|
|
|
text[ p++ ] = '%';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "\n<P><tt><B>%s</B>", name );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( text[ 0 ] != ' ' )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "%s %s", text.c_str(), name );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "%s %s", text.c_str(), name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetupDocumentation();
|
|
|
|
|
|
|
|
if ( definition )
|
|
|
|
{
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "( <i>" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "( " );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( i = 1; i <= definition->NumObjects(); i++ )
|
|
|
|
{
|
|
|
|
definition->ObjectAt( i ).PrintArgument( event_file );
|
|
|
|
|
|
|
|
if ( i < definition->NumObjects() )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, ", " );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, " </i>)</tt><BR>\n" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, " )\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
DeleteDocumentation();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "</tt><BR>\n" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "\n" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( documentation )
|
|
|
|
{
|
|
|
|
char new_doc[ 1024 ];
|
|
|
|
int old_index;
|
|
|
|
int new_index = 0;
|
|
|
|
|
|
|
|
for( old_index = 0; old_index < strlen( documentation ); old_index++ )
|
|
|
|
{
|
|
|
|
if( documentation[ old_index ] == '\n' )
|
|
|
|
{
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
new_doc[ new_index ] = '<';
|
|
|
|
new_doc[ new_index + 1 ] = 'B';
|
|
|
|
new_doc[ new_index + 2 ] = 'R';
|
|
|
|
new_doc[ new_index + 3 ] = '>';
|
|
|
|
new_doc[ new_index + 4 ] = '\n';
|
|
|
|
new_index += 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_doc[ new_index ] = '\n';
|
|
|
|
new_doc[ new_index + 1 ] = '\t';
|
|
|
|
new_doc[ new_index + 2 ] = '\t';
|
|
|
|
new_index += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_doc[ new_index ] = documentation[ old_index ];
|
|
|
|
new_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
new_doc[ new_index ] = 0;
|
|
|
|
|
|
|
|
if ( html )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "<ul>%s</ul>\n", new_doc );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "\t\t- %s\n", new_doc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventDef::PrintEventDocumentation( FILE *event_file, bool html )
|
|
|
|
{
|
|
|
|
if( flags & EV_CODEONLY ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// purposely suppressed
|
|
|
|
if( command[ 0 ] == '_' )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintDocumentation( event_file, html );
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventDef::DeleteDocumentation( void )
|
|
|
|
{
|
|
|
|
if( formatspec )
|
|
|
|
{
|
|
|
|
if( argument_names )
|
|
|
|
{
|
|
|
|
definition->FreeObjectList();
|
|
|
|
|
|
|
|
delete definition;
|
|
|
|
definition = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventDef::SetupDocumentation( void )
|
|
|
|
{
|
|
|
|
const char *name = command.c_str();
|
|
|
|
|
|
|
|
// setup documentation
|
|
|
|
if ( formatspec )
|
|
|
|
{
|
|
|
|
if ( argument_names )
|
|
|
|
{
|
|
|
|
char argumentNames[ 256 ];
|
|
|
|
str argSpec;
|
|
|
|
str rangeSpec;
|
|
|
|
str argName;
|
|
|
|
EventArgDef argDef;
|
|
|
|
const char *namePtr;
|
|
|
|
const char *specPtr;
|
|
|
|
size_t specLength;
|
|
|
|
int index;
|
|
|
|
Container<str> argNames;
|
|
|
|
|
|
|
|
specLength = strlen( formatspec );
|
|
|
|
specPtr = formatspec;
|
|
|
|
//
|
|
|
|
// store off all the names
|
|
|
|
//
|
|
|
|
strcpy( argumentNames, argument_names );
|
|
|
|
namePtr = strtok( argumentNames, " " );
|
|
|
|
while ( namePtr != NULL )
|
|
|
|
{
|
|
|
|
argNames.AddObject( str( namePtr ) );
|
|
|
|
namePtr = strtok( NULL, " " );
|
|
|
|
}
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
|
|
|
|
//
|
|
|
|
// create the definition container
|
|
|
|
//
|
|
|
|
definition = new Container<EventArgDef>;
|
|
|
|
definition->Resize( argNames.NumObjects() );
|
|
|
|
|
|
|
|
// go throught he formatspec
|
|
|
|
while( specLength )
|
|
|
|
{
|
|
|
|
// clear the rangeSpec
|
|
|
|
rangeSpec = "";
|
|
|
|
// get the argSpec
|
|
|
|
argSpec = "";
|
|
|
|
argSpec += *specPtr;
|
|
|
|
specPtr++;
|
|
|
|
specLength--;
|
|
|
|
// see if there is a range specified
|
|
|
|
while ( *specPtr == '[' )
|
|
|
|
{
|
|
|
|
// add in all the characters until NULL or ']'
|
|
|
|
while( specLength && ( *specPtr != ']' ) )
|
|
|
|
{
|
|
|
|
rangeSpec += *specPtr;
|
|
|
|
specPtr++;
|
|
|
|
specLength--;
|
|
|
|
}
|
|
|
|
if ( specLength && ( *specPtr == ']' ) )
|
|
|
|
{
|
|
|
|
rangeSpec += *specPtr;
|
|
|
|
specPtr++;
|
|
|
|
specLength--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( index < argNames.NumObjects() )
|
|
|
|
{
|
|
|
|
argName = argNames.ObjectAt( index + 1 );
|
|
|
|
argDef.Setup( name, argName, argSpec, rangeSpec );
|
|
|
|
definition->AddObject( argDef );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert( 0 );
|
|
|
|
Error( "More format specifiers than argument names for event %s\n", name );
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
if ( index < argNames.NumObjects() )
|
|
|
|
{
|
|
|
|
assert( 0 );
|
|
|
|
Error( "More argument names than format specifiers for event %s\n", name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================================
|
|
|
|
// Event
|
|
|
|
//====================================
|
|
|
|
|
2023-01-30 17:11:44 +01:00
|
|
|
MEM_BlockAlloc<Event> Event_allocator;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
CLASS_DECLARATION( Class, Event, NULL )
|
|
|
|
{
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2017-02-19 12:13:43 +01:00
|
|
|
#ifndef _DEBUG_MEM
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
new Event
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void *Event::operator new( size_t size )
|
|
|
|
{
|
|
|
|
return Event_allocator.Alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
delete ptr
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::operator delete( void *ptr )
|
|
|
|
{
|
|
|
|
Event_allocator.Free( ptr );
|
|
|
|
}
|
|
|
|
|
2017-02-19 12:13:43 +01:00
|
|
|
#endif
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
2023-09-07 18:05:49 +02:00
|
|
|
unsigned int Event::FindEventNum( const char* s )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-07 18:05:49 +02:00
|
|
|
command_t cmd(s, EV_NORMAL);
|
2016-03-27 11:49:47 +02:00
|
|
|
return commandList.findKeyIndex( cmd );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
NumEventCommands
|
|
|
|
|
|
|
|
Number of total events
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::NumEventCommands()
|
|
|
|
{
|
|
|
|
return totalevents;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ListCommands
|
|
|
|
|
|
|
|
List event commands
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::ListCommands
|
|
|
|
(
|
|
|
|
const char *mask
|
|
|
|
)
|
|
|
|
{
|
|
|
|
command_t *command;
|
|
|
|
int eventnum;
|
|
|
|
int num;
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
size_t l;
|
|
|
|
int p;
|
|
|
|
int hidden;
|
|
|
|
str text;
|
|
|
|
Container< int > *sortedList;
|
|
|
|
|
|
|
|
if ( !commandList.size() )
|
|
|
|
{
|
|
|
|
EVENT_DPrintf( "No events.\n" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortedList = &ClassDef::sortedList;
|
|
|
|
SortEventList( sortedList );
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
if ( mask )
|
|
|
|
{
|
|
|
|
l = strlen( mask );
|
|
|
|
}
|
|
|
|
|
|
|
|
hidden = 0;
|
|
|
|
num = 0;
|
|
|
|
n = sortedList->NumObjects();
|
|
|
|
for( i = 1; i <= n; i++ )
|
|
|
|
{
|
|
|
|
eventnum = sortedList->ObjectAt( i );
|
|
|
|
command = &commandList[ eventnum ];
|
|
|
|
|
|
|
|
if ( command->flags & EV_CODEONLY )
|
|
|
|
{
|
|
|
|
hidden++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
if ( mask && Q_stricmpn( command->command, mask, l ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
num++;
|
|
|
|
|
|
|
|
text = " ";
|
|
|
|
p = 0;
|
|
|
|
if( command->flags & EV_CONSOLE )
|
|
|
|
{
|
|
|
|
text[ p++ ] = '*';
|
|
|
|
}
|
|
|
|
if( command->flags & EV_CHEAT )
|
|
|
|
{
|
|
|
|
text[ p++ ] = 'C';
|
|
|
|
}
|
|
|
|
if( command->flags & EV_CACHE )
|
|
|
|
{
|
|
|
|
text[ p++ ] = '%';
|
|
|
|
}
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_Printf( "%4d : %s%s\n", eventnum, text.c_str(), command->command );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
EVENT_Printf( "\n* = console command.\nC = cheat command.\n%% = cache command.\n\n"
|
2016-03-27 11:49:47 +02:00
|
|
|
"Printed %d of %d total commands.\n", num, n - hidden );
|
|
|
|
|
|
|
|
if ( developer->integer && hidden )
|
|
|
|
{
|
|
|
|
EVENT_Printf( "Suppressed %d commands.\n", hidden );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ListDocumentation
|
|
|
|
|
|
|
|
List event documentation
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::ListDocumentation
|
|
|
|
(
|
|
|
|
const char *mask,
|
|
|
|
qboolean print_to_disk
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int num;
|
|
|
|
int n;
|
|
|
|
size_t l;
|
|
|
|
int flags;
|
|
|
|
int hidden;
|
|
|
|
str name;
|
|
|
|
str text;
|
|
|
|
FILE *event_file = NULL;
|
|
|
|
str event_filename;
|
|
|
|
con_map_enum< Event *, EventDef > en = eventDefList;
|
|
|
|
EventDef *def;
|
|
|
|
|
|
|
|
if ( print_to_disk )
|
|
|
|
{
|
|
|
|
if ( !mask || !mask[0] )
|
|
|
|
event_filename = EVENT_FILENAME;
|
|
|
|
else
|
|
|
|
event_filename = str ( mask ) + ".txt";
|
|
|
|
|
|
|
|
event_file = fopen( event_filename.c_str(), "w" );
|
|
|
|
|
|
|
|
if ( event_file == NULL )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
if ( mask )
|
|
|
|
{
|
|
|
|
l = strlen( mask );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EV_Print( event_file, "\nCommand Documentation\n" );
|
|
|
|
EV_Print( event_file, "=====================\n" );
|
|
|
|
|
|
|
|
hidden = 0;
|
|
|
|
num = 0;
|
|
|
|
n = 0;
|
|
|
|
for( def = en.NextValue(); def != NULL; def = en.NextValue() )
|
|
|
|
{
|
|
|
|
flags = def->flags;
|
|
|
|
name = def->command;
|
|
|
|
n++;
|
|
|
|
|
|
|
|
if( flags & EV_CODEONLY )
|
|
|
|
{
|
|
|
|
hidden++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( mask && Q_stricmpn( name, mask, l ) )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
num++;
|
|
|
|
|
|
|
|
def->PrintDocumentation( event_file, qfalse );
|
|
|
|
}
|
|
|
|
|
|
|
|
EV_Print( event_file, "\n* = console command.\nC = cheat command.\n% = cache command.\n\n"
|
|
|
|
"Printed %d of %d total commands.\n", num, n - hidden );
|
|
|
|
|
|
|
|
if ( developer->integer && hidden )
|
|
|
|
{
|
|
|
|
EV_Print( event_file, "Suppressed %d commands.\n", hidden );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( event_file != NULL )
|
|
|
|
{
|
|
|
|
EVENT_Printf( "Printed event info to file %s\n", event_filename.c_str() );
|
|
|
|
fclose( event_file );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PendingEvents
|
|
|
|
|
|
|
|
List pending events
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::PendingEvents
|
|
|
|
(
|
|
|
|
const char *mask
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EventQueueNode *event;
|
|
|
|
size_t l;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
if ( mask )
|
|
|
|
{
|
|
|
|
l = strlen( mask );
|
|
|
|
}
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
event = EventQueue.next;
|
|
|
|
while( event != &EventQueue )
|
|
|
|
{
|
|
|
|
assert( event );
|
|
|
|
assert( event->m_sourceobject );
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
if ( !mask || !Q_stricmpn( event->event->getName(), mask, l ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
num++;
|
|
|
|
//Event::PrintEvent( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
EVENT_Printf( "%d pending events as of %.2f\n", num, EVENT_time );
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindNormalEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindNormalEventNum( const_str s )
|
|
|
|
{
|
|
|
|
unsigned int *eventnum = normalCommandList.find( s );
|
|
|
|
if( eventnum )
|
|
|
|
{
|
|
|
|
return *eventnum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindReturnEventNum
|
|
|
|
|
|
|
|
Finds an event that return a value
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindReturnEventNum( const_str s )
|
|
|
|
{
|
|
|
|
unsigned int *eventnum = returnCommandList.find( s );
|
|
|
|
if( eventnum )
|
|
|
|
{
|
|
|
|
return *eventnum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindSetterEventNum
|
|
|
|
|
|
|
|
Finds an event that act as a write-variable
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindSetterEventNum( const_str s )
|
|
|
|
{
|
|
|
|
unsigned int *eventnum = setterCommandList.find( s );
|
|
|
|
if( eventnum )
|
|
|
|
{
|
|
|
|
return *eventnum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindGetterEventNum
|
|
|
|
|
|
|
|
Finds an event that act as a read-variable
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindGetterEventNum( const_str s )
|
|
|
|
{
|
|
|
|
unsigned int *eventnum = getterCommandList.find( s );
|
|
|
|
if( eventnum )
|
|
|
|
{
|
|
|
|
return *eventnum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindNormalEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindNormalEventNum( str s )
|
|
|
|
{
|
|
|
|
s.tolower();
|
|
|
|
return FindNormalEventNum( Director.AddString( s ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindReturnEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindReturnEventNum( str s )
|
|
|
|
{
|
|
|
|
s.tolower();
|
|
|
|
return FindReturnEventNum( Director.AddString( s ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindSetterEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindSetterEventNum( str s )
|
|
|
|
{
|
|
|
|
s.tolower();
|
|
|
|
return FindSetterEventNum( Director.AddString( s ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
FindGetterEventNum
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
unsigned int Event::FindGetterEventNum( str s )
|
|
|
|
{
|
|
|
|
s.tolower();
|
|
|
|
return FindGetterEventNum( Director.AddString( s ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEventWithFlags
|
|
|
|
|
|
|
|
Returns an event that match the specified flags and the specified type
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::GetEventWithFlags( str name, int flags, uchar type )
|
|
|
|
{
|
|
|
|
unsigned int *index;
|
|
|
|
con_map< const_str, unsigned int > *cmdList;
|
|
|
|
|
|
|
|
if( type == EV_NORMAL )
|
|
|
|
{
|
|
|
|
cmdList = &normalCommandList;
|
|
|
|
}
|
|
|
|
else if( type == EV_RETURN )
|
|
|
|
{
|
|
|
|
cmdList = &returnCommandList;
|
|
|
|
}
|
|
|
|
else if( type == EV_GETTER )
|
|
|
|
{
|
|
|
|
cmdList = &getterCommandList;
|
|
|
|
}
|
|
|
|
else if( type == EV_SETTER )
|
|
|
|
{
|
|
|
|
cmdList = &setterCommandList;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
name.tolower();
|
|
|
|
|
|
|
|
index = cmdList->find( Director.GetString( name ) );
|
|
|
|
|
|
|
|
if( !index || !( GetEventFlags( *index ) & flags ) )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return *index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::GetEvent( str name, uchar type )
|
|
|
|
{
|
|
|
|
return GetEventWithFlags( name, EV_DEFAULT, type );
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
int Event::GetEvent( str name, uchar type )
|
|
|
|
{
|
|
|
|
return FindEventNum( name );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static str str_null;
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEventInfo
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
command_t *Event::GetEventInfo( int eventnum )
|
|
|
|
{
|
|
|
|
return &commandList[ eventnum ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEventFlags
|
|
|
|
|
|
|
|
Returns the specified event flags
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::GetEventFlags( int eventnum )
|
|
|
|
{
|
|
|
|
command_t *cmd = &commandList[ eventnum ];
|
|
|
|
|
|
|
|
if( cmd )
|
|
|
|
{
|
|
|
|
return cmd->flags;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEventName
|
|
|
|
|
|
|
|
Returns the specified event name
|
|
|
|
=======================
|
|
|
|
*/
|
2023-09-07 18:05:49 +02:00
|
|
|
const char* Event::GetEventName( int eventnum )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
command_t *cmd;
|
|
|
|
|
|
|
|
if( eventnum <= 0 ) {
|
|
|
|
return str_null;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd = &commandList[ eventnum ];
|
|
|
|
|
|
|
|
if( cmd )
|
|
|
|
{
|
|
|
|
return cmd->command;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return str_null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return str_null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
compareEvents
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::compareEvents( const void *arg1, const void *arg2 )
|
|
|
|
{
|
|
|
|
int num1 = *( int * )arg1;
|
|
|
|
int num2 = *( int * )arg2;
|
|
|
|
command_t *cmd1 = &commandList[ num1 ];
|
|
|
|
command_t *cmd2 = &commandList[ num2 ];
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
return Q_stricmp( cmd1->command, cmd2->command );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
SortEventList
|
|
|
|
|
|
|
|
Sort events in alphabetical order
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::SortEventList( Container< int > *sortedList )
|
|
|
|
{
|
2023-06-17 02:27:12 +02:00
|
|
|
unsigned int i;
|
2016-03-27 11:49:47 +02:00
|
|
|
command_t *cmd;
|
|
|
|
|
|
|
|
sortedList->Resize( commandList.size() );
|
|
|
|
|
|
|
|
for( i = 1; i <= commandList.size(); i++ )
|
|
|
|
{
|
|
|
|
cmd = &commandList[ i ];
|
|
|
|
|
|
|
|
if( cmd != NULL )
|
|
|
|
{
|
|
|
|
sortedList->AddObject( i );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qsort( ( void * )sortedList->AddressOfObjectAt( 1 ),
|
|
|
|
( size_t )sortedList->NumObjects(),
|
|
|
|
sizeof( int ), compareEvents );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
LoadEvents
|
|
|
|
|
|
|
|
Event loader routine
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::LoadEvents()
|
|
|
|
{
|
2023-09-04 21:38:58 +02:00
|
|
|
command_t c;
|
|
|
|
DataNode* next;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
for(; DataNodeList; DataNodeList = next)
|
|
|
|
{
|
|
|
|
next = DataNodeList->next;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
EventDef* cmd = &eventDefList[DataNodeList->ev];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
cmd->command = DataNodeList->command;
|
|
|
|
cmd->flags = ((DataNodeList->flags == EV_DEFAULT) - 1) & DataNodeList->flags;
|
|
|
|
cmd->formatspec = DataNodeList->formatspec;
|
|
|
|
cmd->argument_names = DataNodeList->argument_names;
|
|
|
|
cmd->documentation = DataNodeList->documentation;
|
|
|
|
cmd->type = DataNodeList->type;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
c.command = DataNodeList->command;
|
|
|
|
c.flags = DataNodeList->flags;
|
|
|
|
c.type = cmd->type;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
DataNodeList->ev->eventnum = commandList.addKeyIndex(c);
|
|
|
|
#ifdef _DEBUG
|
|
|
|
DataNodeList->ev->name = DataNodeList->command;
|
|
|
|
#endif
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
delete DataNodeList;
|
|
|
|
totalevents++;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::Event()
|
|
|
|
{
|
|
|
|
fromScript = false;
|
|
|
|
eventnum = 0;
|
|
|
|
data = NULL;
|
|
|
|
dataSize = 0;
|
|
|
|
maxDataSize = 0;
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
|
|
|
|
Creates an event command
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::Event
|
|
|
|
(
|
|
|
|
const char *command,
|
|
|
|
int flags,
|
|
|
|
const char *formatspec,
|
|
|
|
const char *argument_names,
|
|
|
|
const char *documentation,
|
|
|
|
uchar type
|
|
|
|
)
|
|
|
|
{
|
2023-09-04 21:38:58 +02:00
|
|
|
DataNode* node = new DataNode();
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-04 21:38:58 +02:00
|
|
|
node->ev = this;
|
|
|
|
node->command = command;
|
|
|
|
node->flags = flags;
|
|
|
|
node->formatspec = formatspec;
|
|
|
|
node->argument_names = argument_names;
|
|
|
|
node->documentation = documentation;
|
|
|
|
node->type = type;
|
|
|
|
node->next = DataNodeList;
|
|
|
|
DataNodeList = node;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
fromScript = false;
|
|
|
|
dataSize = 0;
|
2023-08-19 20:48:46 +02:00
|
|
|
maxDataSize = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
data = NULL;
|
|
|
|
eventnum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
=======================
|
|
|
|
*/
|
2023-09-07 18:21:03 +02:00
|
|
|
Event::Event( const Event &ev )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-07 18:21:03 +02:00
|
|
|
fromScript = ev.fromScript;
|
|
|
|
eventnum = ev.eventnum;
|
|
|
|
dataSize = ev.dataSize;
|
|
|
|
maxDataSize = ev.maxDataSize;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
if (dataSize)
|
|
|
|
{
|
|
|
|
data = new ScriptVariable[dataSize];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
for (int i = 0; i < dataSize; i++)
|
|
|
|
{
|
|
|
|
data[i] = ev.data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2023-09-07 18:21:03 +02:00
|
|
|
name = ev.name;
|
2016-03-27 11:49:47 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
Event::Event(Event&& ev)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-07 18:21:03 +02:00
|
|
|
fromScript = ev.fromScript;
|
|
|
|
eventnum = ev.eventnum;
|
2023-08-19 20:48:46 +02:00
|
|
|
dataSize = ev.dataSize;
|
|
|
|
maxDataSize = ev.maxDataSize;
|
2023-09-07 18:21:03 +02:00
|
|
|
data = ev.data;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
ev.data = NULL;
|
|
|
|
ev.dataSize = 0;
|
|
|
|
ev.maxDataSize = 0;
|
|
|
|
ev.eventnum = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
|
|
|
|
Initializes the event with the specified index
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::Event( int index )
|
|
|
|
{
|
|
|
|
fromScript = false;
|
|
|
|
eventnum = index;
|
|
|
|
data = NULL;
|
2023-08-19 20:48:46 +02:00
|
|
|
dataSize = 0;
|
|
|
|
maxDataSize = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
name = GetEventName( index );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
|
2023-07-05 21:42:36 +02:00
|
|
|
Initializes the event with the specified index
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::Event(int index, int numArgs)
|
|
|
|
{
|
|
|
|
fromScript = false;
|
|
|
|
eventnum = index;
|
|
|
|
data = new ScriptVariable[numArgs];
|
2023-08-19 20:48:46 +02:00
|
|
|
dataSize = 0;
|
|
|
|
maxDataSize = numArgs;
|
2023-07-05 21:42:36 +02:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
name = GetEventName(index);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
Initializes the event with the specified command
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::Event(const char* command)
|
|
|
|
{
|
|
|
|
eventnum = FindEventNum(command);
|
|
|
|
if (!eventnum)
|
|
|
|
{
|
|
|
|
EVENT_DPrintf("^~^~^ Event '%s' does not exist.\n", command);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromScript = qfalse;
|
|
|
|
maxDataSize = 0;
|
|
|
|
dataSize = 0;
|
|
|
|
data = NULL;
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
name = command;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Event
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
Initializes the event with the specified command
|
|
|
|
=======================
|
|
|
|
*/
|
2023-09-07 18:05:49 +02:00
|
|
|
Event::Event(const char* command, int numArgs)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-07 18:05:49 +02:00
|
|
|
eventnum = FindEventNum(command);
|
2016-03-27 11:49:47 +02:00
|
|
|
if( !eventnum )
|
|
|
|
{
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_DPrintf( "^~^~^ Event '%s' does not exist.\n", command );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-08-19 20:48:46 +02:00
|
|
|
fromScript = qfalse;
|
|
|
|
maxDataSize = numArgs;
|
|
|
|
|
2023-08-01 19:30:28 +02:00
|
|
|
if (numArgs) {
|
|
|
|
data = new ScriptVariable[numArgs];
|
2023-08-19 20:48:46 +02:00
|
|
|
dataSize = 0;
|
2023-08-01 19:30:28 +02:00
|
|
|
} else {
|
|
|
|
dataSize = 0;
|
|
|
|
data = NULL;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
name = command;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-09-07 18:21:03 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
~Event
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Event::~Event()
|
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Event& Event::operator=(const Event& ev)
|
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
fromScript = ev.fromScript;
|
|
|
|
eventnum = ev.eventnum;
|
|
|
|
dataSize = ev.dataSize;
|
|
|
|
maxDataSize = ev.maxDataSize;
|
|
|
|
|
|
|
|
if (dataSize)
|
|
|
|
{
|
|
|
|
data = new ScriptVariable[dataSize];
|
|
|
|
|
|
|
|
for (int i = 0; i < dataSize; i++)
|
|
|
|
{
|
|
|
|
data[i] = ev.data[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
name = ev.name;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Event& Event::operator=(Event&& ev)
|
|
|
|
{
|
|
|
|
Clear();
|
|
|
|
fromScript = ev.fromScript;
|
|
|
|
eventnum = ev.eventnum;
|
|
|
|
dataSize = ev.dataSize;
|
|
|
|
maxDataSize = ev.maxDataSize;
|
|
|
|
data = ev.data;
|
|
|
|
|
|
|
|
ev.data = NULL;
|
|
|
|
ev.dataSize = 0;
|
|
|
|
ev.maxDataSize = 0;
|
|
|
|
ev.eventnum = 0;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ErrorInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::ErrorInternal(Listener* l, str text) const
|
|
|
|
{
|
|
|
|
str classname;
|
|
|
|
str eventname;
|
|
|
|
|
|
|
|
EVENT_DPrintf("^~^~^ Game");
|
|
|
|
|
|
|
|
classname = l->getClassname();
|
|
|
|
eventname = getName();
|
|
|
|
|
|
|
|
EVENT_DPrintf(" (Event: '%s', Object: '%s') : %s\n", eventname.c_str(), classname.c_str(), text.c_str());
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddContainer
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddContainer( Container< SafePtr< Listener > > *container )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setContainerValue( container );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddEntity
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddEntity( Entity *ent )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setListenerValue( ( Listener * )ent );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddFloat
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddFloat( float number )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setFloatValue( number );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddInteger
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddInteger( int number )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setIntValue( number );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddListener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddListener( Listener * listener )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setListenerValue( listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddNil
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddNil( void )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.Clear();
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddConstString
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddConstString( const_str string )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setConstStringValue( string );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddString
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddString( str string )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setStringValue( string );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddToken
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddToken( str token )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setStringValue( token );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddTokens
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddTokens( int argc, const char **argv )
|
|
|
|
{
|
|
|
|
for( int i = 0; i < argc; i++ )
|
|
|
|
{
|
|
|
|
AddToken( argv[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddValue
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddValue( const ScriptVariable &value )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AddVector
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::AddVector( const Vector& vector )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue();
|
|
|
|
variable.setVectorValue( vector );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Clear
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::Clear( void )
|
|
|
|
{
|
|
|
|
if( data )
|
|
|
|
{
|
|
|
|
delete[] data;
|
|
|
|
|
|
|
|
data = NULL;
|
2023-08-19 20:48:46 +02:00
|
|
|
dataSize = 0;
|
|
|
|
maxDataSize = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CheckPos
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Event::CheckPos( int pos )
|
|
|
|
{
|
|
|
|
if( pos > NumArgs() ) {
|
|
|
|
ScriptError( "Index %d out of range.", pos );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetBoolean
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Event::GetBoolean( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.booleanNumericValue();
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetConstString
|
|
|
|
=======================
|
|
|
|
*/
|
2019-06-29 23:43:30 +02:00
|
|
|
const_str Event::GetConstString( int pos )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.constStringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetEntity
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Entity *Event::GetEntity( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.entityValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetFloat
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
float Event::GetFloat( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.floatValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetInteger
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::GetInteger( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.intValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetListener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Listener * Event::GetListener( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.listenerValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetSimpleEntity
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
SimpleEntity * Event::GetSimpleEntity( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.simpleEntityValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetString
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
str Event::GetString( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
return variable.stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetToken
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
str Event::GetToken( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
return variable.stringValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetValue
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptVariable& Event::GetValue( int pos )
|
|
|
|
{
|
|
|
|
if( pos < 0 )
|
|
|
|
{
|
|
|
|
pos = NumArgs() + pos + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
static ScriptVariable m_null;
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetValue
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptVariable& Event::GetValue( void )
|
|
|
|
{
|
2023-08-19 20:48:46 +02:00
|
|
|
if (dataSize == maxDataSize) {
|
|
|
|
ScriptVariable* tmp = data;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-19 20:48:46 +02:00
|
|
|
maxDataSize++;
|
|
|
|
data = new ScriptVariable[maxDataSize];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-19 20:48:46 +02:00
|
|
|
if (tmp != NULL)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < dataSize; i++) {
|
|
|
|
data[i] = std::move(tmp[i]);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-19 20:48:46 +02:00
|
|
|
delete[] tmp;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dataSize++;
|
|
|
|
|
|
|
|
return data[ dataSize - 1 ];
|
|
|
|
}
|
|
|
|
|
2023-02-02 23:47:25 +01:00
|
|
|
ScriptVariable& Event::GetLastValue()
|
|
|
|
{
|
|
|
|
return GetValue(NumArgs());
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetVector
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Vector Event::GetVector( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.vectorValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined ( GAME_DLL )
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetPathNode
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
PathNode *Event::GetPathNode( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.pathNodeValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetWaypoint
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Waypoint *Event::GetWaypoint( int pos )
|
|
|
|
{
|
|
|
|
ScriptVariable& variable = GetValue( pos );
|
|
|
|
|
|
|
|
return variable.waypointValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsEntityAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsEntityAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos- 1 ].IsEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsListenerAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsListenerAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].IsListener();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsNilAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsNilAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].GetType() == VARIABLE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsNumericAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsNumericAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].IsNumeric();
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsSimpleEntityAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsSimpleEntityAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].IsSimpleEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsStringAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsStringAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].IsString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsVectorAt
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsVectorAt( int pos )
|
|
|
|
{
|
|
|
|
CheckPos( pos );
|
|
|
|
|
|
|
|
return data[ pos - 1 ].IsVector();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
IsFromScript
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Event::IsFromScript()
|
|
|
|
{
|
|
|
|
return fromScript;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
NumArgs
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Event::NumArgs()
|
|
|
|
{
|
|
|
|
return dataSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
getInfo
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
EventDef *Event::getInfo()
|
|
|
|
{
|
|
|
|
return &eventDefList[ this ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
getName
|
|
|
|
=======================
|
|
|
|
*/
|
2023-09-07 18:05:49 +02:00
|
|
|
const char* Event::getName() const
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return GetEventName( eventnum );
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================================
|
|
|
|
// Listener
|
|
|
|
//====================================
|
|
|
|
|
|
|
|
qboolean ListenerDelete = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Listener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Listener::Listener()
|
|
|
|
{
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
m_EndList = NULL;
|
|
|
|
|
|
|
|
m_NotifyList = NULL;
|
|
|
|
m_WaitForList = NULL;
|
|
|
|
|
|
|
|
vars = NULL;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
~Listener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Listener::~Listener()
|
|
|
|
{
|
2023-08-19 15:39:59 +02:00
|
|
|
if (EventSystemStarted) {
|
|
|
|
CancelPendingEvents();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
UnregisterAll();
|
|
|
|
CancelWaitingAll();
|
|
|
|
|
|
|
|
if( vars ) {
|
|
|
|
delete vars;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define L_ARCHIVE_NOTIFYLIST 1
|
|
|
|
#define L_ARCHIVE_WAITFORLIST 2
|
|
|
|
#define L_ARCHIVE_VARLIST 4
|
|
|
|
#define L_ARCHIVE_ENDLIST 8
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Archive
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Archive( Archiver &arc )
|
|
|
|
{
|
|
|
|
Class::Archive( arc );
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
byte flag = 0;
|
|
|
|
|
|
|
|
if( !arc.Loading() )
|
|
|
|
{
|
|
|
|
if( m_NotifyList )
|
|
|
|
flag |= L_ARCHIVE_NOTIFYLIST;
|
|
|
|
if( m_WaitForList )
|
|
|
|
flag |= L_ARCHIVE_WAITFORLIST;
|
|
|
|
if( vars )
|
|
|
|
flag |= L_ARCHIVE_VARLIST;
|
|
|
|
if( m_EndList )
|
|
|
|
flag |= L_ARCHIVE_ENDLIST;
|
|
|
|
}
|
|
|
|
|
|
|
|
arc.ArchiveByte( &flag );
|
|
|
|
|
|
|
|
// archive the notify list
|
|
|
|
if( flag & L_ARCHIVE_NOTIFYLIST )
|
|
|
|
{
|
|
|
|
if( arc.Loading() )
|
|
|
|
{
|
|
|
|
m_NotifyList = new con_set < const_str, ConList > ;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_NotifyList->Archive( arc );
|
|
|
|
}
|
|
|
|
|
|
|
|
// archive the waiting thread list
|
|
|
|
if( flag & L_ARCHIVE_WAITFORLIST )
|
|
|
|
{
|
|
|
|
if( arc.Loading() )
|
|
|
|
{
|
|
|
|
m_WaitForList = new con_set < const_str, ConList > ;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_WaitForList->Archive( arc );
|
|
|
|
}
|
|
|
|
|
|
|
|
// archive the variable list
|
|
|
|
if( flag & L_ARCHIVE_VARLIST )
|
|
|
|
{
|
|
|
|
if( arc.Loading() )
|
|
|
|
{
|
|
|
|
vars = new ScriptVariableList;
|
|
|
|
}
|
|
|
|
|
|
|
|
vars->Archive( arc );
|
|
|
|
}
|
|
|
|
|
|
|
|
// archive the end on event list
|
|
|
|
if( flag & L_ARCHIVE_ENDLIST )
|
|
|
|
{
|
|
|
|
if( arc.Loading() )
|
|
|
|
{
|
|
|
|
m_EndList = new con_set < const_str, ConList >;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_EndList->Archive( arc );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelEventsOfType
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelEventsOfType( Event *ev )
|
|
|
|
{
|
|
|
|
EventQueueNode *node;
|
|
|
|
EventQueueNode *next;
|
|
|
|
int eventnum;
|
|
|
|
|
|
|
|
node = Event::EventQueue.next;
|
|
|
|
|
|
|
|
eventnum = ev->eventnum;
|
|
|
|
while( node != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
next = node->next;
|
|
|
|
if( ( node->GetSourceObject() == this ) && ( node->event->eventnum == eventnum ) )
|
|
|
|
{
|
|
|
|
LL_Remove( node, next, prev );
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelEventsOfType
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelEventsOfType( Event &ev )
|
|
|
|
{
|
|
|
|
this->CancelEventsOfType( &ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelFlaggedEvents
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelFlaggedEvents( int flags )
|
|
|
|
{
|
|
|
|
EventQueueNode *node;
|
|
|
|
EventQueueNode *next;
|
|
|
|
|
|
|
|
node = Event::EventQueue.next;
|
|
|
|
|
|
|
|
while( node != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
next = node->next;
|
|
|
|
if( ( node->GetSourceObject() == this ) && ( node->flags & flags ) )
|
|
|
|
{
|
|
|
|
LL_Remove( node, next, prev );
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelPendingEvents
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelPendingEvents( void )
|
|
|
|
{
|
|
|
|
EventQueueNode *node;
|
|
|
|
EventQueueNode *next;
|
|
|
|
|
|
|
|
node = Event::EventQueue.next;
|
|
|
|
|
|
|
|
while( node != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
next = node->next;
|
|
|
|
if( node->GetSourceObject() == this )
|
|
|
|
{
|
|
|
|
LL_Remove( node, next, prev );
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventPending
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Listener::EventPending( Event &ev )
|
|
|
|
{
|
|
|
|
EventQueueNode *event;
|
|
|
|
int eventnum;
|
|
|
|
|
|
|
|
event = Event::EventQueue.next;
|
|
|
|
|
|
|
|
eventnum = ev.eventnum;
|
|
|
|
|
|
|
|
while( event != &Event::EventQueue )
|
|
|
|
{
|
2023-05-18 00:52:27 +02:00
|
|
|
if( ( event->GetSourceObject() == this ) && ( event->event->eventnum == ev.eventnum ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PostEventInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
EventQueueNode *Listener::PostEventInternal( Event *ev, float delay, int flags )
|
|
|
|
{
|
|
|
|
EventQueueNode *node;
|
|
|
|
EventQueueNode *i;
|
|
|
|
int inttime;
|
|
|
|
|
|
|
|
if( !classinfo()->responseLookup[ ev->eventnum ] )
|
|
|
|
{
|
|
|
|
if( !ev->eventnum )
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_DPrintf( "^~^~^ Failed execution of event '%s' for class '%s'\n", ev->name, getClassname() );
|
2016-03-27 11:49:47 +02:00
|
|
|
#else
|
2023-01-29 20:59:31 +01:00
|
|
|
EVENT_DPrintf( "^~^~^ Failed execution of event for class '%s'\n", getClassname() );
|
2016-03-27 11:49:47 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
delete ev;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
node = new EventQueueNode;
|
|
|
|
|
|
|
|
i = Event::EventQueue.next;
|
2023-01-29 22:57:44 +01:00
|
|
|
inttime = EVENT_msec + ( delay * 1000.0f + 0.5f );
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
while( i != &Event::EventQueue && inttime > i->inttime )
|
|
|
|
{
|
|
|
|
i = i->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->inttime = inttime;
|
|
|
|
node->event = ev;
|
|
|
|
node->flags = flags;
|
|
|
|
node->SetSourceObject( this );
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
node->name = ev->name;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LL_Add( i, node, next, prev );
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PostEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::PostEvent( Event *ev, float delay, int flags )
|
|
|
|
{
|
|
|
|
PostEventInternal( ev, delay, flags );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PostEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::PostEvent( const Event &ev, float delay, int flags )
|
|
|
|
{
|
|
|
|
Event *e = new Event( ev );
|
|
|
|
|
|
|
|
PostEventInternal( e, delay, flags );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PostponeAllEvents
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Listener::PostponeAllEvents( float time )
|
|
|
|
{
|
|
|
|
EventQueueNode *event;
|
|
|
|
EventQueueNode *node;
|
|
|
|
|
|
|
|
event = Event::EventQueue.next;
|
|
|
|
while( event != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
if( event->GetSourceObject() == this )
|
|
|
|
{
|
|
|
|
event->inttime += time * 1000.0f + 0.5f;
|
|
|
|
|
|
|
|
node = event->next;
|
|
|
|
while( ( node != &Event::EventQueue ) && ( event->inttime >= node->inttime ) )
|
|
|
|
{
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
LL_Remove( event, next, prev );
|
|
|
|
LL_Add( node, event, next, prev );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
PostponeEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Listener::PostponeEvent( Event &ev, float time )
|
|
|
|
{
|
|
|
|
EventQueueNode *event;
|
|
|
|
EventQueueNode *node;
|
|
|
|
int eventnum;
|
|
|
|
|
|
|
|
eventnum = ev.eventnum;
|
|
|
|
|
|
|
|
event = Event::EventQueue.next;
|
|
|
|
while( event != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
if( ( event->GetSourceObject() == this ) && ( event->event->eventnum == eventnum ) )
|
|
|
|
{
|
|
|
|
event->inttime += time * 1000.0f + 0.5f;
|
|
|
|
|
|
|
|
node = event->next;
|
|
|
|
while( ( node != &Event::EventQueue ) && ( event->inttime >= node->inttime ) )
|
|
|
|
{
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
LL_Remove( event, next, prev );
|
|
|
|
LL_Add( node, event, next, prev );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::ProcessEvent( Event *ev )
|
|
|
|
{
|
2023-08-19 21:00:04 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return ProcessScriptEvent(ev);
|
|
|
|
}
|
|
|
|
catch (ScriptException& exc)
|
|
|
|
{
|
|
|
|
ev->ErrorInternal(this, exc.string);
|
|
|
|
EVENT_DPrintf("%s\n", exc.string.c_str());
|
|
|
|
// at this point the event didn't get deleted
|
|
|
|
delete ev;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-08-19 21:00:04 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::ProcessEvent( Event &ev )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return ProcessScriptEvent(ev);
|
|
|
|
}
|
|
|
|
catch (ScriptException& exc)
|
|
|
|
{
|
|
|
|
ev.ErrorInternal(this, exc.string);
|
|
|
|
EVENT_DPrintf("%s\n", exc.string.c_str());
|
2016-03-27 11:49:47 +02:00
|
|
|
return false;
|
2023-08-19 21:00:04 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessEvent
|
|
|
|
=======================
|
|
|
|
*/
|
2023-08-19 21:00:04 +02:00
|
|
|
bool Listener::ProcessEvent( const Event &ev )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-08-19 21:00:04 +02:00
|
|
|
try
|
|
|
|
{
|
2023-08-19 21:21:41 +02:00
|
|
|
Event event(ev);
|
|
|
|
return ProcessScriptEvent(event);
|
2023-08-19 21:00:04 +02:00
|
|
|
}
|
|
|
|
catch (ScriptException& exc)
|
|
|
|
{
|
|
|
|
ev.ErrorInternal(this, exc.string);
|
|
|
|
EVENT_DPrintf("%s\n", exc.string.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessEventReturn
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptVariable& Listener::ProcessEventReturn( Event *ev )
|
|
|
|
{
|
|
|
|
ClassDef *c = classinfo();
|
|
|
|
ResponseDef<Class> *responses = NULL;
|
|
|
|
Response response = NULL;
|
|
|
|
static ScriptVariable m_Return;
|
|
|
|
|
|
|
|
if( !ev->eventnum )
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_Printf( "^~^~^ Failed execution of event '%s' for class '%s'\n", ev->name, c->classname );
|
2016-03-27 11:49:47 +02:00
|
|
|
#else
|
|
|
|
EVENT_Printf( "^~^~^ Failed execution of event for class '%s'\n", c->classname );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
delete ev;
|
|
|
|
return m_Return;
|
|
|
|
}
|
|
|
|
|
|
|
|
responses = c->responseLookup[ ev->eventnum ];
|
|
|
|
|
|
|
|
if( responses == NULL )
|
|
|
|
{
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_Printf( "^~^~^ Failed execution of command '%s' for class '%s'\n", Event::GetEventName( ev->eventnum ), c->classname );
|
2016-03-27 11:49:47 +02:00
|
|
|
delete ev;
|
|
|
|
return m_Return;
|
|
|
|
}
|
|
|
|
|
|
|
|
response = responses->response;
|
|
|
|
|
|
|
|
int previousArgs = ev->NumArgs();
|
|
|
|
|
|
|
|
if( response )
|
|
|
|
{
|
|
|
|
( this->*response )( ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( previousArgs != ev->NumArgs() && ev->NumArgs() != 0 )
|
|
|
|
{
|
|
|
|
m_Return = ev->GetValue( ev->NumArgs() );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete ev;
|
|
|
|
|
|
|
|
return m_Return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessScriptEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::ProcessScriptEvent( Event *ev )
|
|
|
|
{
|
|
|
|
bool result = ProcessScriptEvent( *ev );
|
|
|
|
|
|
|
|
delete ev;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessScriptEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::ProcessScriptEvent( Event &ev )
|
|
|
|
{
|
|
|
|
ClassDef *c = classinfo();
|
|
|
|
ResponseDef<Class> *responses = NULL;
|
|
|
|
Response response = NULL;
|
|
|
|
|
|
|
|
if( !ev.eventnum )
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
2023-09-07 18:05:49 +02:00
|
|
|
EVENT_Printf( "^~^~^ Failed execution of event '%s' for class '%s'\n", ev.name, c->classname );
|
2016-03-27 11:49:47 +02:00
|
|
|
#else
|
|
|
|
EVENT_Printf( "^~^~^ Failed execution of event for class '%s'\n", c->classname );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
responses = c->responseLookup[ ev.eventnum ];
|
|
|
|
|
|
|
|
if( responses == NULL )
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
response = responses->response;
|
|
|
|
|
|
|
|
if( response )
|
|
|
|
{
|
|
|
|
( this->*response )( &ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Listener::ProcessContainerEvent( const Container< Event * >& conev )
|
|
|
|
{
|
|
|
|
int num = conev.NumObjects();
|
|
|
|
|
|
|
|
for( int i = 1; i <= num; i++ )
|
|
|
|
{
|
|
|
|
ProcessEvent( conev.ObjectAt( i ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ProcessPendingEvents
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Listener::ProcessPendingEvents( void )
|
|
|
|
{
|
|
|
|
EventQueueNode *event;
|
|
|
|
qboolean processedEvents;
|
|
|
|
float t;
|
|
|
|
|
|
|
|
processedEvents = false;
|
|
|
|
|
2023-01-29 22:57:44 +01:00
|
|
|
t = EVENT_msec;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
event = Event::EventQueue.next;
|
|
|
|
while( event != &Event::EventQueue )
|
|
|
|
{
|
|
|
|
Listener *obj;
|
|
|
|
|
|
|
|
assert( event );
|
|
|
|
|
|
|
|
obj = event->GetSourceObject();
|
|
|
|
|
|
|
|
if( event->inttime > t )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( obj != this )
|
|
|
|
{
|
|
|
|
// traverse normally
|
|
|
|
event = event->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// the event is removed from its list and temporarily added to the active list
|
|
|
|
LL_Remove( event, next, prev );
|
|
|
|
|
|
|
|
// ProcessEvent will dispose of this event when it is done
|
|
|
|
obj->ProcessEvent( event->event );
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
// free up the node
|
|
|
|
delete event;
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
// start over, since can't guarantee that we didn't process any previous or following events
|
|
|
|
event = Event::EventQueue.next;
|
|
|
|
|
|
|
|
processedEvents = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return processedEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetScriptOwner
|
|
|
|
|
|
|
|
listener.owner
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
Listener *Listener::GetScriptOwner( void )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CreateVars
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CreateVars( void )
|
|
|
|
{
|
|
|
|
vars = new ScriptVariableList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ClearVars
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ClearVars( void )
|
|
|
|
{
|
|
|
|
if( vars )
|
|
|
|
{
|
|
|
|
delete vars;
|
|
|
|
CreateVars();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Vars
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptVariableList *Listener::Vars( void )
|
|
|
|
{
|
|
|
|
if( !vars ) {
|
|
|
|
CreateVars();
|
|
|
|
}
|
|
|
|
|
|
|
|
return vars;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
BroadcastEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::BroadcastEvent( str name, Event &event )
|
|
|
|
{
|
|
|
|
return BroadcastEvent( Director.AddString( name ), event );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
BroadcastEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::BroadcastEvent( const_str name, Event &event )
|
|
|
|
{
|
|
|
|
if( !m_NotifyList )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList *listeners = m_NotifyList->findKeyValue( name );
|
|
|
|
|
|
|
|
if( !listeners )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BroadcastEvent( event, listeners );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
BroadcastEvent
|
|
|
|
|
|
|
|
Broadcast an event to the notify list
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::BroadcastEvent( Event &event, ConList *listeners )
|
|
|
|
{
|
|
|
|
int num = listeners->NumObjects();
|
|
|
|
|
|
|
|
if( !num )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( num == 1 )
|
|
|
|
{
|
|
|
|
Listener *listener = listeners->ObjectAt( 1 );
|
|
|
|
|
|
|
|
if( listener )
|
|
|
|
{
|
|
|
|
listener->ProcessEvent( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList listenersCopy = *listeners;
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
for( int i = listenersCopy.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = listenersCopy.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener )
|
|
|
|
{
|
|
|
|
listener->ProcessEvent( event );
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelWaiting
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelWaiting( str name )
|
|
|
|
{
|
|
|
|
CancelWaiting( Director.AddString( name ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelWaiting
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelWaiting( const_str name )
|
|
|
|
{
|
|
|
|
if( !m_WaitForList )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList *list = m_WaitForList->findKeyValue( name );
|
|
|
|
ConList stoppedListeners;
|
|
|
|
|
|
|
|
if( !list )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CancelWaitingSources( name, *list, stoppedListeners );
|
|
|
|
|
|
|
|
m_WaitForList->remove( name );
|
|
|
|
|
|
|
|
if( m_WaitForList->isEmpty() )
|
|
|
|
{
|
|
|
|
delete m_WaitForList;
|
|
|
|
m_WaitForList = NULL;
|
|
|
|
|
|
|
|
if( !DisableListenerNotify )
|
|
|
|
{
|
|
|
|
StoppedWaitFor( name, false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-29 23:43:30 +02:00
|
|
|
for (int i = stoppedListeners.NumObjects(); i > 0; i--)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2019-06-29 23:43:30 +02:00
|
|
|
Listener *listener = stoppedListeners.ObjectAt(i);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2019-06-29 23:43:30 +02:00
|
|
|
if (listener)
|
|
|
|
{
|
|
|
|
if (!DisableListenerNotify)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
listener->StoppedNotify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelWaitingAll
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelWaitingAll()
|
|
|
|
{
|
|
|
|
CancelWaiting( 0 );
|
|
|
|
|
|
|
|
if( !m_WaitForList )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
con_set_enum< const_str, ConList > en = *m_WaitForList;
|
2023-08-19 02:56:51 +02:00
|
|
|
con_set< const_str, ConList >::Entry *e;
|
2016-03-27 11:49:47 +02:00
|
|
|
ConList stoppedListeners;
|
|
|
|
|
|
|
|
for( e = en.NextElement(); e != NULL; e = en.NextElement() )
|
|
|
|
{
|
|
|
|
CancelWaitingSources( e->key, e->value, stoppedListeners );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete m_WaitForList;
|
|
|
|
m_WaitForList = NULL;
|
|
|
|
|
|
|
|
if( !DisableListenerNotify )
|
2019-06-29 23:43:30 +02:00
|
|
|
StoppedWaitFor(STRING_NULL, false );
|
|
|
|
|
|
|
|
for (int i = stoppedListeners.NumObjects(); i > 0; i--)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2019-06-29 23:43:30 +02:00
|
|
|
Listener *listener = stoppedListeners.ObjectAt(i);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2019-06-29 23:43:30 +02:00
|
|
|
if (listener)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2019-06-29 23:43:30 +02:00
|
|
|
if (!DisableListenerNotify)
|
2016-03-27 11:49:47 +02:00
|
|
|
listener->StoppedNotify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelWaitingSources
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelWaitingSources( const_str name, ConList &listeners, ConList &stoppedListeners )
|
|
|
|
{
|
|
|
|
for( int i = listeners.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = listeners.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener && listener->UnregisterSource( name, this ) )
|
|
|
|
{
|
|
|
|
stoppedListeners.AddObject( listener );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Notify
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Notify( const char *name )
|
|
|
|
{
|
|
|
|
Unregister( name );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
StoppedNotify
|
|
|
|
|
|
|
|
Called when stopped notifying for a listener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::StoppedNotify( void )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
StartedWaitFor
|
|
|
|
|
|
|
|
Called when started waiting for a listener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::StartedWaitFor( void )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
StoppedWaitFor
|
|
|
|
|
|
|
|
Called when stopped wait for a listener
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::StoppedWaitFor( const_str name, bool bDeleting )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EndOn
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EndOn( str name, Listener *listener )
|
|
|
|
{
|
|
|
|
EndOn( Director.AddString( name ), listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EndOn
|
|
|
|
|
|
|
|
Removes the specified listener when notifying
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EndOn( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( !m_EndList )
|
|
|
|
{
|
|
|
|
m_EndList = new con_set < const_str, ConList >;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList& list = m_EndList->addKeyValue( name );
|
|
|
|
|
|
|
|
list.AddUniqueObject( listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Register
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Register( str name, Listener *listener )
|
|
|
|
{
|
|
|
|
Register( Director.AddString( name ), listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Register
|
|
|
|
|
|
|
|
Registers a listener, that will be notified with Unregister
|
|
|
|
Listener is usually a ScriptThread
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Register( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
RegisterSource( name, listener );
|
|
|
|
listener->RegisterTarget( name, this );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
RegisterSource
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::RegisterSource( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( !m_NotifyList )
|
|
|
|
{
|
|
|
|
m_NotifyList = new con_set < const_str, ConList >;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList& list = m_NotifyList->addKeyValue( name );
|
|
|
|
|
|
|
|
list.AddObject( listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
RegisterTarget
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::RegisterTarget( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( !m_WaitForList )
|
|
|
|
{
|
|
|
|
StartedWaitFor();
|
|
|
|
m_WaitForList = new con_set < const_str, ConList >;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList& list = m_WaitForList->addKeyValue( name );
|
|
|
|
|
|
|
|
list.AddObject( listener );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Unregister
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Unregister( str name )
|
|
|
|
{
|
|
|
|
Unregister( Director.AddString( name ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Unregister
|
|
|
|
|
|
|
|
Unregister listeners from the specified event
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Unregister( const_str name )
|
|
|
|
{
|
|
|
|
if( m_EndList )
|
|
|
|
{
|
|
|
|
ConList *list = m_EndList->findKeyValue( name );
|
|
|
|
bool bDeleteSelf = false;
|
|
|
|
|
|
|
|
if( list )
|
|
|
|
{
|
|
|
|
ConList listeners = *list;
|
|
|
|
|
|
|
|
m_EndList->remove( name );
|
|
|
|
|
|
|
|
if( m_EndList->isEmpty() )
|
|
|
|
{
|
|
|
|
delete m_EndList;
|
|
|
|
m_EndList = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = listeners.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = listeners.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener )
|
|
|
|
{
|
2023-08-10 12:08:53 +02:00
|
|
|
if( listener == this && ( bDeleteSelf ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( listener == this )
|
|
|
|
{
|
|
|
|
bDeleteSelf = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete listener;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bDeleteSelf )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !m_NotifyList )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList *list = m_NotifyList->findKeyValue( name );
|
|
|
|
ConList stoppedListeners;
|
|
|
|
Container< const_str > stoppedNames;
|
|
|
|
|
|
|
|
if( !list )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnregisterTargets( name, *list, stoppedListeners, stoppedNames );
|
|
|
|
|
|
|
|
m_NotifyList->remove( name );
|
|
|
|
|
|
|
|
if( m_NotifyList->isEmpty() )
|
|
|
|
{
|
|
|
|
delete m_NotifyList;
|
|
|
|
m_NotifyList = NULL;
|
|
|
|
|
|
|
|
if( !DisableListenerNotify )
|
|
|
|
{
|
|
|
|
StoppedNotify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !DisableListenerNotify )
|
|
|
|
{
|
|
|
|
for( int i = stoppedListeners.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = stoppedListeners.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener )
|
|
|
|
{
|
|
|
|
listener->StoppedWaitFor( name, false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Unregister
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Unregister( str name, Listener *listener )
|
|
|
|
{
|
|
|
|
Unregister( Director.AddString( name ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
Unregister
|
|
|
|
|
|
|
|
Unregister a specified listener with the specified label
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::Unregister( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( UnregisterSource( name, listener ) )
|
|
|
|
{
|
|
|
|
if( !DisableListenerNotify ) {
|
|
|
|
StoppedNotify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( listener->UnregisterTarget( name, this ) )
|
|
|
|
{
|
|
|
|
if( !DisableListenerNotify ) {
|
|
|
|
listener->StoppedWaitFor( name, false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
UnregisterAll
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::UnregisterAll( void )
|
|
|
|
{
|
|
|
|
Unregister( 0 );
|
|
|
|
|
|
|
|
if( m_EndList )
|
|
|
|
{
|
|
|
|
delete m_EndList;
|
|
|
|
m_EndList = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !m_NotifyList )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
con_set_enum < const_str, ConList > en = *m_NotifyList;
|
2023-08-19 02:56:51 +02:00
|
|
|
con_set< const_str, ConList >::Entry *e;
|
2016-03-27 11:49:47 +02:00
|
|
|
ConList stoppedListeners;
|
|
|
|
Container< const_str > stoppedNames;
|
|
|
|
|
|
|
|
en = *m_NotifyList;
|
|
|
|
|
|
|
|
for( e = en.NextElement(); e != NULL; e = en.NextElement() )
|
|
|
|
{
|
|
|
|
UnregisterTargets( e->key, e->value, stoppedListeners, stoppedNames );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete m_NotifyList;
|
|
|
|
m_NotifyList = NULL;
|
|
|
|
|
|
|
|
if( !DisableListenerNotify ) {
|
|
|
|
StoppedNotify();
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = stoppedListeners.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = stoppedListeners.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener )
|
|
|
|
{
|
|
|
|
if( !DisableListenerNotify ) {
|
|
|
|
listener->StoppedWaitFor( stoppedNames.ObjectAt( i ), true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
UnregisterSource
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::UnregisterSource( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( !m_NotifyList )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList *list = m_NotifyList->findKeyValue( name );
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
if( !list )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = list->NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
if( list->ObjectAt( i ) == listener )
|
|
|
|
{
|
|
|
|
list->RemoveObjectAt( i );
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( list->NumObjects() == 0 )
|
|
|
|
{
|
|
|
|
m_NotifyList->remove( name );
|
|
|
|
|
|
|
|
if( m_NotifyList->isEmpty() )
|
|
|
|
{
|
|
|
|
delete m_NotifyList;
|
|
|
|
m_NotifyList = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
UnregisterTarget
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::UnregisterTarget( const_str name, Listener *listener )
|
|
|
|
{
|
|
|
|
if( !m_WaitForList )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConList *list = m_WaitForList->findKeyValue( name );
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
if( !list )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = list->NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
if( list->ObjectAt( i ) == listener )
|
|
|
|
{
|
|
|
|
list->RemoveObjectAt( i );
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( list->NumObjects() == 0 )
|
|
|
|
{
|
|
|
|
m_WaitForList->remove( name );
|
|
|
|
|
|
|
|
if( m_WaitForList->isEmpty() )
|
|
|
|
{
|
|
|
|
delete m_WaitForList;
|
|
|
|
m_WaitForList = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
UnregisterTargets
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::UnregisterTargets( const_str name, ConList &listeners, ConList &stoppedListeners, Container< const_str > &stoppedNames )
|
|
|
|
{
|
|
|
|
for( int i = listeners.NumObjects(); i > 0; i-- )
|
|
|
|
{
|
|
|
|
Listener *listener = listeners.ObjectAt( i );
|
|
|
|
|
|
|
|
if( listener && listener->UnregisterTarget( name, this ) )
|
|
|
|
{
|
|
|
|
stoppedListeners.AddObject( listener );
|
|
|
|
stoppedNames.AddObject( name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
AbortRegistration
|
|
|
|
|
|
|
|
Abort the listener from registration of the specified label
|
|
|
|
Doesn't notify
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::AbortRegistration( const_str name, Listener *l )
|
|
|
|
{
|
|
|
|
UnregisterSource( name, l );
|
|
|
|
l->UnregisterTarget( name, this );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
RegisterSize
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Listener::RegisterSize( str name ) const
|
|
|
|
{
|
|
|
|
return RegisterSize( Director.AddString( name ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
RegisterSize
|
|
|
|
|
|
|
|
Returns how many listeners in the notify list
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Listener::RegisterSize( const_str name ) const
|
|
|
|
{
|
|
|
|
ConList *listeners;
|
|
|
|
|
|
|
|
if( !m_NotifyList ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
listeners = m_NotifyList->findKeyValue( name );
|
|
|
|
|
|
|
|
// return the number of listeners waiting for this listener
|
|
|
|
if( listeners )
|
|
|
|
{
|
|
|
|
return listeners->NumObjects();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitingSize
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Listener::WaitingSize( str name ) const
|
|
|
|
{
|
|
|
|
return WaitingSize( Director.AddString( name ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitingSize
|
|
|
|
|
|
|
|
Returns how many listeners in the wait list
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Listener::WaitingSize( const_str name ) const
|
|
|
|
{
|
|
|
|
ConList *listeners;
|
|
|
|
|
|
|
|
if( !m_WaitForList ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
listeners = m_WaitForList->findKeyValue( name );
|
|
|
|
|
|
|
|
// return the number of listeners this listener is waiting for
|
|
|
|
if( listeners )
|
|
|
|
{
|
|
|
|
return listeners->NumObjects();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTillDisabled
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::WaitTillDisabled( str s )
|
|
|
|
{
|
|
|
|
return WaitTillDisabled( Director.AddString( s ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTillDisabled
|
|
|
|
|
|
|
|
Returns true if the specified waittill is disabled
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
bool Listener::WaitTillDisabled( const_str s )
|
|
|
|
{
|
2023-08-19 18:21:32 +02:00
|
|
|
return !WaitTillAllowed(s);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetFlags
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
int Listener::GetFlags( Event *event ) const
|
|
|
|
{
|
|
|
|
return classinfo()->GetFlags( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ValidEvent
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
qboolean Listener::ValidEvent( str name ) const
|
|
|
|
{
|
|
|
|
int num;
|
|
|
|
EventDef *def;
|
|
|
|
|
|
|
|
num = Event::FindEventNum( name );
|
|
|
|
if( !num )
|
|
|
|
return qfalse;
|
|
|
|
|
|
|
|
def = classinfo()->GetDef( num );
|
|
|
|
if( !def )
|
|
|
|
return qfalse;
|
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================
|
|
|
|
// Listener's events
|
|
|
|
//==========================
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventDelete
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventDelete( Event *ev )
|
|
|
|
{
|
|
|
|
if( ev->NumArgs() )
|
|
|
|
{
|
|
|
|
ScriptError( "Arguments not allowed." );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventInheritsFrom
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventInheritsFrom( Event *ev )
|
|
|
|
{
|
|
|
|
ev->AddInteger( inheritsFrom( ev->GetString( 1 ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventIsInheritedBy
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventIsInheritedBy( Event *ev )
|
|
|
|
{
|
|
|
|
ev->AddInteger( isInheritedBy( ev->GetString( 1 ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
GetClassname
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::GetClassname( Event *ev )
|
|
|
|
{
|
|
|
|
ev->AddString( getClassname() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CommandDelay
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CommandDelay( Event *ev )
|
|
|
|
{
|
|
|
|
if( ev->NumArgs() < 2 )
|
|
|
|
{
|
|
|
|
ScriptError( "Not enough arguments." );
|
|
|
|
}
|
|
|
|
|
|
|
|
Event *e = new Event( ev->GetString( 2 ) );
|
|
|
|
|
|
|
|
for( int i = 3; i <= ev->NumArgs(); i++ )
|
|
|
|
{
|
|
|
|
e->AddValue( ev->GetValue( i ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
PostEvent( e, ev->GetFloat( 1 ) );
|
|
|
|
}
|
|
|
|
|
2023-05-29 01:33:07 +02:00
|
|
|
#ifdef WITH_SCRIPT_ENGINE
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CancelFor
|
|
|
|
|
|
|
|
Removes all listeners in the notify list
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CancelFor( Event *ev )
|
|
|
|
{
|
|
|
|
BroadcastEvent( ev->GetConstString( 1 ), EV_Remove );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventDelayThrow
|
|
|
|
|
|
|
|
Same as EventThrow
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventDelayThrow( Event *ev )
|
|
|
|
{
|
|
|
|
BroadcastEvent( 0, *ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventEndOn
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventEndOn( Event *ev )
|
|
|
|
{
|
|
|
|
const_str name = ev->GetConstString( 1 );
|
|
|
|
|
|
|
|
if( Director.CurrentThread() == this )
|
|
|
|
{
|
|
|
|
ScriptError( "cannot end for the current thread!" );
|
|
|
|
}
|
|
|
|
|
|
|
|
EndOn( name, Director.CurrentThread() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventGetOwner
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventGetOwner( Event *ev )
|
|
|
|
{
|
|
|
|
ev->AddListener( GetScriptOwner() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventNotify
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventNotify( Event *ev )
|
|
|
|
{
|
|
|
|
str name = ev->GetString( 1 );
|
|
|
|
|
|
|
|
Notify( name );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventThrow
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventThrow( Event *ev )
|
|
|
|
{
|
|
|
|
BroadcastEvent( 0, *ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
EventUnregister
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::EventUnregister( Event *ev )
|
|
|
|
{
|
|
|
|
Unregister( ev->GetConstString( 1 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTill
|
|
|
|
|
|
|
|
Wait until event of type name
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitTill( Event *ev )
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
|
|
|
|
if( Director.CurrentThread() == this )
|
|
|
|
{
|
|
|
|
ScriptError( "cannot waittill on the current thread!" );
|
|
|
|
}
|
|
|
|
|
|
|
|
name = ev->GetConstString( 1 );
|
|
|
|
|
2023-08-19 18:21:32 +02:00
|
|
|
if( !WaitTillAllowed( name ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
ScriptError( "invalid waittill %s for '%s'", Director.GetString( name ).c_str(), getClassname() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Register( name, Director.CurrentThread() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTillTimeout
|
|
|
|
|
|
|
|
Wait until event of type name with a timeout time
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitTillTimeout( Event *ev )
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
float timeout_time;
|
|
|
|
|
|
|
|
if( Director.CurrentThread() == this )
|
|
|
|
{
|
|
|
|
ScriptError( "cannot waittill on the current thread!" );
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout_time = ev->GetFloat( 1 );
|
|
|
|
name = ev->GetConstString( 2 );
|
2023-08-20 01:46:38 +02:00
|
|
|
|
|
|
|
if( !WaitTillAllowed( name ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
ScriptError( "invalid waittill %s for '%s'", Director.GetString( name ).c_str(), getClassname() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Register( name, Director.CurrentThread() );
|
|
|
|
Director.CurrentThread()->PostEvent( EV_ScriptThread_CancelWaiting, timeout_time );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTillAny
|
|
|
|
|
|
|
|
Wait until any event of type name
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitTillAny( Event *ev )
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
|
|
|
|
if( Director.CurrentThread() == this )
|
|
|
|
{
|
|
|
|
ScriptError( "cannot waittill any on the current thread!" );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int i = 1; i <= ev->NumArgs(); i++ )
|
|
|
|
{
|
|
|
|
name = ev->GetConstString( i );
|
2023-08-20 01:46:38 +02:00
|
|
|
|
|
|
|
if( !WaitTillAllowed( name ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
ScriptError( "invalid waittill %s for '%s'", Director.GetString( name ).c_str(), getClassname() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Register( name, Director.CurrentThread() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitTillAnyTimeout
|
|
|
|
|
|
|
|
Wait until any event of type name with a timeout time
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitTillAnyTimeout( Event *ev )
|
|
|
|
{
|
|
|
|
const_str name;
|
|
|
|
float timeout_time;
|
|
|
|
|
|
|
|
if( Director.CurrentThread() == this )
|
|
|
|
{
|
|
|
|
ScriptError( "cannot waittill any on the current thread!" );
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout_time = ev->GetFloat( 1 );
|
|
|
|
|
|
|
|
for( int i = 1; i <= ev->NumArgs(); i++ )
|
|
|
|
{
|
|
|
|
name = ev->GetConstString( i );
|
2023-08-20 01:46:38 +02:00
|
|
|
|
|
|
|
if( !WaitTillAllowed( name ) )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
ScriptError( "invalid waittill %s for '%s'", Director.GetString( name ).c_str(), getClassname() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Register( name, Director.CurrentThread() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Director.CurrentThread()->PostEvent( EV_ScriptThread_CancelWaiting, timeout_time );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteScriptInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteScriptInternal( Event *ev, ScriptVariable& returnValue )
|
|
|
|
{
|
|
|
|
SafePtr< ScriptThread > thread = CreateScriptInternal( ev->GetValue( 1 ) );
|
|
|
|
ScriptThread *currentThread;
|
|
|
|
bool fReturn = returnValue.GetType() != VARIABLE_NONE;
|
|
|
|
|
|
|
|
thread->ScriptExecute( &ev->data[ 1 ], ev->dataSize - 1, returnValue );
|
|
|
|
|
|
|
|
currentThread = Director.m_CurrentThread;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteThreadInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteThreadInternal( Event *ev, ScriptVariable& returnValue )
|
|
|
|
{
|
|
|
|
SafePtr< ScriptThread > thread = CreateThreadInternal( ev->GetValue( 1 ) );
|
|
|
|
ScriptThread *currentThread;
|
|
|
|
bool fReturn = returnValue.GetType() != VARIABLE_NONE;
|
|
|
|
|
|
|
|
thread->ScriptExecute( &ev->data[ 1 ], ev->dataSize - 1, returnValue );
|
|
|
|
|
|
|
|
currentThread = Director.m_CurrentThread;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitExecuteScriptInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitExecuteScriptInternal( Event *ev, ScriptVariable& returnValue )
|
|
|
|
{
|
|
|
|
ScriptThread *thread = CreateScriptInternal( ev->GetValue( 1 ) );
|
|
|
|
|
|
|
|
thread->GetScriptClass()->Register( 0, Director.CurrentThread() );
|
|
|
|
|
|
|
|
thread->ScriptExecute( &ev->data[ 1 ], ev->dataSize - 1, returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitExecuteThreadInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitExecuteThreadInternal( Event *ev, ScriptVariable& returnValue )
|
|
|
|
{
|
|
|
|
ScriptThread *thread = CreateThreadInternal( ev->GetValue( 1 ) );
|
|
|
|
|
|
|
|
thread->GetScriptClass()->Register( 0, Director.CurrentThread() );
|
|
|
|
|
|
|
|
thread->ScriptExecute( &ev->data[ 1 ], ev->dataSize - 1, returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CreateScriptInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptThread *Listener::CreateScriptInternal( const ScriptVariable& label )
|
|
|
|
{
|
|
|
|
GameScript *scr;
|
|
|
|
ScriptThread *thread = NULL;
|
|
|
|
|
|
|
|
if( label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
{
|
|
|
|
if( label.GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
thread = Director.CreateScriptThread( Director.GetGameScript( label.stringValue() ), this, "" );
|
|
|
|
else
|
|
|
|
thread = Director.CreateScriptThread( Director.GetGameScript( label.constStringValue() ), this, "" );
|
|
|
|
}
|
|
|
|
else if( label.GetType() == VARIABLE_CONSTARRAY && label.arraysize() > 1 )
|
|
|
|
{
|
|
|
|
ScriptVariable *script = label[ 1 ];
|
|
|
|
ScriptVariable *labelname = label[ 2 ];
|
|
|
|
|
|
|
|
if( script->GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
scr = Director.GetGameScript( script->constStringValue() );
|
|
|
|
else
|
|
|
|
scr = Director.GetGameScript( script->stringValue() );
|
|
|
|
|
|
|
|
if( labelname->GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
thread = Director.CreateScriptThread( scr, this, labelname->constStringValue() );
|
|
|
|
else
|
|
|
|
thread = Director.CreateScriptThread( scr, this, labelname->stringValue() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScriptError( "Listener::CreateScriptInternal: bad label type '%s'", label.GetTypeName() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CreateThreadInternal
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
ScriptThread *Listener::CreateThreadInternal( const ScriptVariable& label )
|
|
|
|
{
|
|
|
|
GameScript *scr;
|
|
|
|
ScriptThread *thread = NULL;
|
|
|
|
|
|
|
|
if( label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
{
|
|
|
|
ScriptClass *scriptClass = Director.CurrentScriptClass();
|
|
|
|
scr = scriptClass->GetScript();
|
|
|
|
|
|
|
|
if( label.GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
thread = Director.CreateScriptThread( scr, this, label.constStringValue() );
|
|
|
|
else
|
|
|
|
thread = Director.CreateScriptThread( scr, this, label.stringValue() );
|
|
|
|
}
|
|
|
|
else if( label.GetType() == VARIABLE_CONSTARRAY && label.arraysize() > 1 )
|
|
|
|
{
|
|
|
|
ScriptVariable *script = label[ 1 ];
|
|
|
|
ScriptVariable *labelname = label[ 2 ];
|
|
|
|
|
|
|
|
if( script->GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
scr = Director.GetGameScript( script->constStringValue() );
|
|
|
|
else
|
|
|
|
scr = Director.GetGameScript( script->stringValue() );
|
|
|
|
|
|
|
|
if( labelname->GetType() == VARIABLE_CONSTSTRING )
|
|
|
|
thread = Director.CreateScriptThread( scr, this, labelname->constStringValue() );
|
|
|
|
else
|
|
|
|
thread = Director.CreateScriptThread( scr, this, labelname->stringValue() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScriptError( "ScriptClass::CreateThreadInternal: bad argument format" );
|
|
|
|
}
|
|
|
|
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CreateReturnThread
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CreateReturnThread( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
returnValue.newPointer();
|
|
|
|
|
|
|
|
ExecuteThreadInternal( ev, returnValue );
|
|
|
|
|
|
|
|
ev->AddValue( returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
CreateThread
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::CreateThread( Event *ev )
|
|
|
|
{
|
2023-01-30 00:50:21 +01:00
|
|
|
ScriptVariable returnValue;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-01-30 00:50:21 +01:00
|
|
|
ExecuteThreadInternal(ev, returnValue);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteReturnScript
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteReturnScript( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
returnValue.newPointer();
|
|
|
|
|
|
|
|
ExecuteScriptInternal( ev, returnValue );
|
|
|
|
|
|
|
|
ev->AddValue( returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteScript
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteScript( Event *ev )
|
|
|
|
{
|
2023-01-30 00:50:21 +01:00
|
|
|
ScriptVariable returnValue;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-01-30 00:50:21 +01:00
|
|
|
ExecuteScriptInternal(ev, returnValue);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitCreateReturnThread
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitCreateReturnThread( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
returnValue.newPointer();
|
|
|
|
|
|
|
|
WaitExecuteThreadInternal( ev, returnValue );
|
|
|
|
|
|
|
|
ev->AddValue( returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitCreateThread
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitCreateThread( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
WaitExecuteThreadInternal( ev, returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitExecuteReturnScript
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitExecuteReturnScript( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
returnValue.newPointer();
|
|
|
|
|
|
|
|
WaitExecuteScriptInternal( ev, returnValue );
|
|
|
|
|
|
|
|
ev->AddValue( returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
WaitExecuteScript
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::WaitExecuteScript( Event *ev )
|
|
|
|
{
|
|
|
|
ScriptVariable returnValue;
|
|
|
|
|
|
|
|
WaitExecuteScriptInternal( ev, returnValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteThread
|
|
|
|
|
|
|
|
Execute a thread with optionally parameters
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteThread( str scriptName, str labelName, Event *params )
|
|
|
|
{
|
|
|
|
ScriptThread *thread = Director.CreateThread( scriptName, labelName, this );
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if( !thread )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
thread->Execute( params );
|
|
|
|
}
|
|
|
|
catch( ScriptException& exc )
|
|
|
|
{
|
2023-01-29 20:59:31 +01:00
|
|
|
EVENT_DPrintf( "Listener::ExecuteThread: %s\n", exc.string.c_str() );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
ExecuteThread
|
|
|
|
|
|
|
|
Execute a thread with optionally parameters
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void Listener::ExecuteThread( str scriptName, str labelName, Event& params )
|
|
|
|
{
|
|
|
|
ScriptThread *thread = Director.CreateThread( scriptName, labelName, this );
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if( !thread )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
thread->Execute( params );
|
|
|
|
}
|
|
|
|
catch( ScriptException& exc )
|
|
|
|
{
|
2023-01-29 20:59:31 +01:00
|
|
|
EVENT_DPrintf( "Listener::ExecuteThread: %s\n", exc.string.c_str() );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
command_t::command_t()
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-09-07 18:05:49 +02:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-09-07 18:05:49 +02:00
|
|
|
command_t::command_t(const char* name, byte t)
|
|
|
|
: command(name)
|
|
|
|
, type(t)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|