Keep track of script activators

Can supply the activating object, line, line side, polyobject, and (added for SRB2) sector.
This commit is contained in:
Sally Coolatta 2022-10-08 05:39:56 -04:00
parent a315482aa4
commit 93cdac681b
8 changed files with 327 additions and 6 deletions

View file

@ -155,6 +155,14 @@ ACSVM_Thread *ACSVM_AllocThread(ACSVM_Environment *env,
return new(std::nothrow) ACSVM_Thread(env, *funcs, data);
}
//
// ACSVM_AllocThreadInfo
//
ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *data)
{
return new(std::nothrow) ACSVM_ThreadInfo(data);
}
//
// ACSVM_ThreadFromVoid
//

View file

@ -133,6 +133,8 @@ public:
ACSVM_Thread *ACSVM_AllocThread(ACSVM_Environment *env,
ACSVM_ThreadFuncs const *funcs, void *data);
ACSVM_ThreadInfo *ACSVM_AllocThreadInfo(void *data);
ACSVM_Thread *ACSVM_ThreadFromVoid(void *thread);
void ACSVM_Thread_Exec(ACSVM_Thread *thread);

Binary file not shown.

View file

@ -60,6 +60,7 @@
#include "k_boss.h"
#include "k_bot.h"
#include "doomstat.h"
#include "k_acs.h"
#ifdef HAVE_DISCORDRPC
#include "discord.h"
@ -2877,6 +2878,8 @@ void G_DoReborn(INT32 playernum)
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}
ACS_RunPlayerEnterScript(player);
}
void G_AddPlayer(INT32 playernum)

View file

