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_specialstage.c
|
||||
k_roulette.c
|
||||
k_acs.c
|
||||
k_acs-func.c
|
||||
)
|
||||
|
||||
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
|
||||
|
|
@ -515,6 +513,7 @@ endif()
|
|||
|
||||
add_subdirectory(sdl)
|
||||
add_subdirectory(objects)
|
||||
add_subdirectory(acs)
|
||||
add_subdirectory(tests)
|
||||
|
||||
# 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.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file k_acs-func.c
|
||||
/// \brief ACS CallFunc definitions
|
||||
/// \file call-funcs.cpp
|
||||
/// \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 "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_think.h"
|
||||
#include "p_mobj.h"
|
||||
#include "p_tick.h"
|
||||
#include "w_wad.h"
|
||||
#include "m_random.h"
|
||||
#include "g_game.h"
|
||||
#include "d_player.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
#include "p_polyobj.h"
|
||||
#include "taglist.h"
|
||||
#include "p_local.h"
|
||||
#include "deh_tables.h"
|
||||
#include "fastcmp.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;
|
||||
#include "../d_think.h"
|
||||
#include "../p_mobj.h"
|
||||
#include "../p_tick.h"
|
||||
#include "../w_wad.h"
|
||||
#include "../m_random.h"
|
||||
#include "../g_game.h"
|
||||
#include "../d_player.h"
|
||||
#include "../r_defs.h"
|
||||
#include "../r_state.h"
|
||||
#include "../p_polyobj.h"
|
||||
#include "../taglist.h"
|
||||
#include "../p_local.h"
|
||||
#include "../deh_tables.h"
|
||||
#include "../fastcmp.h"
|
||||
#include "../hu_stuff.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../r_textures.h"
|
||||
}
|
||||
|
||||
ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *activator)
|
||||
{
|
||||
(void)activator;
|
||||
return NULL;
|
||||
}
|
||||
#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 "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)
|
||||
|
||||
Helper function for ACS_CF_ThingCount. Gets
|
||||
Helper function for CallFunc_ThingCount. Gets
|
||||
an object type from a string.
|
||||
|
||||
Input Arguments:-
|
||||
|
|
@ -62,15 +69,13 @@ ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *activator)
|
|||
--------------------------------------------------*/
|
||||
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
||||
{
|
||||
mobjtype_t i;
|
||||
|
||||
if (fastncmp("MT_", word, 3))
|
||||
{
|
||||
// take off the MT_
|
||||
word += 3;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMMOBJFREESLOTS; i++)
|
||||
for (int i = 0; i < NUMMOBJFREESLOTS; 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]))
|
||||
{
|
||||
*type = MT_FIRSTFREESLOT+i;
|
||||
*type = static_cast<mobjtype_t>(static_cast<int>(MT_FIRSTFREESLOT) + i);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -111,8 +116,6 @@ static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
|
|||
--------------------------------------------------*/
|
||||
static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
||||
{
|
||||
sfxenum_t i;
|
||||
|
||||
if (fastncmp("SFX_", word, 4))
|
||||
{
|
||||
// take off the SFX_
|
||||
|
|
@ -124,11 +127,11 @@ static bool ACS_GetSFXFromString(const char *word, sfxenum_t *type)
|
|||
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))
|
||||
{
|
||||
*type = i;
|
||||
*type = static_cast<sfxenum_t>(i);
|
||||
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)
|
||||
|
||||
Helper function for ACS_CF_ThingCount.
|
||||
Helper function for CallFunc_ThingCount.
|
||||
Returns whenever or not to add this thing
|
||||
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.
|
||||
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,
|
||||
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)
|
||||
&& (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.
|
||||
--------------------------------------------------*/
|
||||
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 high = 0;
|
||||
|
|
@ -214,22 +217,22 @@ bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC
|
|||
low = argV[0];
|
||||
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;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
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
|
||||
type and tid. Both fields are optional;
|
||||
no type means indescriminate against type,
|
||||
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_String *str = NULL;
|
||||
ACSVM::MapScope *map = NULL;
|
||||
ACSVM::String *str = NULL;
|
||||
const char *className = NULL;
|
||||
size_t classLen = 0;
|
||||
|
||||
|
|
@ -240,11 +243,11 @@ bool ACS_CF_ThingCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
|||
|
||||
(void)argC;
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[0]);
|
||||
|
||||
className = ACSVM_String_GetStr(str);
|
||||
classLen = ACSVM_String_GetLen(str);
|
||||
className = str->str;
|
||||
classLen = str->len;
|
||||
|
||||
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
|
||||
// still aren't attached to mobj_t, only
|
||||
// mapthing_t. Fix this.
|
||||
CONS_Alert(CONS_WARNING,
|
||||
"ThingCount TID field not implemented -- waiting for mobj tags.\n"
|
||||
);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
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
|
||||
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;
|
||||
|
||||
st.state = ACSVM_ThreadState_WaitTag;
|
||||
st.data = argV[0];
|
||||
st.type = ACS_TAGTYPE_SECTOR;
|
||||
thread->state = {
|
||||
ACSVM::ThreadState::WaitTag,
|
||||
argV[0],
|
||||
ACS_TAGTYPE_SECTOR
|
||||
};
|
||||
|
||||
ACSVM_Thread_SetState(thread, st);
|
||||
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
|
||||
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;
|
||||
|
||||
st.state = ACSVM_ThreadState_WaitTag;
|
||||
st.data = argV[0];
|
||||
st.type = ACS_TAGTYPE_POLYOBJ;
|
||||
thread->state = {
|
||||
ACSVM::ThreadState::WaitTag,
|
||||
argV[0],
|
||||
ACS_TAGTYPE_POLYOBJ
|
||||
};
|
||||
|
||||
ACSVM_Thread_SetState(thread, st);
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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_String *str = NULL;
|
||||
const char *texName = NULL;
|
||||
ACSVM::MapScope *map = nullptr;
|
||||
ACSVM::String *str = nullptr;
|
||||
const char *texName = nullptr;
|
||||
|
||||
INT32 secnum = -1;
|
||||
mtag_t tag = 0;
|
||||
|
|
@ -355,9 +359,9 @@ bool ACS_CF_ChangeFloor(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
|||
|
||||
tag = argV[0];
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
||||
texName = ACSVM_String_GetStr(str);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[1]);
|
||||
texName = str->str;
|
||||
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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_String *str = NULL;
|
||||
ACSVM::MapScope *map = NULL;
|
||||
ACSVM::String *str = NULL;
|
||||
const char *texName = NULL;
|
||||
|
||||
INT32 secnum = -1;
|
||||
|
|
@ -386,9 +390,9 @@ bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wo
|
|||
|
||||
tag = argV[0];
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
||||
texName = ACSVM_String_GetStr(str);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[1]);
|
||||
texName = str->str;
|
||||
|
||||
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
|
||||
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)argC;
|
||||
|
||||
ACSVM_Thread_DataStk_Push(thread, info->side);
|
||||
thread->dataStk.push(info->side);
|
||||
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
|
||||
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)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
|
||||
version only prints if the activator is a
|
||||
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)argC;
|
||||
|
||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
||||
|
||||
if (ACS_ActivatorIsLocal(thread) == true)
|
||||
{
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(ACSVM_PrintBuf_GetData(buf));
|
||||
HU_DoCEcho(thread->printBuf.data());
|
||||
}
|
||||
|
||||
ACSVM_PrintBuf_Drop(buf);
|
||||
|
||||
thread->printBuf.drop();
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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 i;
|
||||
|
|
@ -497,78 +496,78 @@ bool ACS_CF_PlayerCount(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
|||
numPlayers++;
|
||||
}
|
||||
|
||||
ACSVM_Thread_DataStk_Push(thread, numPlayers);
|
||||
thread->dataStk.push(numPlayers);
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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)argC;
|
||||
|
||||
ACSVM_Thread_DataStk_Push(thread, gametype);
|
||||
thread->dataStk.push(gametype);
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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)argC;
|
||||
|
||||
ACSVM_Thread_DataStk_Push(thread, gamespeed);
|
||||
thread->dataStk.push(gamespeed);
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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)argC;
|
||||
|
||||
ACSVM_Thread_DataStk_Push(thread, leveltime);
|
||||
thread->dataStk.push(leveltime);
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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_String *str = NULL;
|
||||
ACSVM::MapScope *map = nullptr;
|
||||
ACSVM::String *str = nullptr;
|
||||
|
||||
const char *sfxName = NULL;
|
||||
const char *sfxName = nullptr;
|
||||
size_t sfxLen = 0;
|
||||
|
||||
sfxenum_t sfxId = sfx_None;
|
||||
INT32 vol = 0;
|
||||
mobj_t *origin = NULL;
|
||||
mobj_t *origin = nullptr;
|
||||
|
||||
(void)argC;
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[0]);
|
||||
|
||||
sfxName = ACSVM_String_GetStr(str);
|
||||
sfxLen = ACSVM_String_GetLen(str);
|
||||
sfxName = str->str;
|
||||
sfxLen = str->len;
|
||||
|
||||
if (sfxLen > 0)
|
||||
{
|
||||
|
|
@ -589,15 +588,15 @@ bool ACS_CF_SectorSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word
|
|||
|
||||
vol = argV[1];
|
||||
|
||||
if (info->sector != NULL)
|
||||
if (info->sector != nullptr)
|
||||
{
|
||||
// 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.
|
||||
origin = (void *)&info->line->frontsector->soundorg;
|
||||
origin = static_cast<mobj_t *>(static_cast<void *>(&info->line->frontsector->soundorg));
|
||||
}
|
||||
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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_String *str = NULL;
|
||||
ACSVM::MapScope *map = nullptr;
|
||||
ACSVM::String *str = nullptr;
|
||||
|
||||
const char *sfxName = NULL;
|
||||
const char *sfxName = nullptr;
|
||||
size_t sfxLen = 0;
|
||||
|
||||
sfxenum_t sfxId = sfx_None;
|
||||
|
|
@ -622,11 +621,11 @@ bool ACS_CF_AmbientSound(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wor
|
|||
|
||||
(void)argC;
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[0]);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[0]);
|
||||
|
||||
sfxName = ACSVM_String_GetStr(str);
|
||||
sfxLen = ACSVM_String_GetLen(str);
|
||||
sfxName = str->str;
|
||||
sfxLen = str->len;
|
||||
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
|
|
@ -663,14 +662,14 @@ enum
|
|||
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;
|
||||
UINT8 sideId = 0;
|
||||
UINT8 texPos = 0;
|
||||
|
||||
ACSVM_MapScope *map = NULL;
|
||||
ACSVM_String *str = NULL;
|
||||
ACSVM::MapScope *map = NULL;
|
||||
ACSVM::String *str = NULL;
|
||||
const char *texName = NULL;
|
||||
INT32 texId = LUMPERROR;
|
||||
|
||||
|
|
@ -682,9 +681,9 @@ bool ACS_CF_SetLineTexture(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
|||
sideId = (argV[1] & 1);
|
||||
texPos = argV[2];
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[4]);
|
||||
texName = ACSVM_String_GetStr(str);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[4]);
|
||||
texName = str->str;
|
||||
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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;
|
||||
INT32 spec = 0;
|
||||
|
|
@ -735,14 +734,14 @@ bool ACS_CF_SetLineSpecial(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_W
|
|||
tag = argV[0];
|
||||
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)
|
||||
{
|
||||
line_t *line = &lines[lineId];
|
||||
size_t i;
|
||||
|
||||
if (info->line != NULL && line == info->line)
|
||||
if (info->line != nullptr && line == info->line)
|
||||
{
|
||||
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.
|
||||
--------------------------------------------------*/
|
||||
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_String *str = NULL;
|
||||
ACSVM::MapScope *map = nullptr;
|
||||
ACSVM::String *str = nullptr;
|
||||
|
||||
const char *sfxName = NULL;
|
||||
const char *sfxName = nullptr;
|
||||
size_t sfxLen = 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];
|
||||
|
||||
map = ACSVM_Thread_GetScopeMap(thread);
|
||||
str = ACSVM_MapScope_GetString(map, argV[1]);
|
||||
map = thread->scopeMap;
|
||||
str = map->getString(argV[1]);
|
||||
|
||||
sfxName = ACSVM_String_GetStr(str);
|
||||
sfxLen = ACSVM_String_GetLen(str);
|
||||
sfxName = str->str;
|
||||
sfxLen = str->len;
|
||||
|
||||
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
|
||||
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)argC;
|
||||
|
||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
||||
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(ACSVM_PrintBuf_GetData(buf));
|
||||
|
||||
ACSVM_PrintBuf_Drop(buf);
|
||||
HU_DoCEcho(thread->printBuf.data());
|
||||
|
||||
thread->printBuf.drop();
|
||||
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.
|
||||
This version only prints if the activator
|
||||
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)argC;
|
||||
|
||||
buf = ACSVM_Thread_GetPrintBuf(thread);
|
||||
|
||||
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;
|
||||
}
|
||||
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 "m_random.h" // P_ClearRandom
|
||||
#include "k_specialstage.h"
|
||||
#include "k_acs.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
#ifdef CMAKECONFIG
|
||||
#include "config.h"
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
#include "k_specialstage.h"
|
||||
#include "k_bot.h"
|
||||
#include "doomstat.h"
|
||||
#include "k_acs.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
#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_director.h" // K_InitDirector
|
||||
#include "k_specialstage.h"
|
||||
#include "k_acs.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
// Replay names have time
|
||||
#if !defined (UNDER_CE)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
#include "console.h" // CON_LogMessage
|
||||
#include "k_respawn.h"
|
||||
#include "k_terrain.h"
|
||||
#include "k_acs.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#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);
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
||||
boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include "k_waypoint.h"
|
||||
#include "k_director.h"
|
||||
#include "k_specialstage.h"
|
||||
#include "k_acs.h"
|
||||
#include "acs/interface.h"
|
||||
|
||||
tic_t leveltime;
|
||||
|
||||
|
|
|
|||
|
|
@ -295,6 +295,7 @@ TYPEDEF (disappear_t);
|
|||
TYPEDEF (fade_t);
|
||||
TYPEDEF (fadecolormap_t);
|
||||
TYPEDEF (planedisplace_t);
|
||||
TYPEDEF (activator_t);
|
||||
|
||||
// r_data.h
|
||||
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})
|
||||
|
||||
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}")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue