2023-01-30 18:20:50 +01:00
|
|
|
#include "scriptclass.h"
|
2023-06-17 01:24:20 +02:00
|
|
|
#include "../fgame/scriptmaster.h"
|
|
|
|
#include "../fgame/scriptthread.h"
|
2023-04-29 21:56:38 +02:00
|
|
|
#include "scriptexception.h"
|
2023-01-30 18:20:50 +01:00
|
|
|
|
|
|
|
//====================
|
|
|
|
// ScriptClass
|
|
|
|
//====================
|
|
|
|
|
|
|
|
MEM_BlockAlloc<ScriptClass> ScriptClass_allocator;
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
CLASS_DECLARATION(Listener, ScriptClass, NULL) {
|
|
|
|
{NULL, NULL}
|
2023-01-30 18:20:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
new ScriptClass
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
void *ScriptClass::operator new(size_t size)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return ScriptClass_allocator.Alloc();
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
delete ptr
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
void ScriptClass::operator delete(void *ptr)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
ScriptClass_allocator.Free(ptr);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
ScriptClass
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
ScriptClass::ScriptClass(GameScript *gameScript, Listener *self)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
m_Self = self;
|
|
|
|
m_Script = gameScript;
|
|
|
|
m_Threads = NULL;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
ScriptClass
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
ScriptClass::ScriptClass()
|
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
m_Self = NULL;
|
|
|
|
m_Script = NULL;
|
|
|
|
m_Threads = NULL;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
~ScriptClass
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
ScriptClass::~ScriptClass()
|
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
if (m_Script == NULL) {
|
|
|
|
throw ScriptException("Attempting to delete dead class.");
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
KillThreads();
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
if (!m_Script->m_Filename) {
|
|
|
|
// This is a temporary gamescript
|
|
|
|
delete m_Script;
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
Archive
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
void ScriptClass::Archive(Archiver& arc) {}
|
2023-01-30 18:20:50 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
ArchiveInternal
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void ScriptClass::ArchiveInternal(Archiver& arc)
|
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
Listener::Archive(arc);
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
arc.ArchiveObjectPosition(this);
|
|
|
|
arc.ArchiveSafePointer(&m_Self);
|
|
|
|
GameScript::Archive(arc, m_Script);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
ArchiveScript
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
void ScriptClass::ArchiveScript(Archiver& arc, ScriptClass **obj)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
ScriptClass *scr;
|
|
|
|
ScriptVM *m_current;
|
|
|
|
ScriptThread *m_thread;
|
|
|
|
int num;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (arc.Saving()) {
|
|
|
|
scr = *obj;
|
|
|
|
scr->ArchiveInternal(arc);
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
for (m_current = scr->m_Threads; m_current != NULL; m_current = m_current->next) {
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
|
|
|
|
arc.ArchiveInteger(&num);
|
|
|
|
|
|
|
|
for (m_current = scr->m_Threads; m_current != NULL; m_current = m_current->next) {
|
|
|
|
m_current->m_Thread->ArchiveInternal(arc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scr = new ScriptClass();
|
|
|
|
scr->ArchiveInternal(arc);
|
|
|
|
|
|
|
|
arc.ArchiveInteger(&num);
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
m_thread = new ScriptThread(scr, NULL);
|
|
|
|
m_thread->ArchiveInternal(arc);
|
|
|
|
}
|
|
|
|
|
|
|
|
*obj = scr;
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
ArchiveCodePos
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
void ScriptClass::ArchiveCodePos(Archiver& arc, unsigned char **codePos)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
m_Script->ArchiveCodePos(arc, codePos);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
CreateThreadInternal
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
ScriptThread *ScriptClass::CreateThreadInternal(const ScriptVariable& label)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
GameScript *scr;
|
|
|
|
ScriptThread *thread = NULL;
|
|
|
|
|
|
|
|
if (label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING) {
|
|
|
|
if (label.GetType() == VARIABLE_CONSTSTRING) {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(this, label.constStringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
} else {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(this, label.stringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
|
|
|
} 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) {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(scr, GetSelf(), labelname->constStringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
} else {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(scr, GetSelf(), labelname->stringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ScriptError("ScriptClass::CreateThreadInternal: bad argument format");
|
|
|
|
}
|
|
|
|
|
|
|
|
return thread;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
CreateScriptInternal
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
ScriptThread *ScriptClass::CreateScriptInternal(const ScriptVariable& label)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
GameScript *scr;
|
|
|
|
ScriptThread *thread = NULL;
|
|
|
|
|
|
|
|
if (label.GetType() == VARIABLE_STRING || label.GetType() == VARIABLE_CONSTSTRING) {
|
|
|
|
if (label.GetType() == VARIABLE_CONSTSTRING) {
|
2023-10-26 20:08:09 +02:00
|
|
|
scr = Director.GetGameScript(label.constStringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
} else {
|
2023-10-26 20:08:09 +02:00
|
|
|
scr = Director.GetGameScript(label.stringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(scr, GetSelf(), "");
|
2023-07-05 21:23:39 +02:00
|
|
|
} 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) {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(scr, GetSelf(), labelname->constStringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
} else {
|
2023-10-26 20:08:09 +02:00
|
|
|
thread = Director.CreateScriptThread(scr, GetSelf(), labelname->stringValue());
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ScriptError("ScriptClass::CreateScriptInternal: bad label type '%s'", label.GetTypeName());
|
|
|
|
}
|
|
|
|
|
|
|
|
return thread;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
AddThread
|
|
|
|
====================
|
|
|
|
*/
|
2023-10-26 20:18:50 +02:00
|
|
|
void ScriptClass::AddThread(ScriptVM *thread)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-10-26 20:18:50 +02:00
|
|
|
thread->next = m_Threads;
|
|
|
|
m_Threads = thread;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
KillThreads
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void ScriptClass::KillThreads()
|
|
|
|
{
|
2023-10-26 20:08:09 +02:00
|
|
|
ScriptVM *thread;
|
|
|
|
ScriptVM *next;
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
if (!m_Threads) {
|
|
|
|
return;
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-10-26 20:08:09 +02:00
|
|
|
for (thread = m_Threads; thread; thread = next) {
|
|
|
|
if (g_scripttrace->integer && thread->CanScriptTracePrint()) {
|
|
|
|
gi.DPrintf2("---KILLTHREADS THREAD: %p\n", thread);
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-10-26 20:08:09 +02:00
|
|
|
thread->m_ScriptClass = NULL;
|
|
|
|
next = thread->next;
|
|
|
|
delete thread->m_Thread;
|
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
m_Threads = NULL;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
RemoveThread
|
|
|
|
====================
|
|
|
|
*/
|
2023-10-26 20:18:50 +02:00
|
|
|
void ScriptClass::RemoveThread(ScriptVM *thread)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-10-26 20:18:50 +02:00
|
|
|
ScriptVM *current;
|
|
|
|
ScriptVM *next;
|
|
|
|
|
|
|
|
if (m_Threads == thread) {
|
|
|
|
m_Threads = thread->next;
|
2023-07-05 21:23:39 +02:00
|
|
|
|
2023-10-26 20:18:50 +02:00
|
|
|
if (!m_Threads) {
|
2023-07-05 21:23:39 +02:00
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
} else {
|
2023-10-26 20:18:50 +02:00
|
|
|
next = m_Threads;
|
|
|
|
for (current = m_Threads->next; current != thread; current = current->next) {
|
|
|
|
next = current;
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
|
|
|
|
2023-10-26 20:18:50 +02:00
|
|
|
next->next = current->next;
|
2023-07-05 21:23:39 +02:00
|
|
|
}
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
Filename
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
str ScriptClass::Filename()
|
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script->Filename();
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
FindLabel
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
unsigned char *ScriptClass::FindLabel(str label)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script->m_State.FindLabel(label);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
FindLabel
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
unsigned char *ScriptClass::FindLabel(const_str label)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script->m_State.FindLabel(label);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
NearestLabel
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
const_str ScriptClass::NearestLabel(unsigned char *pos)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script->m_State.NearestLabel(pos);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GetCatchStateScript
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
StateScript *ScriptClass::GetCatchStateScript(unsigned char *in, unsigned char *& out)
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script->GetCatchStateScript(in, out);
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GetScript
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
GameScript *ScriptClass::GetScript()
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return m_Script;
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
====================
|
|
|
|
GetSelf
|
|
|
|
====================
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
Listener *ScriptClass::GetSelf()
|
2023-01-30 18:20:50 +01:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
return static_cast<Listener *>(m_Self.Pointer());
|
2023-01-30 18:20:50 +01:00
|
|
|
}
|