@ -30,6 +30,7 @@
#include "p_local.h"
#include "deh_tables.h"
#include "fastcmp.h"
#include "hu_stuff.h"
/*--------------------------------------------------
static bool ACS_GetMobjTypeFromString(const char *word, mobjtype_t *type)
@ -115,6 +116,34 @@ static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type)
return false;
}
/*--------------------------------------------------
static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread)
Helper function for many print functions.
Returns whenever or not the activator of the
thread is a display player or not.
Input Arguments:-
thread: The thread we're exeucting on.
Return:-
true if it's for a display player,
otherwise false.
--------------------------------------------------*/
static bool ACS_ActivatorIsLocal(ACSVM_Thread *thread)
{
acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread);
if ((info != NULL)
&& (info->mo != NULL && P_MobjWasRemoved(info->mo) == false)
&& (info->mo->player != NULL))
{
return P_IsDisplayPlayer(info->mo->player);
}
return false;
}
/*--------------------------------------------------
bool ACS_CF_Random(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
@ -315,10 +344,29 @@ bool ACS_CF_ChangeCeiling(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Wo
return false;
}
/*--------------------------------------------------
bool ACS_CF_LineSide(ACSVM_Thread *thread, ACSVM_Word const *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)
{
acs_threadinfo_t *info = (acs_threadinfo_t *)ACSVM_Thread_GetInfo(thread);
(void)argV;
(void)argC;
ACSVM_Thread_DataStk_Push(thread, info->side);
return false;
}
/*--------------------------------------------------
bool ACS_CF_EndPrint(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
ACS wrapper for CONS_Printf.
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)
{
@ -328,7 +376,13 @@ bool ACS_CF_EndPrint(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word ar
(void)argC;
buf = ACSVM_Thread_GetPrintBuf(thread);
CONS_Printf("%s\n", ACSVM_PrintBuf_GetData(buf));
if (ACS_ActivatorIsLocal(thread) == true)
{
HU_SetCEchoDuration(5);
HU_DoCEcho(ACSVM_PrintBuf_GetData(buf));
}
ACSVM_PrintBuf_Drop(buf);
return false;
@ -411,3 +465,52 @@ bool ACS_CF_Timer(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC)
ACSVM_Thread_DataStk_Push(thread, leveltime);
return false;
}
/*--------------------------------------------------
bool ACS_CF_EndPrintBold(ACSVM_Thread *thread, ACSVM_Word const *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)
{
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);
return false;
}
/*--------------------------------------------------
bool ACS_CF_EndLog(ACSVM_Thread *thread, ACSVM_Word const *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)
{
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));
}
ACSVM_PrintBuf_Drop(buf);
return false;
}

View file

@ -23,6 +23,10 @@
#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"
@ -227,7 +231,7 @@ static void ACS_EnvConstruct(ACSVM_Environment *env)
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
// 84 to 85: Implemented by ACSVM
@ -237,6 +241,8 @@ static void ACS_EnvConstruct(ACSVM_Environment *env)
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, 101, "", 0, ACS_CF_EndPrintBold);
// 136 to 137: Implemented by ACSVM
// 157: Implemented by ACSVM
@ -256,7 +262,7 @@ static void ACS_EnvConstruct(ACSVM_Environment *env)
// 256 to 257: Implemented by ACSVM
// 263: Implemented by ACSVM
ACS_AddCodeDataCallFunc(env, 270, "", 0, ACS_CF_EndPrint);
ACS_AddCodeDataCallFunc(env, 270, "", 0, ACS_CF_EndLog);
// 273 to 275: Implemented by ACSVM
// 291 to 325: Implemented by ACSVM
@ -404,6 +410,85 @@ static bool ACS_EnvCheckTag(ACSVM_Environment const *env, ACSVM_Word type, ACSVM
return true;
}
/*--------------------------------------------------
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)
{
acs_threadinfo_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)
{
acs_threadinfo_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(acs_threadinfo_t), PU_STATIC, NULL);
}
else
{
activator = (acs_threadinfo_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)
@ -421,6 +506,7 @@ void ACS_Init(void)
funcs.ctor = ACS_EnvConstruct;
funcs.loadModule = ACS_EnvLoadModule;
funcs.checkTag = ACS_EnvCheckTag;
funcs.allocThread = ACS_EnvAllocThread;
ACSenv = ACSVM_AllocEnvironment(&funcs, NULL);
@ -520,7 +606,7 @@ void ACS_LoadLevelScripts(size_t mapID)
// Start up new map scope.
ACS_ResetMap(hub);
map = ACSVM_HubScope_GetMapScope(hub, 0);
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.
@ -552,9 +638,70 @@ void ACS_LoadLevelScripts(size_t mapID)
// 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;
acs_threadinfo_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(acs_threadinfo_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, 1, NULL, 0, NULL, NULL);
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);
}
}
/*--------------------------------------------------

View file

@ -16,6 +16,10 @@
#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"
@ -25,6 +29,9 @@
#include "CAPI/String.h"
#include "CAPI/Thread.h"
//
// Special global script types.
//
typedef enum
{
ACS_ST_OPEN = 1, // OPEN: Runs once when the level starts.
@ -33,12 +40,27 @@ typedef enum
ACS_ST_ENTER = 4, // ENTER: Runs when a player enters the game; both on start of the level, and when un-spectating.
} 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.
} acs_threadinfo_t;
/*--------------------------------------------------
ACSVM_Environment *ACS_GetEnvironment(void);
@ -96,6 +118,33 @@ void ACS_Shutdown(void);
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_Tick(void);
@ -105,6 +154,7 @@ void ACS_LoadLevelScripts(size_t mapID);
void ACS_Tick(void);
/*--------------------------------------------------
bool ACS_CF_???(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word argC);
@ -132,11 +182,14 @@ bool ACS_CF_TagWait(ACSVM_Thread *thread, ACSVM_Word const *argV, ACSVM_Word arg
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_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_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__

View file

@ -4333,12 +4333,17 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (!fromnetsave) // uglier hack
{ // to make a newly loaded level start on the second frame.
INT32 buf = gametic % BACKUPTICS;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
}
P_PreTicker(2);
ACS_RunLevelStartScripts();
P_MapStart(); // just in case MapLoad modifies tmthing
LUA_HookInt(gamemap, HOOK(MapLoad));
P_MapEnd(); // just in case MapLoad modifies tmthing