mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Fully port the ACS integration to C++
This commit is contained in:
parent
88ffab9f3c
commit
8eef5efa95
20 changed files with 1164 additions and 1269 deletions
|
|
@ -130,8 +130,6 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
||||||
k_profiles.c
|
k_profiles.c
|
||||||
k_specialstage.c
|
k_specialstage.c
|
||||||
k_roulette.c
|
k_roulette.c
|
||||||
k_acs.c
|
|
||||||
k_acs-func.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
|
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
|
||||||
|
|
@ -515,6 +513,7 @@ endif()
|
||||||
|
|
||||||
add_subdirectory(sdl)
|
add_subdirectory(sdl)
|
||||||
add_subdirectory(objects)
|
add_subdirectory(objects)
|
||||||
|
add_subdirectory(acs)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
# strip debug symbols into separate file when using gcc.
|
# strip debug symbols into separate file when using gcc.
|
||||||
|
|
|
||||||
10
src/acs/CMakeLists.txt
Normal file
10
src/acs/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
target_sources(SRB2SDL2 PRIVATE
|
||||||
|
environment.cpp
|
||||||
|
environment.hpp
|
||||||
|
thread.cpp
|
||||||
|
thread.hpp
|
||||||
|
call-funcs.cpp
|
||||||
|
call-funcs.hpp
|
||||||
|
interface.cpp
|
||||||
|
interface.h
|
||||||
|
)
|
||||||
|
|
@ -8,49 +8,56 @@
|
||||||
// terms of the GNU General Public License, version 2.
|
// terms of the GNU General Public License, version 2.
|
||||||
// See the 'LICENSE' file for more details.
|
// See the 'LICENSE' file for more details.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file k_acs-func.c
|
/// \file call-funcs.cpp
|
||||||
/// \brief ACS CallFunc definitions
|
/// \brief Action Code Script: CallFunc instructions
|
||||||
|
|
||||||
#include "k_acs.h"
|
extern "C" {
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "../d_think.h"
|
||||||
#include "doomdef.h"
|
#include "../p_mobj.h"
|
||||||
#include "doomstat.h"
|
#include "../p_tick.h"
|
||||||
#include "d_think.h"
|
#include "../w_wad.h"
|
||||||
#include "p_mobj.h"
|
#include "../m_random.h"
|
||||||
#include "p_tick.h"
|
#include "../g_game.h"
|
||||||
#include "w_wad.h"
|
#include "../d_player.h"
|
||||||
#include "m_random.h"
|
#include "../r_defs.h"
|
||||||
#include "g_game.h"
|
#include "../r_state.h"
|
||||||
#include "d_player.h"
|
#include "../p_polyobj.h"
|
||||||
#include "r_defs.h"
|
#include "../taglist.h"
|
||||||
#include "r_state.h"
|
#include "../p_local.h"
|
||||||
#include "p_polyobj.h"
|
#include "../deh_tables.h"
|
||||||
#include "taglist.h"
|
#include "../fastcmp.h"
|
||||||
#include "p_local.h"
|
#include "../hu_stuff.h"
|
||||||
#include "deh_tables.h"
|
#include "../s_sound.h"
|
||||||
#include "fastcmp.h"
|
#include "../r_textures.h"
|
||||||
#include "hu_stuff.h"
|
|
||||||
#include "s_sound.h"
|
|
||||||
#include "r_textures.h"
|
|
||||||
|
|
||||||
ACSVM_String *ACSVM_MapScope_GetString(ACSVM_MapScope *map, ACSVM_Word index)
|
|
||||||
{
|
|
||||||
(void)map;
|
|
||||||
(void)index;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *activator)
|
#include <ACSVM/Code.hpp>
|
||||||
{
|
#include <ACSVM/CodeData.hpp>
|
||||||
(void)activator;
|
#include <ACSVM/Environment.hpp>
|
||||||
return NULL;
|
#include <ACSVM/Error.hpp>
|
||||||
}
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
#include "call-funcs.hpp"
|
||||||
|
|
||||||
|
#include "environment.hpp"
|
||||||
|
#include "thread.hpp"
|
||||||
|
#include "../cxxutil.hpp"
|
||||||
|
|
||||||
|
using namespace srb2::acs;
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
||||||
|
|
||||||
Helper function for ACS_CF_ThingCount. Gets
|
Helper function for CallFunc_ThingCount. Gets
|
||||||
an object type from a string.
|
an object type from a string.
|
||||||
|
|
||||||
Input Arguments:-
|
Input Arguments:-
|
||||||
|
|
@ -62,15 +69,13 @@ ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *activator)
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
||||||
{
|
{
|
||||||
mobjtype_t i;
|
|
||||||
|
|
||||||
if (fastncmp("MT_", word, 3))
|
if (fastncmp("MT_", word, 3))
|
||||||
{
|
{
|
||||||
// take off the MT_
|
// take off the MT_
|
||||||
word += 3;
|
word += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUMMOBJFREESLOTS; i++)
|
for (int i = 0; i < NUMMOBJFREESLOTS; i++)
|
||||||
{
|
{
|
||||||
if (!FREE_MOBJS[i])
|
if (!FREE_MOBJS[i])
|
||||||
{
|
{
|
||||||
|
|
@ -79,16 +84,16 @@ static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
||||||
|
|
||||||
if (fastcmp(word, FREE_MOBJS[i]))
|
if (fastcmp(word, FREE_MOBJS[i]))
|
||||||
{
|
{
|
||||||
*type = MT_FIRSTFREESLOT+i;
|
*type = static_cast<mobjtype_t>(static_cast<int>(MT_FIRSTFREESLOT) + i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MT_FIRSTFREESLOT; i++)
|
for (int i = 0; i < MT_FIRSTFREESLOT; i++)
|
||||||
{
|
{
|
||||||
if (fastcmp(word, MOBJTYPE_LIST[i]+3))
|
if (fastcmp(word, MOBJTYPE_LIST[i] + 3))
|
||||||
{
|
{
|
||||||
*type = i;
|
*type = static_cast<mobjtype_t>(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,8 +116,6 @@ static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
||||||
{
|
{
|
||||||
sfxenum_t i;
|
|
||||||
|
|
||||||
if (fastncmp("SFX_", word, 4))
|
if (fastncmp("SFX_", word, 4))
|
||||||
{
|
{
|
||||||
// take off the SFX_
|
// take off the SFX_
|
||||||
|
|
@ -124,11 +127,11 @@ static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
||||||
word += 2;
|
word += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NUMSFX; i++)
|
for (int i = 0; i < NUMSFX; i++)
|
||||||
{
|
{
|
||||||
if (S_sfx[i].name && fasticmp(word, S_sfx[i].name))
|
if (S_sfx[i].name && fasticmp(word, S_sfx[i].name))
|
||||||
{
|
{
|
||||||
*type = i;
|
*type = static_cast<sfxenum_t>(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +142,7 @@ static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type)
|
static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type)
|
||||||
|
|
||||||
Helper function for ACS_CF_ThingCount.
|
Helper function for CallFunc_ThingCount.
|
||||||
Returns whenever or not to add this thing
|
Returns whenever or not to add this thing
|
||||||
to the thing count.
|
to the thing count.
|
||||||
|
|
||||||
|
|
@ -172,7 +175,7 @@ static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread)
|
static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread)
|
||||||
|
|
||||||
Helper function for many print functions.
|
Helper function for many print functions.
|
||||||
Returns whenever or not the activator of the
|
Returns whenever or not the activator of the
|
||||||
|
|
@ -185,9 +188,9 @@ static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type)
|
||||||
true if it's for a display player,
|
true if it's for a display player,
|
||||||
otherwise false.
|
otherwise false.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread)
|
static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread)
|
||||||
{
|
{
|
||||||
activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread);
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
|
||||||
if ((info != NULL)
|
if ((info != NULL)
|
||||||
&& (info->mo != NULL && P_MobjWasRemoved(info->mo) == false)
|
&& (info->mo != NULL && P_MobjWasRemoved(info->mo) == false)
|
||||||
|
|
@ -200,11 +203,11 @@ static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_Random(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
ACS wrapper for P_RandomRange.
|
ACS wrapper for P_RandomRange.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_Random(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
INT32 low = 0;
|
INT32 low = 0;
|
||||||
INT32 high = 0;
|
INT32 high = 0;
|
||||||
|
|
@ -214,22 +217,22 @@ bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC
|
||||||
low = argV[0];
|
low = argV[0];
|
||||||
high = argV[1];
|
high = argV[1];
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, P_RandomRange(PR_ACS, low, high));
|
thread->dataStk.push(P_RandomRange(PR_ACS, low, high));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Counts the number of things of a particular
|
Counts the number of things of a particular
|
||||||
type and tid. Both fields are optional;
|
type and tid. Both fields are optional;
|
||||||
no type means indescriminate against type,
|
no type means indescriminate against type,
|
||||||
no tid means search thru all thinkers.
|
no tid means search thru all thinkers.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = NULL;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = NULL;
|
||||||
const char *className = NULL;
|
const char *className = NULL;
|
||||||
size_t classLen = 0;
|
size_t classLen = 0;
|
||||||
|
|
||||||
|
|
@ -240,11 +243,11 @@ bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
str = map->getString(argV[0]);
|
||||||
|
|
||||||
className = ACSVM_String_GetStr(str);
|
className = str->str;
|
||||||
classLen = ACSVM_String_GetLen(str);
|
classLen = str->len;
|
||||||
|
|
||||||
if (classLen > 0)
|
if (classLen > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -270,6 +273,9 @@ bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
// TODO: Even in SRB2 next's UDMF, tag lists
|
// TODO: Even in SRB2 next's UDMF, tag lists
|
||||||
// still aren't attached to mobj_t, only
|
// still aren't attached to mobj_t, only
|
||||||
// mapthing_t. Fix this.
|
// mapthing_t. Fix this.
|
||||||
|
CONS_Alert(CONS_WARNING,
|
||||||
|
"ThingCount TID field not implemented -- waiting for mobj tags.\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -293,60 +299,58 @@ bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, count);
|
thread->dataStk.push(count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_TagWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_TagWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pauses the thread until the tagged
|
Pauses the thread until the tagged
|
||||||
sector stops moving.
|
sector stops moving.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_TagWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_TagWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_ThreadState st = {0};
|
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
st.state = ACSVM_ThreadState_WaitTag;
|
thread->state = {
|
||||||
st.data = argV[0];
|
ACSVM::ThreadState::WaitTag,
|
||||||
st.type = ACS_TAGTYPE_SECTOR;
|
argV[0],
|
||||||
|
ACS_TAGTYPE_SECTOR
|
||||||
|
};
|
||||||
|
|
||||||
ACSVM_Thread_SetState(thread, st);
|
|
||||||
return true; // Execution interrupted
|
return true; // Execution interrupted
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_PolyWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_PolyWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pauses the thread until the tagged
|
Pauses the thread until the tagged
|
||||||
polyobject stops moving.
|
polyobject stops moving.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_PolyWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_PolyWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_ThreadState st = {0};
|
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
st.state = ACSVM_ThreadState_WaitTag;
|
thread->state = {
|
||||||
st.data = argV[0];
|
ACSVM::ThreadState::WaitTag,
|
||||||
st.type = ACS_TAGTYPE_POLYOBJ;
|
argV[0],
|
||||||
|
ACS_TAGTYPE_POLYOBJ
|
||||||
|
};
|
||||||
|
|
||||||
ACSVM_Thread_SetState(thread, st);
|
|
||||||
return true; // Execution interrupted
|
return true; // Execution interrupted
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ChangeFloor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Changes a floor texture.
|
Changes a floor texture.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ChangeFloor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = nullptr;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = nullptr;
|
||||||
const char *texName = NULL;
|
const char *texName = nullptr;
|
||||||
|
|
||||||
INT32 secnum = -1;
|
INT32 secnum = -1;
|
||||||
mtag_t tag = 0;
|
mtag_t tag = 0;
|
||||||
|
|
@ -355,9 +359,9 @@ bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
|
|
||||||
tag = argV[0];
|
tag = argV[0];
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
str = map->getString(argV[1]);
|
||||||
texName = ACSVM_String_GetStr(str);
|
texName = str->str;
|
||||||
|
|
||||||
TAG_ITER_SECTORS(tag, secnum)
|
TAG_ITER_SECTORS(tag, secnum)
|
||||||
{
|
{
|
||||||
|
|
@ -369,14 +373,14 @@ bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ChangeCeiling(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Changes a ceiling texture.
|
Changes a ceiling texture.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ChangeCeiling(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = NULL;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = NULL;
|
||||||
const char *texName = NULL;
|
const char *texName = NULL;
|
||||||
|
|
||||||
INT32 secnum = -1;
|
INT32 secnum = -1;
|
||||||
|
|
@ -386,9 +390,9 @@ bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wo
|
||||||
|
|
||||||
tag = argV[0];
|
tag = argV[0];
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
str = map->getString(argV[1]);
|
||||||
texName = ACSVM_String_GetStr(str);
|
texName = str->str;
|
||||||
|
|
||||||
TAG_ITER_SECTORS(tag, secnum)
|
TAG_ITER_SECTORS(tag, secnum)
|
||||||
{
|
{
|
||||||
|
|
@ -400,31 +404,31 @@ bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wo
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_LineSide(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pushes which side of the linedef was
|
Pushes which side of the linedef was
|
||||||
activated.
|
activated.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_LineSide(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread);
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, info->side);
|
thread->dataStk.push(info->side);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_ClearLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ClearLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
If there is an activating linedef, set its
|
If there is an activating linedef, set its
|
||||||
special to 0.
|
special to 0.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_ClearLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ClearLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread);
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
@ -439,38 +443,33 @@ bool ACS_CF_ClearLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_EndPrint(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndPrint(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
One of the ACS wrappers for CEcho. This
|
One of the ACS wrappers for CEcho. This
|
||||||
version only prints if the activator is a
|
version only prints if the activator is a
|
||||||
display player.
|
display player.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_EndPrint(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndPrint(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_PrintBuf *buf = NULL;
|
|
||||||
|
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
|
||||||
|
|
||||||
if (ACS_ActivatorIsLocal(thread) == true)
|
if (ACS_ActivatorIsLocal(thread) == true)
|
||||||
{
|
{
|
||||||
HU_SetCEchoDuration(5);
|
HU_SetCEchoDuration(5);
|
||||||
HU_DoCEcho(ACSVM_PrintBuf_GetData(buf));
|
HU_DoCEcho(thread->printBuf.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM_PrintBuf_Drop(buf);
|
thread->printBuf.drop();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_PlayerCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_PlayerCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pushes the number of players to ACS.
|
Pushes the number of players to ACS.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_PlayerCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_PlayerCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
UINT8 numPlayers = 0;
|
UINT8 numPlayers = 0;
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
@ -497,78 +496,78 @@ bool ACS_CF_PlayerCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
numPlayers++;
|
numPlayers++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, numPlayers);
|
thread->dataStk.push(numPlayers);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_GameType(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_GameType(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pushes the current gametype to ACS.
|
Pushes the current gametype to ACS.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_GameType(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_GameType(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, gametype);
|
thread->dataStk.push(gametype);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_GameSpeed(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_GameSpeed(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pushes the current game speed to ACS.
|
Pushes the current game speed to ACS.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_GameSpeed(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_GameSpeed(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, gamespeed);
|
thread->dataStk.push(gamespeed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_Timer(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_Timer(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Pushes leveltime to ACS.
|
Pushes leveltime to ACS.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_Timer(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_Timer(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
ACSVM_Thread_DataStk_Push(thread, leveltime);
|
thread->dataStk.push(leveltime);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SectorSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Plays a point sound effect from a sector.
|
Plays a point sound effect from a sector.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SectorSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread);
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = nullptr;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = nullptr;
|
||||||
|
|
||||||
const char *sfxName = NULL;
|
const char *sfxName = nullptr;
|
||||||
size_t sfxLen = 0;
|
size_t sfxLen = 0;
|
||||||
|
|
||||||
sfxenum_t sfxId = sfx_None;
|
sfxenum_t sfxId = sfx_None;
|
||||||
INT32 vol = 0;
|
INT32 vol = 0;
|
||||||
mobj_t *origin = NULL;
|
mobj_t *origin = nullptr;
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
str = map->getString(argV[0]);
|
||||||
|
|
||||||
sfxName = ACSVM_String_GetStr(str);
|
sfxName = str->str;
|
||||||
sfxLen = ACSVM_String_GetLen(str);
|
sfxLen = str->len;
|
||||||
|
|
||||||
if (sfxLen > 0)
|
if (sfxLen > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -589,15 +588,15 @@ bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
|
|
||||||
vol = argV[1];
|
vol = argV[1];
|
||||||
|
|
||||||
if (info->sector != NULL)
|
if (info->sector != nullptr)
|
||||||
{
|
{
|
||||||
// New to Ring Racers: Use activating sector directly.
|
// New to Ring Racers: Use activating sector directly.
|
||||||
origin = (void *)&info->sector->soundorg;
|
origin = static_cast<mobj_t *>(static_cast<void *>(&info->sector->soundorg));
|
||||||
}
|
}
|
||||||
else if (info->line != NULL)
|
else if (info->line != nullptr)
|
||||||
{
|
{
|
||||||
// Original Hexen behavior: Use line's frontsector.
|
// Original Hexen behavior: Use line's frontsector.
|
||||||
origin = (void *)&info->line->frontsector->soundorg;
|
origin = static_cast<mobj_t *>(static_cast<void *>(&info->line->frontsector->soundorg));
|
||||||
}
|
}
|
||||||
|
|
||||||
S_StartSoundAtVolume(origin, sfxId, vol);
|
S_StartSoundAtVolume(origin, sfxId, vol);
|
||||||
|
|
@ -605,16 +604,16 @@ bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_AmbientSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Plays a sound effect globally.
|
Plays a sound effect globally.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_AmbientSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = nullptr;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = nullptr;
|
||||||
|
|
||||||
const char *sfxName = NULL;
|
const char *sfxName = nullptr;
|
||||||
size_t sfxLen = 0;
|
size_t sfxLen = 0;
|
||||||
|
|
||||||
sfxenum_t sfxId = sfx_None;
|
sfxenum_t sfxId = sfx_None;
|
||||||
|
|
@ -622,11 +621,11 @@ bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wor
|
||||||
|
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
str = map->getString(argV[0]);
|
||||||
|
|
||||||
sfxName = ACSVM_String_GetStr(str);
|
sfxName = str->str;
|
||||||
sfxLen = ACSVM_String_GetLen(str);
|
sfxLen = str->len;
|
||||||
|
|
||||||
if (sfxLen > 0)
|
if (sfxLen > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -652,7 +651,7 @@ bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wor
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Plays a sound effect globally.
|
Plays a sound effect globally.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
|
|
@ -663,14 +662,14 @@ enum
|
||||||
SLT_POS_BOTTOM
|
SLT_POS_BOTTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
mtag_t tag = 0;
|
mtag_t tag = 0;
|
||||||
UINT8 sideId = 0;
|
UINT8 sideId = 0;
|
||||||
UINT8 texPos = 0;
|
UINT8 texPos = 0;
|
||||||
|
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = NULL;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = NULL;
|
||||||
const char *texName = NULL;
|
const char *texName = NULL;
|
||||||
INT32 texId = LUMPERROR;
|
INT32 texId = LUMPERROR;
|
||||||
|
|
||||||
|
|
@ -682,9 +681,9 @@ bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
||||||
sideId = (argV[1] & 1);
|
sideId = (argV[1] & 1);
|
||||||
texPos = argV[2];
|
texPos = argV[2];
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[4]);
|
str = map->getString(argV[4]);
|
||||||
texName = ACSVM_String_GetStr(str);
|
texName = str->str;
|
||||||
|
|
||||||
texId = R_TextureNumForName(texName);
|
texId = R_TextureNumForName(texName);
|
||||||
|
|
||||||
|
|
@ -718,13 +717,13 @@ bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Changes a linedef's special and arguments.
|
Changes a linedef's special and arguments.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
activator_t *info = (activator_t *)ACSVM_Thread_GetInfo(thread);
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
|
||||||
mtag_t tag = 0;
|
mtag_t tag = 0;
|
||||||
INT32 spec = 0;
|
INT32 spec = 0;
|
||||||
|
|
@ -735,14 +734,14 @@ bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
||||||
tag = argV[0];
|
tag = argV[0];
|
||||||
spec = argV[1];
|
spec = argV[1];
|
||||||
|
|
||||||
numArgs = min(max(argC - 2, 0), NUMLINEARGS);
|
numArgs = std::min(std::max((signed)(argC - 2), 0), NUMLINEARGS);
|
||||||
|
|
||||||
TAG_ITER_LINES(tag, lineId)
|
TAG_ITER_LINES(tag, lineId)
|
||||||
{
|
{
|
||||||
line_t *line = &lines[lineId];
|
line_t *line = &lines[lineId];
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (info->line != NULL && line == info->line)
|
if (info->line != nullptr && line == info->line)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -759,16 +758,16 @@ bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_ThingSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
Plays a sound effect for a tagged object.
|
Plays a sound effect for a tagged object.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_ThingSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_MapScope *map = NULL;
|
ACSVM::MapScope *map = nullptr;
|
||||||
ACSVM_String *str = NULL;
|
ACSVM::String *str = nullptr;
|
||||||
|
|
||||||
const char *sfxName = NULL;
|
const char *sfxName = nullptr;
|
||||||
size_t sfxLen = 0;
|
size_t sfxLen = 0;
|
||||||
|
|
||||||
mtag_t tag = 0;
|
mtag_t tag = 0;
|
||||||
|
|
@ -779,11 +778,11 @@ bool ACS_CF_ThingSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
|
|
||||||
tag = argV[0];
|
tag = argV[0];
|
||||||
|
|
||||||
map = ACSVM_Thread_GetScopeMap(thread);
|
map = thread->scopeMap;
|
||||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
str = map->getString(argV[1]);
|
||||||
|
|
||||||
sfxName = ACSVM_String_GetStr(str);
|
sfxName = str->str;
|
||||||
sfxLen = ACSVM_String_GetLen(str);
|
sfxLen = str->len;
|
||||||
|
|
||||||
if (sfxLen > 0)
|
if (sfxLen > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -823,50 +822,40 @@ bool ACS_CF_ThingSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_EndPrintBold(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
One of the ACS wrappers for CEcho. This
|
One of the ACS wrappers for CEcho. This
|
||||||
version prints for all players.
|
version prints for all players.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_EndPrintBold(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_PrintBuf *buf = NULL;
|
|
||||||
|
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
|
||||||
|
|
||||||
HU_SetCEchoDuration(5);
|
HU_SetCEchoDuration(5);
|
||||||
HU_DoCEcho(ACSVM_PrintBuf_GetData(buf));
|
HU_DoCEcho(thread->printBuf.data());
|
||||||
|
|
||||||
ACSVM_PrintBuf_Drop(buf);
|
|
||||||
|
|
||||||
|
thread->printBuf.drop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool ACS_CF_EndLog(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
One of the ACS wrappers for CONS_Printf.
|
One of the ACS wrappers for CONS_Printf.
|
||||||
This version only prints if the activator
|
This version only prints if the activator
|
||||||
is a display player.
|
is a display player.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
bool ACS_CF_EndLog(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
|
bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
{
|
{
|
||||||
ACSVM_PrintBuf *buf = NULL;
|
|
||||||
|
|
||||||
(void)argV;
|
(void)argV;
|
||||||
(void)argC;
|
(void)argC;
|
||||||
|
|
||||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
|
||||||
|
|
||||||
if (ACS_ActivatorIsLocal(thread) == true)
|
if (ACS_ActivatorIsLocal(thread) == true)
|
||||||
{
|
{
|
||||||
CONS_Printf("%s\n", ACSVM_PrintBuf_GetData(buf));
|
CONS_Printf("%s\n", thread->printBuf.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM_PrintBuf_Drop(buf);
|
thread->printBuf.drop();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
70
src/acs/call-funcs.hpp
Normal file
70
src/acs/call-funcs.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file call-funcs.hpp
|
||||||
|
/// \brief Action Code Script: CallFunc instructions
|
||||||
|
|
||||||
|
#ifndef __SRB2_ACS_CALL_FUNCS_HPP__
|
||||||
|
#define __SRB2_ACS_CALL_FUNCS_HPP__
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
bool CallFunc_???(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
||||||
|
These are the actual CallFuncs ran when ACS
|
||||||
|
is executed. Which CallFuncs are executed
|
||||||
|
is based on the indices from the compiled
|
||||||
|
data. ACS_EnvConstruct is where the link
|
||||||
|
between the byte code and the actual function
|
||||||
|
is made.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
thread: The ACS execution thread this action
|
||||||
|
is running on.
|
||||||
|
argV: An array of the action's arguments.
|
||||||
|
argC: The length of the argument array.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
Returns true if this function pauses the
|
||||||
|
thread's execution. Otherwise returns false.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
bool CallFunc_Random(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_TagWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_PolyWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_ChangeFloor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_ChangeCeiling(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_LineSide(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_ClearLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_EndPrint(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_PlayerCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_GameType(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_GameSpeed(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_Timer(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_SectorSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_AmbientSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_EndLog(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
||||||
|
#endif // __SRB2_ACS_CALL_FUNCS_HPP__
|
||||||
307
src/acs/environment.cpp
Normal file
307
src/acs/environment.cpp
Normal file
|
|
@ -0,0 +1,307 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file environment.cpp
|
||||||
|
/// \brief Action Code Script: Environment definition
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
|
||||||
|
#include "../r_defs.h"
|
||||||
|
#include "../r_state.h"
|
||||||
|
#include "../g_game.h"
|
||||||
|
#include "../p_spec.h"
|
||||||
|
#include "../w_wad.h"
|
||||||
|
#include "../z_zone.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
#include "environment.hpp"
|
||||||
|
#include "thread.hpp"
|
||||||
|
#include "call-funcs.hpp"
|
||||||
|
#include "../cxxutil.hpp"
|
||||||
|
|
||||||
|
using namespace srb2::acs;
|
||||||
|
|
||||||
|
Environment ACSEnv;
|
||||||
|
|
||||||
|
Environment::Environment()
|
||||||
|
{
|
||||||
|
ACSVM::GlobalScope *global = getGlobalScope(0);
|
||||||
|
|
||||||
|
// Activate global scope immediately, since we don't want it off.
|
||||||
|
// Not that we're adding any modules to it, though. :p
|
||||||
|
global->active = true;
|
||||||
|
|
||||||
|
// Add the data & function pointers.
|
||||||
|
|
||||||
|
// Starting with raw ACS0 codes. I'm using this classic-style
|
||||||
|
// format here to have a blueprint for what needs implementing,
|
||||||
|
// but it'd also be fine to move these to new style.
|
||||||
|
|
||||||
|
// See also:
|
||||||
|
// - https://doomwiki.org/wiki/ACS0_instruction_set
|
||||||
|
// - https://github.com/DavidPH/ACSVM/blob/master/ACSVM/CodeData.hpp
|
||||||
|
// - https://github.com/DavidPH/ACSVM/blob/master/ACSVM/CodeList.hpp
|
||||||
|
|
||||||
|
// 0 to 56: Implemented by ACSVM
|
||||||
|
addCodeDataACS0( 57, {"", 2, addCallFunc(CallFunc_Random)});
|
||||||
|
addCodeDataACS0( 58, {"WW", 0, addCallFunc(CallFunc_Random)});
|
||||||
|
addCodeDataACS0( 59, {"", 2, addCallFunc(CallFunc_ThingCount)});
|
||||||
|
addCodeDataACS0( 60, {"WW", 0, addCallFunc(CallFunc_ThingCount)});
|
||||||
|
addCodeDataACS0( 61, {"", 1, addCallFunc(CallFunc_TagWait)});
|
||||||
|
addCodeDataACS0( 62, {"W", 0, addCallFunc(CallFunc_TagWait)});
|
||||||
|
addCodeDataACS0( 63, {"", 1, addCallFunc(CallFunc_PolyWait)});
|
||||||
|
addCodeDataACS0( 64, {"W", 0, addCallFunc(CallFunc_PolyWait)});
|
||||||
|
addCodeDataACS0( 65, {"", 2, addCallFunc(CallFunc_ChangeFloor)});
|
||||||
|
addCodeDataACS0( 66, {"WWS", 0, addCallFunc(CallFunc_ChangeFloor)});
|
||||||
|
addCodeDataACS0( 67, {"", 2, addCallFunc(CallFunc_ChangeCeiling)});
|
||||||
|
addCodeDataACS0( 68, {"WWS", 0, addCallFunc(CallFunc_ChangeCeiling)});
|
||||||
|
// 69 to 79: Implemented by ACSVM
|
||||||
|
addCodeDataACS0( 80, {"", 0, addCallFunc(CallFunc_LineSide)});
|
||||||
|
// 81 to 82: Implemented by ACSVM
|
||||||
|
addCodeDataACS0( 83, {"", 0, addCallFunc(CallFunc_ClearLineSpecial)});
|
||||||
|
// 84 to 85: Implemented by ACSVM
|
||||||
|
addCodeDataACS0( 86, {"", 0, addCallFunc(CallFunc_EndPrint)});
|
||||||
|
// 87 to 89: Implemented by ACSVM
|
||||||
|
addCodeDataACS0( 90, {"", 0, addCallFunc(CallFunc_PlayerCount)});
|
||||||
|
addCodeDataACS0( 91, {"", 0, addCallFunc(CallFunc_GameType)});
|
||||||
|
addCodeDataACS0( 92, {"", 0, addCallFunc(CallFunc_GameSpeed)});
|
||||||
|
addCodeDataACS0( 93, {"", 0, addCallFunc(CallFunc_Timer)});
|
||||||
|
addCodeDataACS0( 94, {"", 2, addCallFunc(CallFunc_SectorSound)});
|
||||||
|
addCodeDataACS0( 95, {"", 2, addCallFunc(CallFunc_AmbientSound)});
|
||||||
|
|
||||||
|
addCodeDataACS0( 97, {"", 4, addCallFunc(CallFunc_SetLineTexture)});
|
||||||
|
|
||||||
|
addCodeDataACS0( 99, {"", 7, addCallFunc(CallFunc_SetLineSpecial)});
|
||||||
|
addCodeDataACS0(100, {"", 3, addCallFunc(CallFunc_ThingSound)});
|
||||||
|
addCodeDataACS0(101, {"", 0, addCallFunc(CallFunc_EndPrintBold)});
|
||||||
|
// 136 to 137: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 157: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 167 to 173: Implemented by ACSVM
|
||||||
|
addCodeDataACS0(174, {"BB", 0, addCallFunc(CallFunc_Random)});
|
||||||
|
// 175 to 179: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 181 to 189: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 203 to 217: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 225 to 243: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 253: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 256 to 257: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 263: Implemented by ACSVM
|
||||||
|
addCodeDataACS0(270, {"", 0, addCallFunc(CallFunc_EndLog)});
|
||||||
|
// 273 to 275: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 291 to 325: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 330: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 349 to 361: Implemented by ACSVM
|
||||||
|
|
||||||
|
// 363 to 380: Implemented by ACSVM
|
||||||
|
}
|
||||||
|
|
||||||
|
ACSVM::Thread *Environment::allocThread()
|
||||||
|
{
|
||||||
|
return new Thread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Environment::loadModule(ACSVM::Module *module)
|
||||||
|
{
|
||||||
|
ACSVM::ModuleName *const name = &module->name;
|
||||||
|
|
||||||
|
size_t lumpLen = 0;
|
||||||
|
std::vector<ACSVM::Byte> data;
|
||||||
|
|
||||||
|
if (name->i == (size_t)LUMPERROR)
|
||||||
|
{
|
||||||
|
// No lump given for module.
|
||||||
|
CONS_Alert(CONS_ERROR, "Bad lump for ACS module '%s'\n", name->s->str);
|
||||||
|
throw ACSVM::ReadError("file open failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
lumpLen = W_LumpLength(name->i);
|
||||||
|
|
||||||
|
if (W_IsLumpWad(name->i) == true || lumpLen == 0)
|
||||||
|
{
|
||||||
|
// The lump given is a virtual resource.
|
||||||
|
// Try to grab a BEHAVIOR lump from inside of it.
|
||||||
|
virtres_t *vRes = vres_GetMap(name->i);
|
||||||
|
virtlump_t *vLump = vres_Find(vRes, "BEHAVIOR");
|
||||||
|
|
||||||
|
CONS_Printf("Attempting to load ACS module from map's virtual resource...\n");
|
||||||
|
|
||||||
|
if (vLump != nullptr && vLump->size > 0)
|
||||||
|
{
|
||||||
|
data.insert(data.begin(), vLump->data, vLump->data + vLump->size);
|
||||||
|
CONS_Printf("Successfully found BEHAVIOR lump.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CONS_Printf("No BEHAVIOR lump found.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// It's a real lump.
|
||||||
|
ACSVM::Byte *lump = static_cast<ACSVM::Byte *>(Z_Calloc(lumpLen, PU_STATIC, nullptr));
|
||||||
|
auto _ = srb2::finally([lump]() { Z_Free(lump); });
|
||||||
|
|
||||||
|
W_ReadLump(name->i, lump);
|
||||||
|
data.insert(data.begin(), lump, lump + lumpLen);
|
||||||
|
|
||||||
|
CONS_Printf("Loading ACS module directly from lump.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.empty() == false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
module->readBytecode(data.data(), data.size());
|
||||||
|
}
|
||||||
|
catch (const ACSVM::ReadError &e)
|
||||||
|
{
|
||||||
|
CONS_Printf("Failed to load ACS module '%s': %s\n", name->s->str, e.what());
|
||||||
|
throw ACSVM::ReadError("failed import");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unlike Hexen, a BEHAVIOR lump is not required.
|
||||||
|
// Simply ignore in this instance.
|
||||||
|
CONS_Printf("No data received, ignoring...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Environment::checkTag(ACSVM::Word type, ACSVM::Word tag)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ACS_TAGTYPE_SECTOR:
|
||||||
|
{
|
||||||
|
INT32 secnum = -1;
|
||||||
|
|
||||||
|
TAG_ITER_SECTORS(tag, secnum)
|
||||||
|
{
|
||||||
|
sector_t *sec = §ors[secnum];
|
||||||
|
|
||||||
|
if (sec->floordata != nullptr || sec->ceilingdata != nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ACS_TAGTYPE_POLYOBJ:
|
||||||
|
{
|
||||||
|
const polyobj_t *po = Polyobj_GetForNum(tag);
|
||||||
|
return (po == nullptr || po->thinker == nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACSVM::Word Environment::callSpecImpl
|
||||||
|
(
|
||||||
|
ACSVM::Thread *thread, ACSVM::Word spec,
|
||||||
|
const ACSVM::Word *argV, ACSVM::Word argC
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto info = &static_cast<Thread *>(thread)->info;
|
||||||
|
ACSVM::MapScope *const map = thread->scopeMap;
|
||||||
|
|
||||||
|
int arg = 0;
|
||||||
|
int numStringArgs = 0;
|
||||||
|
|
||||||
|
INT32 args[NUMLINEARGS] = {0};
|
||||||
|
|
||||||
|
char *stringargs[NUMLINESTRINGARGS] = {0};
|
||||||
|
auto _ = srb2::finally(
|
||||||
|
[stringargs]()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUMLINESTRINGARGS; i++)
|
||||||
|
{
|
||||||
|
Z_Free(stringargs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
activator_t *activator = static_cast<activator_t *>(Z_Calloc(sizeof(activator_t), PU_LEVEL, nullptr));
|
||||||
|
auto __ = srb2::finally([activator]() { Z_Free(activator); });
|
||||||
|
|
||||||
|
// This needs manually set, as ACS just uses indicies in the
|
||||||
|
// compiled string table and not actual strings, and SRB2 has
|
||||||
|
// separate args and stringargs, so there's no way to
|
||||||
|
// properly distinguish them.
|
||||||
|
switch (spec)
|
||||||
|
{
|
||||||
|
case 442:
|
||||||
|
numStringArgs = 2;
|
||||||
|
break;
|
||||||
|
case 413:
|
||||||
|
case 414:
|
||||||
|
case 415:
|
||||||
|
case 423:
|
||||||
|
case 425:
|
||||||
|
case 443:
|
||||||
|
case 459:
|
||||||
|
case 461:
|
||||||
|
case 463:
|
||||||
|
case 469:
|
||||||
|
numStringArgs = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; arg < numStringArgs; arg++)
|
||||||
|
{
|
||||||
|
ACSVM::String *strPtr = map->getString(argV[arg]);
|
||||||
|
|
||||||
|
stringargs[arg] = static_cast<char *>(Z_Malloc(strPtr->len + 1, PU_STATIC, nullptr));
|
||||||
|
M_Memcpy(stringargs[arg], strPtr->str, strPtr->len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; arg < std::min((signed)argC, NUMLINEARGS); arg++)
|
||||||
|
{
|
||||||
|
args[arg - numStringArgs] = argV[arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
P_SetTarget(&activator->mo, info->mo);
|
||||||
|
activator->line = info->line;
|
||||||
|
activator->side = info->side;
|
||||||
|
activator->sector = info->sector;
|
||||||
|
activator->po = info->po;
|
||||||
|
activator->fromLineSpecial = false;
|
||||||
|
|
||||||
|
P_ProcessSpecial(activator, spec, args, stringargs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
52
src/acs/environment.hpp
Normal file
52
src/acs/environment.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file environment.hpp
|
||||||
|
/// \brief Action Code Script: Environment definition
|
||||||
|
|
||||||
|
#ifndef __SRB2_ACS_ENVIRONMENT_HPP__
|
||||||
|
#define __SRB2_ACS_ENVIRONMENT_HPP__
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
namespace srb2::acs {
|
||||||
|
|
||||||
|
class Environment : public ACSVM::Environment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Environment();
|
||||||
|
|
||||||
|
virtual bool checkTag(ACSVM::Word type, ACSVM::Word tag);
|
||||||
|
|
||||||
|
virtual ACSVM::Word callSpecImpl(
|
||||||
|
ACSVM::Thread *thread, ACSVM::Word spec,
|
||||||
|
const ACSVM::Word *argV, ACSVM::Word argC
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual ACSVM::Thread *allocThread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void loadModule(ACSVM::Module *module);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extern srb2::acs::Environment ACSEnv;
|
||||||
|
|
||||||
|
#endif // __SRB2_ACS_ENVIRONMENT_HPP__
|
||||||
232
src/acs/interface.cpp
Normal file
232
src/acs/interface.cpp
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file interface.cpp
|
||||||
|
/// \brief Action Code Script: Interface for the rest of SRB2's game logic
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "interface.h"
|
||||||
|
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
|
||||||
|
#include "../r_defs.h"
|
||||||
|
#include "../g_game.h"
|
||||||
|
#include "../i_system.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
#include "environment.hpp"
|
||||||
|
#include "thread.hpp"
|
||||||
|
|
||||||
|
#include "../cxxutil.hpp"
|
||||||
|
|
||||||
|
using namespace srb2::acs;
|
||||||
|
|
||||||
|
using std::size_t;
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Init(void)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_Init(void)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// Initialize ACS on engine start-up.
|
||||||
|
ACSEnv = new Environment();
|
||||||
|
I_AddExitFunc(ACS_Shutdown);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Shutdown(void)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_Shutdown(void)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// Delete ACS environment.
|
||||||
|
delete ACSEnv;
|
||||||
|
ACSEnv = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_LoadLevelScripts(size_t mapID)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_LoadLevelScripts(size_t mapID)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||||
|
ACSVM::HubScope *hub = NULL;
|
||||||
|
ACSVM::MapScope *map = NULL;
|
||||||
|
|
||||||
|
std::vector<ACSVM::Module *> modules;
|
||||||
|
|
||||||
|
// Just some notes on how Hexen's scopes work, if anyone
|
||||||
|
// intends to implement proper hub logic:
|
||||||
|
|
||||||
|
// The integer is an ID for which hub / map it is,
|
||||||
|
// and instead sets active according to which ones
|
||||||
|
// should run, since you can go between them.
|
||||||
|
|
||||||
|
// But I didn't intend on implementing these features,
|
||||||
|
// since hubs aren't planned for Ring Racers (although
|
||||||
|
// they might be useful for SRB2), and I intentionally
|
||||||
|
// avoided implementing global ACS (since Lua would be
|
||||||
|
// a better language to do that kind of code).
|
||||||
|
|
||||||
|
// Since we literally only are using map scope, we can
|
||||||
|
// just free everything between every level. But if
|
||||||
|
// hubs are to be implemented, this logic would need
|
||||||
|
// to be far more sophisticated.
|
||||||
|
|
||||||
|
// Reset hub scope, even if we are not using it.
|
||||||
|
hub = global->getHubScope(0);
|
||||||
|
hub->reset();
|
||||||
|
hub->active = true;
|
||||||
|
|
||||||
|
// Start up new map scope.
|
||||||
|
map = hub->getMapScope(0); // This is where you'd put in mapID if you add hub support.
|
||||||
|
map->reset();
|
||||||
|
map->active = true;
|
||||||
|
|
||||||
|
// Insert BEHAVIOR lump into the list.
|
||||||
|
{
|
||||||
|
ACSVM::ModuleName name = ACSVM::ModuleName(
|
||||||
|
env->getString( mapheaderinfo[mapID]->lumpname ),
|
||||||
|
nullptr,
|
||||||
|
mapheaderinfo[mapID]->lumpnum
|
||||||
|
);
|
||||||
|
|
||||||
|
modules.push_back(env->getModule(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modules.empty() == false)
|
||||||
|
{
|
||||||
|
// Register the modules with map scope.
|
||||||
|
map->addModules(modules.data(), modules.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunPlayerEnterScript(player_t *player)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_RunPlayerEnterScript(player_t *player)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||||
|
ACSVM::HubScope *const hub = global->getHubScope(0);
|
||||||
|
ACSVM::MapScope *const map = hub->getMapScope(0);
|
||||||
|
|
||||||
|
ACSVM::MapScope::ScriptStartInfo scriptInfo;
|
||||||
|
ThreadInfo info;
|
||||||
|
|
||||||
|
P_SetTarget(&info.mo, player->mo);
|
||||||
|
|
||||||
|
scriptInfo.info = &info;
|
||||||
|
|
||||||
|
map->scriptStartTypeForced(ACS_ST_ENTER, scriptInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunLevelStartScripts(void)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_RunLevelStartScripts(void)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||||
|
ACSVM::HubScope *const hub = global->getHubScope(0);
|
||||||
|
ACSVM::MapScope *const map = hub->getMapScope(0);
|
||||||
|
|
||||||
|
map->scriptStartType(ACS_ST_OPEN, {});
|
||||||
|
|
||||||
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
player_t *player = NULL;
|
||||||
|
|
||||||
|
if (playeringame[i] == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
player = &players[i];
|
||||||
|
if (player->spectator == true)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACS_RunPlayerEnterScript(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunLapScript(mobj_t *mo, line_t *line)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_RunLapScript(mobj_t *mo, line_t *line)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
ACSVM::GlobalScope *const global = env->getGlobalScope(0);
|
||||||
|
ACSVM::HubScope *const hub = global->getHubScope(0);
|
||||||
|
ACSVM::MapScope *const map = hub->getMapScope(0);
|
||||||
|
|
||||||
|
ACSVM::MapScope::ScriptStartInfo scriptInfo;
|
||||||
|
ThreadInfo info;
|
||||||
|
|
||||||
|
P_SetTarget(&info.mo, mo);
|
||||||
|
info.line = line;
|
||||||
|
|
||||||
|
scriptInfo.info = &info;
|
||||||
|
|
||||||
|
map->scriptStartTypeForced(ACS_ST_LAP, scriptInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Tick(void)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void ACS_Tick(void)
|
||||||
|
{
|
||||||
|
Environment *env = &ACSEnv;
|
||||||
|
|
||||||
|
if (env->hasActiveThread() == true)
|
||||||
|
{
|
||||||
|
env->exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/acs/interface.h
Normal file
116
src/acs/interface.h
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file interface.h
|
||||||
|
/// \brief Action Code Script: Interface for the rest of SRB2's game logic
|
||||||
|
|
||||||
|
#ifndef __SRB2_ACS_INTERFACE_H__
|
||||||
|
#define __SRB2_ACS_INTERFACE_H__
|
||||||
|
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Init(void);
|
||||||
|
|
||||||
|
Initializes the ACS environment. Handles creating
|
||||||
|
the VM, initializing its hooks, storing the
|
||||||
|
pointer for future reference, and adding the
|
||||||
|
shutdown function.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_Init(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Shutdown(void);
|
||||||
|
|
||||||
|
Frees the ACS environment, for when the game
|
||||||
|
is exited.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_Shutdown(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_LoadLevelScripts(size_t mapID);
|
||||||
|
|
||||||
|
Resets the ACS hub and map scopes to remove
|
||||||
|
existing running scripts, and inserts the new
|
||||||
|
level's ACS modules (BEHAVIOR lump) into
|
||||||
|
the environment.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
mapID: The map's number to read the BEHAVIOR
|
||||||
|
lump of.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
None
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_LoadLevelScripts(size_t mapID);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunPlayerEnterScript(player_t *player);
|
||||||
|
|
||||||
|
Runs the map's special script for a player
|
||||||
|
entering the game.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
player: The player to run the script for.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
None
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_RunPlayerEnterScript(player_t *player);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunLevelStartScripts(void);
|
||||||
|
|
||||||
|
Runs the map's special scripts for opening
|
||||||
|
the level, and for all players to enter
|
||||||
|
the game.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_RunLevelStartScripts(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_RunLapScript(mobj_t *mo, line_t *line);
|
||||||
|
|
||||||
|
Runs the map's special script for a player
|
||||||
|
crossing the finish line.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
player: The player to run the script for.
|
||||||
|
line: The finish line's linedef.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
None
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_RunLapScript(mobj_t *mo, line_t *line);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void ACS_Tick(void);
|
||||||
|
|
||||||
|
Executes all of the ACS environment's
|
||||||
|
currently active threads.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void ACS_Tick(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __SRB2_ACS_INTERFACE_H__
|
||||||
57
src/acs/thread.cpp
Normal file
57
src/acs/thread.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file thread.cpp
|
||||||
|
/// \brief Action Code Script: Thread definition
|
||||||
|
|
||||||
|
#include "thread.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
using namespace srb2::acs;
|
||||||
|
|
||||||
|
void Thread::start(
|
||||||
|
ACSVM::Script *script, ACSVM::MapScope *map,
|
||||||
|
const ACSVM::ThreadInfo *infoPtr, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
{
|
||||||
|
ACSVM::Thread::start(script, map, infoPtr, argV, argC);
|
||||||
|
|
||||||
|
if (infoPtr != nullptr)
|
||||||
|
{
|
||||||
|
info = *static_cast<const ThreadInfo *>(infoPtr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::stop()
|
||||||
|
{
|
||||||
|
ACSVM::Thread::stop();
|
||||||
|
info = {};
|
||||||
|
}
|
||||||
125
src/acs/thread.hpp
Normal file
125
src/acs/thread.hpp
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
||||||
|
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) 2022 by Kart Krew
|
||||||
|
//
|
||||||
|
// This program is free software distributed under the
|
||||||
|
// terms of the GNU General Public License, version 2.
|
||||||
|
// See the 'LICENSE' file for more details.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// \file thread.hpp
|
||||||
|
/// \brief Action Code Script: Thread definition
|
||||||
|
|
||||||
|
#ifndef __SRB2_ACS_THREAD_HPP__
|
||||||
|
#define __SRB2_ACS_THREAD_HPP__
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../doomtype.h"
|
||||||
|
#include "../doomdef.h"
|
||||||
|
#include "../doomstat.h"
|
||||||
|
#include "../p_tick.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <ACSVM/Code.hpp>
|
||||||
|
#include <ACSVM/CodeData.hpp>
|
||||||
|
#include <ACSVM/Environment.hpp>
|
||||||
|
#include <ACSVM/Error.hpp>
|
||||||
|
#include <ACSVM/Module.hpp>
|
||||||
|
#include <ACSVM/Scope.hpp>
|
||||||
|
#include <ACSVM/Script.hpp>
|
||||||
|
#include <ACSVM/Serial.hpp>
|
||||||
|
#include <ACSVM/Thread.hpp>
|
||||||
|
#include <Util/Floats.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace srb2::acs {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Special global script types.
|
||||||
|
//
|
||||||
|
enum acs_scriptType_e
|
||||||
|
{
|
||||||
|
ACS_ST_OPEN = 1, // OPEN: Runs once when the level starts.
|
||||||
|
ACS_ST_RESPAWN = 2, // RESPAWN: Runs when a player respawns.
|
||||||
|
ACS_ST_DEATH = 3, // DEATH: Runs when a player dies.
|
||||||
|
ACS_ST_ENTER = 4, // ENTER: Runs when a player enters the game; both on start of the level, and when un-spectating.
|
||||||
|
ACS_ST_LAP = 5, // LAP: Runs when a player's lap increases from crossing the finish line.
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Script "waiting on tag" types.
|
||||||
|
//
|
||||||
|
enum acs_tagType_e
|
||||||
|
{
|
||||||
|
ACS_TAGTYPE_POLYOBJ,
|
||||||
|
ACS_TAGTYPE_SECTOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThreadInfo : public ACSVM::ThreadInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mobj_t *mo; // Object that activated this thread.
|
||||||
|
line_t *line; // Linedef that activated this thread.
|
||||||
|
UINT8 side; // Front / back side of said linedef.
|
||||||
|
sector_t *sector; // Sector that activated this thread.
|
||||||
|
polyobj_t *po; // Polyobject that activated this thread.
|
||||||
|
bool fromLineSpecial; // Called from P_ProcessLineSpecial.
|
||||||
|
|
||||||
|
ThreadInfo() :
|
||||||
|
mo{ nullptr },
|
||||||
|
line{ nullptr },
|
||||||
|
side{ 0 },
|
||||||
|
sector{ nullptr },
|
||||||
|
po{ nullptr },
|
||||||
|
fromLineSpecial{ false }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadInfo(const ThreadInfo &info) :
|
||||||
|
mo{ nullptr },
|
||||||
|
line{ info.line },
|
||||||
|
side{ info.side },
|
||||||
|
sector{ info.sector },
|
||||||
|
po{ info.po },
|
||||||
|
fromLineSpecial{ info.fromLineSpecial }
|
||||||
|
{
|
||||||
|
P_SetTarget(&mo, info.mo);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ThreadInfo()
|
||||||
|
{
|
||||||
|
P_SetTarget(&mo, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadInfo &operator = (const ThreadInfo &info)
|
||||||
|
{
|
||||||
|
P_SetTarget(&mo, info.mo);
|
||||||
|
line = info.line;
|
||||||
|
side = info.side;
|
||||||
|
po = info.po;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Thread : public ACSVM::Thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadInfo info;
|
||||||
|
|
||||||
|
explicit Thread(ACSVM::Environment *env_) : ACSVM::Thread{env_} {}
|
||||||
|
|
||||||
|
virtual ACSVM::ThreadInfo const *getInfo() const { return &info; }
|
||||||
|
|
||||||
|
virtual void start(
|
||||||
|
ACSVM::Script *script, ACSVM::MapScope *map,
|
||||||
|
const ACSVM::ThreadInfo *info, const ACSVM::Word *argV, ACSVM::Word argC
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void stop();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __SRB2_ACS_THREAD_HPP__
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "m_random.h" // P_ClearRandom
|
#include "m_random.h" // P_ClearRandom
|
||||||
#include "k_specialstage.h"
|
#include "k_specialstage.h"
|
||||||
#include "k_acs.h"
|
#include "acs/interface.h"
|
||||||
|
|
||||||
#ifdef CMAKECONFIG
|
#ifdef CMAKECONFIG
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
#include "k_specialstage.h"
|
#include "k_specialstage.h"
|
||||||
#include "k_bot.h"
|
#include "k_bot.h"
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "k_acs.h"
|
#include "acs/interface.h"
|
||||||
|
|
||||||
#ifdef HAVE_DISCORDRPC
|
#ifdef HAVE_DISCORDRPC
|
||||||
#include "discord.h"
|
#include "discord.h"
|
||||||
|
|
|
||||||
833
src/k_acs.c
833
src/k_acs.c
|
|
@ -1,833 +0,0 @@
|
||||||
// DR. ROBOTNIK'S RING RACERS
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
|
||||||
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
|
||||||
// Copyright (C) 2022 by Kart Krew
|
|
||||||
//
|
|
||||||
// This program is free software distributed under the
|
|
||||||
// terms of the GNU General Public License, version 2.
|
|
||||||
// See the 'LICENSE' file for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/// \file k_acs.c
|
|
||||||
/// \brief Action Code Script implementation using ACSVM
|
|
||||||
|
|
||||||
#include "k_acs.h"
|
|
||||||
|
|
||||||
#include "doomtype.h"
|
|
||||||
#include "doomdef.h"
|
|
||||||
#include "doomstat.h"
|
|
||||||
#include "z_zone.h"
|
|
||||||
#include "w_wad.h"
|
|
||||||
#include "i_system.h"
|
|
||||||
#include "r_defs.h"
|
|
||||||
#include "r_state.h"
|
|
||||||
#include "p_polyobj.h"
|
|
||||||
#include "taglist.h"
|
|
||||||
#include "d_player.h"
|
|
||||||
#include "g_game.h"
|
|
||||||
#include "p_tick.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
|
|
||||||
#include <CAPI/BinaryIO.h>
|
|
||||||
#include <CAPI/Environment.h>
|
|
||||||
#include <CAPI/Module.h>
|
|
||||||
#include <CAPI/PrintBuf.h>
|
|
||||||
#include <CAPI/Scope.h>
|
|
||||||
#include <CAPI/String.h>
|
|
||||||
#include <CAPI/Thread.h>
|
|
||||||
|
|
||||||
static ACSVM_Environment *ACSenv = NULL;
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
ACSVM_Environment *ACS_GetEnvironment(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
ACSVM_Environment *ACS_GetEnvironment(void)
|
|
||||||
{
|
|
||||||
return ACSenv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvBadAlloc(ACSVM_Environment *env, char const *what)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs in case of a memory
|
|
||||||
allocation failure occuring. Environment state
|
|
||||||
afterwards is unusable; the only thing safe to do
|
|
||||||
is using ACSVM_FreeEnvironment.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
what - Error string.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_EnvBadAlloc(ACSVM_Environment *env, char const *what)
|
|
||||||
{
|
|
||||||
(void)env;
|
|
||||||
|
|
||||||
CONS_Alert(CONS_ERROR, "Error allocating memory for ACS (%s)\n", what);
|
|
||||||
|
|
||||||
if (env == ACSenv)
|
|
||||||
{
|
|
||||||
// Restart the main environment.
|
|
||||||
ACS_Shutdown();
|
|
||||||
I_RemoveExitFunc(ACS_Shutdown); // Since ACS_Init will add it again.
|
|
||||||
ACS_Init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvReadError(ACSVM_Environment *env, char const *what)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when an ACS module
|
|
||||||
fails to read. Environment state should be safe
|
|
||||||
afterwards.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
what - Error string.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_EnvReadError(ACSVM_Environment *env, char const *what)
|
|
||||||
{
|
|
||||||
(void)env;
|
|
||||||
CONS_Alert(CONS_WARNING, "Error reading ACS module (%s)\n", what);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvSerialError(ACSVM_Environment *env, char const *what)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when the ACS state
|
|
||||||
fails to save or load. Environment state is
|
|
||||||
safe in that it shouldn't be causing crashes,
|
|
||||||
but it is indeterminate.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
what - Error string.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_EnvSerialError(ACSVM_Environment *env, char const *what)
|
|
||||||
{
|
|
||||||
(void)env;
|
|
||||||
CONS_Alert(CONS_WARNING, "Error serializing ACS state (%s)\n", what);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvThreadKilled(ACSVM_Environment *env, char const *what)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when the thread
|
|
||||||
has been killed for whatever reason, so that
|
|
||||||
the console can warn the user about it.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment the thread is from.
|
|
||||||
thread - The thread that was stopped.
|
|
||||||
reason - The reason the thread was stopped. See ACSVM_KillType.
|
|
||||||
data - Bytecode data at time of stopping.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_EnvThreadKilled(ACSVM_Environment const *env, ACSVM_Thread *thread, ACSVM_Word reason, ACSVM_Word data)
|
|
||||||
{
|
|
||||||
static const char *strings[] = {
|
|
||||||
"Just for fun", // ACSVM_KillType_None
|
|
||||||
"Out of bounds", // ACSVM_KillType_OutOfBounds
|
|
||||||
"Unknown code", // ACSVM_KillType_UnknownCode
|
|
||||||
"Unknown function", // ACSVM_KillType_UnknownFunc
|
|
||||||
"Reached recursion limit" // ACSVM_KillType_BranchLimit
|
|
||||||
};
|
|
||||||
|
|
||||||
(void)env;
|
|
||||||
(void)thread;
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
CONS_Alert(CONS_ERROR, "ACS thread killed (%s)\n", strings[reason]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_AddCodeDataCallFunc(
|
|
||||||
ACSVM_Environment *env, ACSVM_Word code,
|
|
||||||
char const *args, ACSVM_Word argc, ACSVM_CallFunc func)
|
|
||||||
|
|
||||||
Shortcut function to simplify adding
|
|
||||||
CallFuncs. These are for code data ones;
|
|
||||||
accessible in all ACS formats.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data to add this to.
|
|
||||||
code - The byte code for this function.
|
|
||||||
args - A string of arguments to use. The
|
|
||||||
letters represent different operations
|
|
||||||
to preform on the stack.
|
|
||||||
argc - Number of arguments to pull from
|
|
||||||
the stack, if not using args.
|
|
||||||
func - The function to add.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static inline void ACS_AddCodeDataCallFunc(ACSVM_Environment *env, ACSVM_Word code, char const *args, ACSVM_Word argc, ACSVM_CallFunc func)
|
|
||||||
{
|
|
||||||
ACSVM_Word funcId = ACSVM_Environment_AddCallFunc(env, func);
|
|
||||||
ACSVM_Code tCode = (argc != 0 ? ACSVM_Code_CallFunc : ACSVM_Code_CallFunc_Lit);
|
|
||||||
|
|
||||||
ACSVM_Environment_AddCodeDataACS0(
|
|
||||||
env, code,
|
|
||||||
args, tCode, argc,
|
|
||||||
funcId
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvConstruct(ACSVM_Environment *env)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when the
|
|
||||||
environment is initally created.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data to construct.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_EnvConstruct(ACSVM_Environment *env)
|
|
||||||
{
|
|
||||||
ACSVM_GlobalScope *global = ACSVM_Environment_GetGlobalScope(env, 0);
|
|
||||||
|
|
||||||
// Activate global scope immediately, since we don't want it off.
|
|
||||||
// Not that we're adding any modules to it, though. :p
|
|
||||||
ACSVM_GlobalScope_SetActive(global, true);
|
|
||||||
|
|
||||||
// Add the data & function pointers.
|
|
||||||
|
|
||||||
// Starting with raw ACS0 codes. I'm using this classic-style
|
|
||||||
// format here to have a blueprint for what needs implementing,
|
|
||||||
// but it'd also be fine to move these to new style.
|
|
||||||
|
|
||||||
// See also:
|
|
||||||
// - https://doomwiki.org/wiki/ACS0_instruction_set
|
|
||||||
// - https://github.com/DavidPH/ACSVM/blob/master/ACSVM/CodeData.hpp
|
|
||||||
// - https://github.com/DavidPH/ACSVM/blob/master/ACSVM/CodeList.hpp
|
|
||||||
|
|
||||||
// 0 to 56: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 57, "", 2, ACS_CF_Random);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 58, "WW", 0, ACS_CF_Random);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 59, "", 2, ACS_CF_ThingCount);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 60, "WW", 0, ACS_CF_ThingCount);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 61, "", 1, ACS_CF_TagWait);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 62, "W", 0, ACS_CF_TagWait);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 63, "", 1, ACS_CF_PolyWait);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 64, "W", 0, ACS_CF_PolyWait);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 65, "", 2, ACS_CF_ChangeFloor);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 66, "WWS", 0, ACS_CF_ChangeFloor);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 67, "", 2, ACS_CF_ChangeCeiling);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 68, "WWS", 0, ACS_CF_ChangeCeiling);
|
|
||||||
// 69 to 79: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 80, "", 0, ACS_CF_LineSide);
|
|
||||||
// 81 to 82: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 83, "", 0, ACS_CF_ClearLineSpecial);
|
|
||||||
// 84 to 85: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 86, "", 0, ACS_CF_EndPrint);
|
|
||||||
// 87 to 89: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 90, "", 0, ACS_CF_PlayerCount);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 91, "", 0, ACS_CF_GameType);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 92, "", 0, ACS_CF_GameSpeed);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 93, "", 0, ACS_CF_Timer);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 94, "", 2, ACS_CF_SectorSound);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 95, "", 2, ACS_CF_AmbientSound);
|
|
||||||
|
|
||||||
ACS_AddCodeDataCallFunc(env, 97, "", 4, ACS_CF_SetLineTexture);
|
|
||||||
|
|
||||||
ACS_AddCodeDataCallFunc(env, 99, "", 7, ACS_CF_SetLineSpecial);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 100, "", 3, ACS_CF_ThingSound);
|
|
||||||
ACS_AddCodeDataCallFunc(env, 101, "", 0, ACS_CF_EndPrintBold);
|
|
||||||
// 136 to 137: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 157: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 167 to 173: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 174, "BB", 0, ACS_CF_Random);
|
|
||||||
// 175 to 179: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 181 to 189: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 203 to 217: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 225 to 243: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 253: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 256 to 257: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 263: Implemented by ACSVM
|
|
||||||
ACS_AddCodeDataCallFunc(env, 270, "", 0, ACS_CF_EndLog);
|
|
||||||
// 273 to 275: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 291 to 325: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 330: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 349 to 361: Implemented by ACSVM
|
|
||||||
|
|
||||||
// 363 to 380: Implemented by ACSVM
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_EnvLoadModule(ACSVM_Environment *env, ACSVM_Module *module)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when a ACS
|
|
||||||
module is being loaded.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
module - The ACS module being loaded.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
true when successful, otherwise false.
|
|
||||||
Returning false will also call the
|
|
||||||
ACS_EnvReadError hook.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static bool ACS_EnvLoadModule(ACSVM_Environment *env, ACSVM_Module *module)
|
|
||||||
{
|
|
||||||
ACSVM_ModuleName name = ACSVM_Module_GetName(module);
|
|
||||||
const char *str = ACSVM_String_GetStr(name.s);
|
|
||||||
|
|
||||||
size_t lumpLen = 0;
|
|
||||||
|
|
||||||
ACSVM_Byte *data = NULL;
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
(void)env;
|
|
||||||
|
|
||||||
if (name.i == (size_t)LUMPERROR)
|
|
||||||
{
|
|
||||||
// No lump given for module.
|
|
||||||
CONS_Alert(CONS_ERROR, "Bad lump for ACS module \"%s\"\n", str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lumpLen = W_LumpLength(name.i);
|
|
||||||
|
|
||||||
if (W_IsLumpWad(name.i) == true || lumpLen == 0)
|
|
||||||
{
|
|
||||||
// The lump given is a virtual resource.
|
|
||||||
// Try to grab it from there.
|
|
||||||
virtres_t *vRes = vres_GetMap(name.i);
|
|
||||||
virtlump_t *vLump = vres_Find(vRes, "BEHAVIOR");
|
|
||||||
|
|
||||||
CONS_Printf("Attempting to load ACS module from map's virtual resource...\n");
|
|
||||||
|
|
||||||
if (vLump != NULL)
|
|
||||||
{
|
|
||||||
data = Z_Calloc(vLump->size, PU_STATIC, NULL);
|
|
||||||
memcpy(data, vLump->data, vLump->size);
|
|
||||||
size = vLump->size;
|
|
||||||
CONS_Printf("Successfully found BEHAVIOR lump.\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CONS_Printf("No BEHAVIOR lump found.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// It's a real lump.
|
|
||||||
data = Z_Calloc(lumpLen, PU_STATIC, NULL);
|
|
||||||
W_ReadLump(name.i, data);
|
|
||||||
size = lumpLen;
|
|
||||||
CONS_Printf("Loading ACS module directly from lump.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data != NULL && size > 0)
|
|
||||||
{
|
|
||||||
CONS_Printf("Reading bytecode of ACS module...\n");
|
|
||||||
ret = ACSVM_Module_ReadBytecode(module, data, size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Unlike Hexen, BEHAVIOR is not required.
|
|
||||||
// Simply ignore in this instance.
|
|
||||||
CONS_Printf("No data received, ignoring...\n");
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Z_Free(data);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static bool ACS_EnvCheckTag(ACSVM_Environment const *env, ACSVM_Word type, ACSVM_Word tag)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Ran to determine
|
|
||||||
whenever or not a thread should still be
|
|
||||||
waiting on a tag movement.
|
|
||||||
See: TagWait, PolyWait.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
type - The kind of level data we're waiting on. See also: acs_tagType_e.
|
|
||||||
tag - The tag of said level data.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
true when the tag is done moving and
|
|
||||||
execution can continue, or false to keep
|
|
||||||
the thread paused.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static bool ACS_EnvCheckTag(ACSVM_Environment const *env, ACSVM_Word type, ACSVM_Word tag)
|
|
||||||
{
|
|
||||||
(void)env;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ACS_TAGTYPE_SECTOR:
|
|
||||||
{
|
|
||||||
INT32 secnum = -1;
|
|
||||||
|
|
||||||
TAG_ITER_SECTORS(tag, secnum)
|
|
||||||
{
|
|
||||||
sector_t *sec = §ors[secnum];
|
|
||||||
|
|
||||||
if (sec->floordata != NULL || sec->ceilingdata != NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ACS_TAGTYPE_POLYOBJ:
|
|
||||||
{
|
|
||||||
const polyobj_t *po = Polyobj_GetForNum(tag);
|
|
||||||
return (po == NULL || po->thinker == NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static ACSVM_Word ACS_EnvCallSpecial(ACSVM_Environment const *env, ACSVM_Thread *thread, ACSVM_Word spec, ACSVM_Word const *argV, ACSVM_Word argC)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Activates a special
|
|
||||||
function straight from the script rather than
|
|
||||||
a linedef.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
thread - The thread that is executing the special.
|
|
||||||
spec - The special ID to execute.
|
|
||||||
argV - Array containing the arguments given from the script.
|
|
||||||
argC - The number of entries in argV.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
1 when successful, otherwise 0.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static ACSVM_Word ACS_EnvCallSpecial(ACSVM_Environment *env, ACSVM_Thread *thread, ACSVM_Word spec, ACSVM_Word const *argV, ACSVM_Word argC)
|
|
||||||
{
|
|
||||||
activator_t *info = ACSVM_Thread_GetInfo(thread);
|
|
||||||
ACSVM_MapScope *map = ACSVM_Thread_GetScopeMap(thread);
|
|
||||||
|
|
||||||
INT32 args[NUMLINEARGS] = {0};
|
|
||||||
char *stringargs[NUMLINESTRINGARGS] = {0};
|
|
||||||
size_t numStringArgs = 0;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
(void)env;
|
|
||||||
|
|
||||||
// This needs manually set, as ACS just uses indicies in the
|
|
||||||
// compiled string table and not actual strings, and SRB2 has
|
|
||||||
// separate args and stringargs, so there's no way to
|
|
||||||
// properly distinguish them.
|
|
||||||
switch (spec)
|
|
||||||
{
|
|
||||||
case 442:
|
|
||||||
numStringArgs = 2;
|
|
||||||
break;
|
|
||||||
case 413:
|
|
||||||
case 414:
|
|
||||||
case 415:
|
|
||||||
case 423:
|
|
||||||
case 425:
|
|
||||||
case 443:
|
|
||||||
case 459:
|
|
||||||
case 461:
|
|
||||||
case 463:
|
|
||||||
case 469:
|
|
||||||
numStringArgs = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < numStringArgs; i++)
|
|
||||||
{
|
|
||||||
ACSVM_String *strPtr = ACSVM_MapScope_GetString(map, argV[i]);
|
|
||||||
const char *str = ACSVM_String_GetStr(strPtr);
|
|
||||||
size_t strLen = ACSVM_String_GetLen(strPtr);
|
|
||||||
|
|
||||||
stringargs[i] = Z_Malloc(strLen + 1, PU_STATIC, NULL);
|
|
||||||
M_Memcpy(stringargs[i], str, strLen + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < min(argC, NUMLINEARGS); i++)
|
|
||||||
{
|
|
||||||
args[i - numStringArgs] = argV[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
P_ProcessSpecial(info, spec, args, stringargs);
|
|
||||||
|
|
||||||
for (i = 0; i < numStringArgs; i++)
|
|
||||||
{
|
|
||||||
Z_Free(stringargs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_ThrDestruct(ACSVM_Thread *thread)
|
|
||||||
|
|
||||||
ACSVM Thread hook. Runs as the thread
|
|
||||||
is in the process of being destroyed.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
thread - The ACS thread data to destroy.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_ThrDestruct(ACSVM_Thread *thread)
|
|
||||||
{
|
|
||||||
activator_t *info = ACSVM_Thread_GetInfo(thread);
|
|
||||||
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
Z_Free(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_ThrStart(ACSVM_Thread *thread, void *data)
|
|
||||||
|
|
||||||
ACSVM Thread hook. Runs immediately after
|
|
||||||
an ACS thread has been started.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
thread - The ACS thread data.
|
|
||||||
data - ACS thread info, as a raw pointer.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
The newly created ACS thread.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_ThrStart(ACSVM_Thread *thread, void *data)
|
|
||||||
{
|
|
||||||
activator_t *activator = NULL;
|
|
||||||
|
|
||||||
ACSVM_Thread_SetResult(thread, 1);
|
|
||||||
|
|
||||||
if (data == NULL)
|
|
||||||
{
|
|
||||||
// Create an empty one, to reduce NULL checks.
|
|
||||||
// Might not be necessary.
|
|
||||||
activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
activator = (activator_t *)data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACSVM_Thread_SetInfo(thread, activator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static ACSVM_Thread *ACS_EnvAllocThread(ACSVM_Environment *env)
|
|
||||||
|
|
||||||
ACSVM Environment hook. Runs when an ACS
|
|
||||||
thread is being created. This is where
|
|
||||||
our own thread hooks are supposed to
|
|
||||||
be loaded.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
env - The ACS environment data.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
The newly created ACS thread.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static ACSVM_Thread *ACS_EnvAllocThread(ACSVM_Environment *env)
|
|
||||||
{
|
|
||||||
ACSVM_ThreadFuncs funcs = {0};
|
|
||||||
|
|
||||||
funcs.dtor = ACS_ThrDestruct;
|
|
||||||
funcs.start = ACS_ThrStart;
|
|
||||||
|
|
||||||
return ACSVM_AllocThread(env, &funcs, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Init(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_Init(void)
|
|
||||||
{
|
|
||||||
// Initialize ACS on engine start-up.
|
|
||||||
ACSVM_EnvironmentFuncs funcs = {0};
|
|
||||||
|
|
||||||
funcs.bad_alloc = ACS_EnvBadAlloc;
|
|
||||||
funcs.readError = ACS_EnvReadError;
|
|
||||||
funcs.serialError = ACS_EnvSerialError;
|
|
||||||
funcs.printKill = ACS_EnvThreadKilled;
|
|
||||||
funcs.ctor = ACS_EnvConstruct;
|
|
||||||
funcs.loadModule = ACS_EnvLoadModule;
|
|
||||||
funcs.checkTag = ACS_EnvCheckTag;
|
|
||||||
funcs.callSpecImpl = ACS_EnvCallSpecial;
|
|
||||||
funcs.allocThread = ACS_EnvAllocThread;
|
|
||||||
|
|
||||||
ACSenv = ACSVM_AllocEnvironment(&funcs, NULL);
|
|
||||||
|
|
||||||
I_AddExitFunc(ACS_Shutdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Shutdown(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_Shutdown(void)
|
|
||||||
{
|
|
||||||
// Delete ACS environment.
|
|
||||||
ACSVM_FreeEnvironment(ACSenv);
|
|
||||||
ACSenv = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_ResetHub(ACSVM_GlobalScope *global)
|
|
||||||
|
|
||||||
Shortcut function to quickly free the
|
|
||||||
only hub scope Ring Racers uses.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
global - The global scope to free the hub from.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_ResetHub(ACSVM_GlobalScope *global)
|
|
||||||
{
|
|
||||||
ACSVM_HubScope *hub = ACSVM_GlobalScope_GetHubScope(global, 0);
|
|
||||||
ACSVM_GlobalScope_FreeHubScope(global, hub);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void ACS_ResetMap(ACSVM_HubScope *hub)
|
|
||||||
|
|
||||||
Shortcut function to quickly free the
|
|
||||||
only map scope Ring Racers uses.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
hub - The hub scope to free the map from.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void ACS_ResetMap(ACSVM_HubScope *hub)
|
|
||||||
{
|
|
||||||
ACSVM_MapScope *map = ACSVM_HubScope_GetMapScope(hub, 0);
|
|
||||||
ACSVM_HubScope_FreeMapScope(hub, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_LoadLevelScripts(size_t mapID)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_LoadLevelScripts(size_t mapID)
|
|
||||||
{
|
|
||||||
ACSVM_Environment *env = ACSenv;
|
|
||||||
ACSVM_StringTable *strTab = ACSVM_Environment_GetStringTable(env);
|
|
||||||
|
|
||||||
ACSVM_GlobalScope *global = NULL;
|
|
||||||
ACSVM_HubScope *hub = NULL;
|
|
||||||
ACSVM_MapScope *map = NULL;
|
|
||||||
|
|
||||||
ACSVM_Module **modules = NULL;
|
|
||||||
size_t modules_len = 0;
|
|
||||||
size_t modules_size = 4;
|
|
||||||
|
|
||||||
global = ACSVM_Environment_GetGlobalScope(ACSenv, 0);
|
|
||||||
|
|
||||||
// Just some notes on how Hexen's scopes work, if anyone
|
|
||||||
// intends to implement proper hub logic:
|
|
||||||
|
|
||||||
// The integer is an ID for which hub / map it is,
|
|
||||||
// and instead sets active according to which ones
|
|
||||||
// should run, since you can go between them.
|
|
||||||
|
|
||||||
// But I didn't intend on implementing these features,
|
|
||||||
// since hubs aren't planned for Ring Racers (although
|
|
||||||
// they might be useful for SRB2), and I intentionally
|
|
||||||
// avoided implementing global ACS (since Lua would be
|
|
||||||
// a better language to do that kind of code).
|
|
||||||
|
|
||||||
// Since we literally only are using map scope, we can
|
|
||||||
// just free everything between every level. But if
|
|
||||||
// hubs are to be implemented, this logic would need
|
|
||||||
// to be far more sophisticated.
|
|
||||||
|
|
||||||
// Reset hub scope, even if we are not using it.
|
|
||||||
ACS_ResetHub(global);
|
|
||||||
hub = ACSVM_GlobalScope_GetHubScope(global, 0);
|
|
||||||
ACSVM_HubScope_SetActive(hub, true);
|
|
||||||
|
|
||||||
// Start up new map scope.
|
|
||||||
ACS_ResetMap(hub);
|
|
||||||
map = ACSVM_HubScope_GetMapScope(hub, 0); // This is where you'd put in mapID if you add hub support.
|
|
||||||
ACSVM_MapScope_SetActive(map, true);
|
|
||||||
|
|
||||||
// Allocate module list.
|
|
||||||
modules = Z_Calloc(modules_size * sizeof(ACSVM_Module *), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
// Insert BEHAVIOR lump into the list.
|
|
||||||
{
|
|
||||||
char const *str = mapheaderinfo[mapID]->lumpname;
|
|
||||||
size_t len = strlen(str);
|
|
||||||
size_t hash = ACSVM_StrHash(str, len);
|
|
||||||
|
|
||||||
ACSVM_ModuleName name = {0};
|
|
||||||
|
|
||||||
name.s = ACSVM_StringTable_GetStringByData(strTab, str, len, hash);
|
|
||||||
name.i = mapheaderinfo[mapID]->lumpnum;
|
|
||||||
|
|
||||||
if (modules_len >= modules_size)
|
|
||||||
{
|
|
||||||
modules_size *= 2;
|
|
||||||
modules = Z_Realloc(modules, modules_size * sizeof(ACSVM_Module *), PU_STATIC, &modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
modules[modules_len] = ACSVM_Environment_GetModule(env, name);
|
|
||||||
modules_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modules_len > 0)
|
|
||||||
{
|
|
||||||
// Register the modules with map scope.
|
|
||||||
ACSVM_MapScope_AddModules(map, modules, modules_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunPlayerEnterScript(player_t *player)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_RunPlayerEnterScript(player_t *player)
|
|
||||||
{
|
|
||||||
ACSVM_GlobalScope *global = NULL;
|
|
||||||
ACSVM_HubScope *hub = NULL;
|
|
||||||
ACSVM_MapScope *map = NULL;
|
|
||||||
|
|
||||||
activator_t *activator = NULL;
|
|
||||||
|
|
||||||
global = ACSVM_Environment_GetGlobalScope(ACSenv, 0);
|
|
||||||
hub = ACSVM_GlobalScope_GetHubScope(global, 0);
|
|
||||||
map = ACSVM_HubScope_GetMapScope(hub, 0);
|
|
||||||
|
|
||||||
activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
P_SetTarget(&activator->mo, player->mo);
|
|
||||||
|
|
||||||
ACSVM_MapScope_ScriptStartTypeForced(map, ACS_ST_ENTER, NULL, 0, ACSVM_AllocThreadInfo(activator), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunLevelStartScripts(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_RunLevelStartScripts(void)
|
|
||||||
{
|
|
||||||
ACSVM_GlobalScope *global = NULL;
|
|
||||||
ACSVM_HubScope *hub = NULL;
|
|
||||||
ACSVM_MapScope *map = NULL;
|
|
||||||
|
|
||||||
UINT8 i;
|
|
||||||
|
|
||||||
global = ACSVM_Environment_GetGlobalScope(ACSenv, 0);
|
|
||||||
hub = ACSVM_GlobalScope_GetHubScope(global, 0);
|
|
||||||
map = ACSVM_HubScope_GetMapScope(hub, 0);
|
|
||||||
|
|
||||||
// Start OPEN scripts.
|
|
||||||
ACSVM_MapScope_ScriptStartType(map, ACS_ST_OPEN, NULL, 0, NULL, NULL);
|
|
||||||
|
|
||||||
// Start ENTER scripts.
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
|
||||||
{
|
|
||||||
player_t *player = NULL;
|
|
||||||
|
|
||||||
if (playeringame[i] == false)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
player = &players[i];
|
|
||||||
if (player->spectator == true)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACS_RunPlayerEnterScript(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunLapScript(mobj_t *mo, line_t *line)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_RunLapScript(mobj_t *mo, line_t *line)
|
|
||||||
{
|
|
||||||
ACSVM_GlobalScope *global = NULL;
|
|
||||||
ACSVM_HubScope *hub = NULL;
|
|
||||||
ACSVM_MapScope *map = NULL;
|
|
||||||
|
|
||||||
activator_t *activator = NULL;
|
|
||||||
|
|
||||||
global = ACSVM_Environment_GetGlobalScope(ACSenv, 0);
|
|
||||||
hub = ACSVM_GlobalScope_GetHubScope(global, 0);
|
|
||||||
map = ACSVM_HubScope_GetMapScope(hub, 0);
|
|
||||||
|
|
||||||
activator = Z_Calloc(sizeof(activator_t), PU_STATIC, NULL);
|
|
||||||
|
|
||||||
P_SetTarget(&activator->mo, mo);
|
|
||||||
activator->line = line;
|
|
||||||
|
|
||||||
ACSVM_MapScope_ScriptStartTypeForced(map, ACS_ST_LAP, NULL, 0, ACSVM_AllocThreadInfo(activator), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Tick(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void ACS_Tick(void)
|
|
||||||
{
|
|
||||||
ACSVM_Environment *env = ACSenv;
|
|
||||||
|
|
||||||
if (ACSVM_Environment_HasActiveThread(env) == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ACSVM_Environment_Exec(env);
|
|
||||||
}
|
|
||||||
244
src/k_acs.h
244
src/k_acs.h
|
|
@ -1,244 +0,0 @@
|
||||||
// DR. ROBOTNIK'S RING RACERS
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity)
|
|
||||||
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
|
|
||||||
// Copyright (C) 2022 by Kart Krew
|
|
||||||
//
|
|
||||||
// This program is free software distributed under the
|
|
||||||
// terms of the GNU General Public License, version 2.
|
|
||||||
// See the 'LICENSE' file for more details.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/// \file k_acs.h
|
|
||||||
/// \brief Action Code Script implementation using ACSVM
|
|
||||||
|
|
||||||
#ifndef __K_ACS__
|
|
||||||
#define __K_ACS__
|
|
||||||
|
|
||||||
#include "doomtype.h"
|
|
||||||
#include "doomdef.h"
|
|
||||||
#include "p_mobj.h"
|
|
||||||
#include "r_defs.h"
|
|
||||||
#include "p_polyobj.h"
|
|
||||||
#include "d_player.h"
|
|
||||||
|
|
||||||
#include <CAPI/BinaryIO.h>
|
|
||||||
#include <CAPI/Environment.h>
|
|
||||||
#include <CAPI/Module.h>
|
|
||||||
#include <CAPI/PrintBuf.h>
|
|
||||||
#include <CAPI/Scope.h>
|
|
||||||
#include <CAPI/String.h>
|
|
||||||
#include <CAPI/Thread.h>
|
|
||||||
|
|
||||||
// Temp
|
|
||||||
ACSVM_String *ACSVM_MapScope_GetString(ACSVM_MapScope *map, ACSVM_Word index);
|
|
||||||
ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *activator);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Special global script types.
|
|
||||||
//
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ACS_ST_OPEN = 1, // OPEN: Runs once when the level starts.
|
|
||||||
ACS_ST_RESPAWN = 2, // RESPAWN: Runs when a player respawns.
|
|
||||||
ACS_ST_DEATH = 3, // DEATH: Runs when a player dies.
|
|
||||||
ACS_ST_ENTER = 4, // ENTER: Runs when a player enters the game; both on start of the level, and when un-spectating.
|
|
||||||
ACS_ST_LAP = 5, // LAP: Runs when a player's lap increases from crossing the finish line.
|
|
||||||
} acs_scriptType_e;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Script "waiting on tag" types.
|
|
||||||
//
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ACS_TAGTYPE_POLYOBJ,
|
|
||||||
ACS_TAGTYPE_SECTOR,
|
|
||||||
} acs_tagType_e;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Thread activator info
|
|
||||||
//
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
mobj_t *mo; // Object that activated this thread.
|
|
||||||
line_t *line; // Linedef that activated this thread.
|
|
||||||
UINT8 side; // Front / back side of said linedef.
|
|
||||||
sector_t *sector; // Sector that activated this thread.
|
|
||||||
polyobj_t *po; // Polyobject that activated this thread.
|
|
||||||
boolean fromLineSpecial; // Called from P_ProcessLineSpecial.
|
|
||||||
} activator_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
|
|
||||||
|
|
||||||
Runs a numbered special action. Can be called
|
|
||||||
by both linedefs and ACS scripts.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
activator - Struct containing information on what activated this special.
|
|
||||||
special - Special ID.
|
|
||||||
args - Array of the args.
|
|
||||||
stringargs - Array of the string args.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
ACSVM_Environment *ACS_GetEnvironment(void);
|
|
||||||
|
|
||||||
Returns the global ACS environment. This contains
|
|
||||||
all of the information about the ACS VM state.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
None
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
The ACS environment object.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
ACSVM_Environment *ACS_GetEnvironment(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Init(void);
|
|
||||||
|
|
||||||
Initializes the ACS environment. Handles creating
|
|
||||||
the VM, initializing its hooks, storing the
|
|
||||||
pointer for future reference, and adding the
|
|
||||||
shutdown function.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_Init(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Shutdown(void);
|
|
||||||
|
|
||||||
Frees the ACS environment, for when the game
|
|
||||||
is exited.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_Shutdown(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_LoadLevelScripts(size_t mapID);
|
|
||||||
|
|
||||||
Resets the ACS hub and map scopes to remove
|
|
||||||
existing running scripts, and inserts the new
|
|
||||||
level's ACS modules (BEHAVIOR lump) into
|
|
||||||
the environment.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
mapID: The map's number to read the BEHAVIOR
|
|
||||||
lump of.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
None
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_LoadLevelScripts(size_t mapID);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunPlayerEnterScript(player_t *player);
|
|
||||||
|
|
||||||
Runs the map's special script for a player
|
|
||||||
entering the game.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
player: The player to run the script for.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
None
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_RunPlayerEnterScript(player_t *player);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunLevelStartScripts(void);
|
|
||||||
|
|
||||||
Runs the map's special scripts for opening
|
|
||||||
the level, and for all players to enter
|
|
||||||
the game.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_RunLevelStartScripts(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_RunLapScript(mobj_t *mo, line_t *line);
|
|
||||||
|
|
||||||
Runs the map's special script for a player
|
|
||||||
crossing the finish line.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
player: The player to run the script for.
|
|
||||||
line: The finish line's linedef.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
None
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_RunLapScript(mobj_t *mo, line_t *line);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void ACS_Tick(void);
|
|
||||||
|
|
||||||
Executes all of the ACS environment's
|
|
||||||
currently active threads.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
void ACS_Tick(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
bool ACS_CF_???(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
|
|
||||||
These are the actual CallFuncs ran when ACS
|
|
||||||
is executed. Which CallFuncs are executed
|
|
||||||
is based on the indices from the compiled
|
|
||||||
data. ACS_EnvConstruct is where the link
|
|
||||||
between the byte code and the actual function
|
|
||||||
is made.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
thread: The ACS execution thread this action
|
|
||||||
is running on.
|
|
||||||
argV: An array of the action's arguments.
|
|
||||||
argC: The length of the argument array.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
Returns true if this function pauses the
|
|
||||||
thread's execution. Otherwise returns false.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
|
|
||||||
bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_TagWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_PolyWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_ClearLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_EndPrint(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_PlayerCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_GameType(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_GameSpeed(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_Timer(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_ThingSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_EndPrintBold(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
bool ACS_CF_EndLog(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __K_ACS__
|
|
||||||
|
|
@ -98,7 +98,7 @@
|
||||||
#include "k_brightmap.h"
|
#include "k_brightmap.h"
|
||||||
#include "k_director.h" // K_InitDirector
|
#include "k_director.h" // K_InitDirector
|
||||||
#include "k_specialstage.h"
|
#include "k_specialstage.h"
|
||||||
#include "k_acs.h"
|
#include "acs/interface.h"
|
||||||
|
|
||||||
// Replay names have time
|
// Replay names have time
|
||||||
#if !defined (UNDER_CE)
|
#if !defined (UNDER_CE)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
#include "console.h" // CON_LogMessage
|
#include "console.h" // CON_LogMessage
|
||||||
#include "k_respawn.h"
|
#include "k_respawn.h"
|
||||||
#include "k_terrain.h"
|
#include "k_terrain.h"
|
||||||
#include "k_acs.h"
|
#include "acs/interface.h"
|
||||||
|
|
||||||
#ifdef HW3SOUND
|
#ifdef HW3SOUND
|
||||||
#include "hardware/hw3sound.h"
|
#include "hardware/hw3sound.h"
|
||||||
|
|
|
||||||
15
src/p_spec.h
15
src/p_spec.h
|
|
@ -559,6 +559,21 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
|
||||||
|
|
||||||
void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing);
|
void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Special activation info
|
||||||
|
//
|
||||||
|
struct activator_t
|
||||||
|
{
|
||||||
|
mobj_t *mo;
|
||||||
|
line_t *line;
|
||||||
|
UINT8 side;
|
||||||
|
sector_t *sector;
|
||||||
|
polyobj_t *po;
|
||||||
|
boolean fromLineSpecial; // Backwards compat for ACS
|
||||||
|
};
|
||||||
|
|
||||||
|
void P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, char **stringargs);
|
||||||
|
|
||||||
void P_SetupSignExit(player_t *player);
|
void P_SetupSignExit(player_t *player);
|
||||||
|
|
||||||
boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec);
|
boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
#include "k_waypoint.h"
|
#include "k_waypoint.h"
|
||||||
#include "k_director.h"
|
#include "k_director.h"
|
||||||
#include "k_specialstage.h"
|
#include "k_specialstage.h"
|
||||||
#include "k_acs.h"
|
#include "acs/interface.h"
|
||||||
|
|
||||||
tic_t leveltime;
|
tic_t leveltime;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,7 @@ TYPEDEF (disappear_t);
|
||||||
TYPEDEF (fade_t);
|
TYPEDEF (fade_t);
|
||||||
TYPEDEF (fadecolormap_t);
|
TYPEDEF (fadecolormap_t);
|
||||||
TYPEDEF (planedisplace_t);
|
TYPEDEF (planedisplace_t);
|
||||||
|
TYPEDEF (activator_t);
|
||||||
|
|
||||||
// r_data.h
|
// r_data.h
|
||||||
TYPEDEF (lumplist_t);
|
TYPEDEF (lumplist_t);
|
||||||
|
|
|
||||||
1
thirdparty/CMakeLists.txt
vendored
1
thirdparty/CMakeLists.txt
vendored
|
|
@ -634,7 +634,6 @@ if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}")
|
||||||
add_library(acsvm "${SRB2_INTERNAL_LIBRARY_TYPE}" ${acsvm_SOURCES})
|
add_library(acsvm "${SRB2_INTERNAL_LIBRARY_TYPE}" ${acsvm_SOURCES})
|
||||||
|
|
||||||
target_compile_features(acsvm PRIVATE cxx_std_11)
|
target_compile_features(acsvm PRIVATE cxx_std_11)
|
||||||
#target_compile_definitions(ACSVM_SHARED="${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
|
|
||||||
|
|
||||||
target_include_directories(acsvm INTERFACE "${acsvm_SOURCE_DIR}")
|
target_include_directories(acsvm INTERFACE "${acsvm_SOURCE_DIR}")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue