summaryrefslogtreecommitdiff
path: root/src/hexen/p_acs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hexen/p_acs.c')
-rw-r--r--src/hexen/p_acs.c1884
1 files changed, 1884 insertions, 0 deletions
diff --git a/src/hexen/p_acs.c b/src/hexen/p_acs.c
new file mode 100644
index 00000000..9ca9f6af
--- /dev/null
+++ b/src/hexen/p_acs.c
@@ -0,0 +1,1884 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 1993-2008 Raven Software
+// Copyright(C) 2008 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+
+
+// HEADER FILES ------------------------------------------------------------
+
+#include "h2def.h"
+#include "m_random.h"
+#include "s_sound.h"
+#include "i_swap.h"
+#include "i_system.h"
+#include "p_local.h"
+
+// MACROS ------------------------------------------------------------------
+
+#define SCRIPT_CONTINUE 0
+#define SCRIPT_STOP 1
+#define SCRIPT_TERMINATE 2
+#define OPEN_SCRIPTS_BASE 1000
+#define PRINT_BUFFER_SIZE 256
+#define GAME_SINGLE_PLAYER 0
+#define GAME_NET_COOPERATIVE 1
+#define GAME_NET_DEATHMATCH 2
+#define TEXTURE_TOP 0
+#define TEXTURE_MIDDLE 1
+#define TEXTURE_BOTTOM 2
+#define S_DROP ACScript->stackPtr--
+#define S_POP ACScript->stack[--ACScript->stackPtr]
+#define S_PUSH(x) ACScript->stack[ACScript->stackPtr++] = x
+
+// TYPES -------------------------------------------------------------------
+
+typedef struct
+{
+ int marker;
+ int infoOffset;
+ int code;
+} PACKEDATTR acsHeader_t;
+
+// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
+
+// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
+
+// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
+
+static void StartOpenACS(int number, int infoIndex, int *address);
+static void ScriptFinished(int number);
+static boolean TagBusy(int tag);
+static boolean AddToACSStore(int map, int number, byte * args);
+static int GetACSIndex(int number);
+static void Push(int value);
+static int Pop(void);
+static int Top(void);
+static void Drop(void);
+
+static int CmdNOP(void);
+static int CmdTerminate(void);
+static int CmdSuspend(void);
+static int CmdPushNumber(void);
+static int CmdLSpec1(void);
+static int CmdLSpec2(void);
+static int CmdLSpec3(void);
+static int CmdLSpec4(void);
+static int CmdLSpec5(void);
+static int CmdLSpec1Direct(void);
+static int CmdLSpec2Direct(void);
+static int CmdLSpec3Direct(void);
+static int CmdLSpec4Direct(void);
+static int CmdLSpec5Direct(void);
+static int CmdAdd(void);
+static int CmdSubtract(void);
+static int CmdMultiply(void);
+static int CmdDivide(void);
+static int CmdModulus(void);
+static int CmdEQ(void);
+static int CmdNE(void);
+static int CmdLT(void);
+static int CmdGT(void);
+static int CmdLE(void);
+static int CmdGE(void);
+static int CmdAssignScriptVar(void);
+static int CmdAssignMapVar(void);
+static int CmdAssignWorldVar(void);
+static int CmdPushScriptVar(void);
+static int CmdPushMapVar(void);
+static int CmdPushWorldVar(void);
+static int CmdAddScriptVar(void);
+static int CmdAddMapVar(void);
+static int CmdAddWorldVar(void);
+static int CmdSubScriptVar(void);
+static int CmdSubMapVar(void);
+static int CmdSubWorldVar(void);
+static int CmdMulScriptVar(void);
+static int CmdMulMapVar(void);
+static int CmdMulWorldVar(void);
+static int CmdDivScriptVar(void);
+static int CmdDivMapVar(void);
+static int CmdDivWorldVar(void);
+static int CmdModScriptVar(void);
+static int CmdModMapVar(void);
+static int CmdModWorldVar(void);
+static int CmdIncScriptVar(void);
+static int CmdIncMapVar(void);
+static int CmdIncWorldVar(void);
+static int CmdDecScriptVar(void);
+static int CmdDecMapVar(void);
+static int CmdDecWorldVar(void);
+static int CmdGoto(void);
+static int CmdIfGoto(void);
+static int CmdDrop(void);
+static int CmdDelay(void);
+static int CmdDelayDirect(void);
+static int CmdRandom(void);
+static int CmdRandomDirect(void);
+static int CmdThingCount(void);
+static int CmdThingCountDirect(void);
+static int CmdTagWait(void);
+static int CmdTagWaitDirect(void);
+static int CmdPolyWait(void);
+static int CmdPolyWaitDirect(void);
+static int CmdChangeFloor(void);
+static int CmdChangeFloorDirect(void);
+static int CmdChangeCeiling(void);
+static int CmdChangeCeilingDirect(void);
+static int CmdRestart(void);
+static int CmdAndLogical(void);
+static int CmdOrLogical(void);
+static int CmdAndBitwise(void);
+static int CmdOrBitwise(void);
+static int CmdEorBitwise(void);
+static int CmdNegateLogical(void);
+static int CmdLShift(void);
+static int CmdRShift(void);
+static int CmdUnaryMinus(void);
+static int CmdIfNotGoto(void);
+static int CmdLineSide(void);
+static int CmdScriptWait(void);
+static int CmdScriptWaitDirect(void);
+static int CmdClearLineSpecial(void);
+static int CmdCaseGoto(void);
+static int CmdBeginPrint(void);
+static int CmdEndPrint(void);
+static int CmdPrintString(void);
+static int CmdPrintNumber(void);
+static int CmdPrintCharacter(void);
+static int CmdPlayerCount(void);
+static int CmdGameType(void);
+static int CmdGameSkill(void);
+static int CmdTimer(void);
+static int CmdSectorSound(void);
+static int CmdAmbientSound(void);
+static int CmdSoundSequence(void);
+static int CmdSetLineTexture(void);
+static int CmdSetLineBlocking(void);
+static int CmdSetLineSpecial(void);
+static int CmdThingSound(void);
+static int CmdEndPrintBold(void);
+
+static void ThingCount(int type, int tid);
+
+// EXTERNAL DATA DECLARATIONS ----------------------------------------------
+
+// PUBLIC DATA DEFINITIONS -------------------------------------------------
+
+int ACScriptCount;
+byte *ActionCodeBase;
+acsInfo_t *ACSInfo;
+int MapVars[MAX_ACS_MAP_VARS];
+int WorldVars[MAX_ACS_WORLD_VARS];
+acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker
+
+// PRIVATE DATA DEFINITIONS ------------------------------------------------
+
+static acs_t *ACScript;
+static int *PCodePtr;
+static byte SpecArgs[8];
+static int ACStringCount;
+static char **ACStrings;
+static char PrintBuffer[PRINT_BUFFER_SIZE];
+static acs_t *NewScript;
+
+static int (*PCodeCmds[]) (void) =
+{
+CmdNOP,
+ CmdTerminate,
+ CmdSuspend,
+ CmdPushNumber,
+ CmdLSpec1,
+ CmdLSpec2,
+ CmdLSpec3,
+ CmdLSpec4,
+ CmdLSpec5,
+ CmdLSpec1Direct,
+ CmdLSpec2Direct,
+ CmdLSpec3Direct,
+ CmdLSpec4Direct,
+ CmdLSpec5Direct,
+ CmdAdd,
+ CmdSubtract,
+ CmdMultiply,
+ CmdDivide,
+ CmdModulus,
+ CmdEQ,
+ CmdNE,
+ CmdLT,
+ CmdGT,
+ CmdLE,
+ CmdGE,
+ CmdAssignScriptVar,
+ CmdAssignMapVar,
+ CmdAssignWorldVar,
+ CmdPushScriptVar,
+ CmdPushMapVar,
+ CmdPushWorldVar,
+ CmdAddScriptVar,
+ CmdAddMapVar,
+ CmdAddWorldVar,
+ CmdSubScriptVar,
+ CmdSubMapVar,
+ CmdSubWorldVar,
+ CmdMulScriptVar,
+ CmdMulMapVar,
+ CmdMulWorldVar,
+ CmdDivScriptVar,
+ CmdDivMapVar,
+ CmdDivWorldVar,
+ CmdModScriptVar,
+ CmdModMapVar,
+ CmdModWorldVar,
+ CmdIncScriptVar,
+ CmdIncMapVar,
+ CmdIncWorldVar,
+ CmdDecScriptVar,
+ CmdDecMapVar,
+ CmdDecWorldVar,
+ CmdGoto,
+ CmdIfGoto,
+ CmdDrop,
+ CmdDelay,
+ CmdDelayDirect,
+ CmdRandom,
+ CmdRandomDirect,
+ CmdThingCount,
+ CmdThingCountDirect,
+ CmdTagWait,
+ CmdTagWaitDirect,
+ CmdPolyWait,
+ CmdPolyWaitDirect,
+ CmdChangeFloor,
+ CmdChangeFloorDirect,
+ CmdChangeCeiling,
+ CmdChangeCeilingDirect,
+ CmdRestart,
+ CmdAndLogical,
+ CmdOrLogical,
+ CmdAndBitwise,
+ CmdOrBitwise,
+ CmdEorBitwise,
+ CmdNegateLogical,
+ CmdLShift,
+ CmdRShift,
+ CmdUnaryMinus,
+ CmdIfNotGoto,
+ CmdLineSide,
+ CmdScriptWait,
+ CmdScriptWaitDirect,
+ CmdClearLineSpecial,
+ CmdCaseGoto,
+ CmdBeginPrint,
+ CmdEndPrint,
+ CmdPrintString,
+ CmdPrintNumber,
+ CmdPrintCharacter,
+ CmdPlayerCount,
+ CmdGameType,
+ CmdGameSkill,
+ CmdTimer,
+ CmdSectorSound,
+ CmdAmbientSound,
+ CmdSoundSequence,
+ CmdSetLineTexture,
+ CmdSetLineBlocking,
+ CmdSetLineSpecial, CmdThingSound, CmdEndPrintBold};
+
+// CODE --------------------------------------------------------------------
+
+//==========================================================================
+//
+// P_LoadACScripts
+//
+//==========================================================================
+
+void P_LoadACScripts(int lump)
+{
+ int i;
+ int *buffer;
+ acsHeader_t *header;
+ acsInfo_t *info;
+
+ header = W_CacheLumpNum(lump, PU_LEVEL);
+ ActionCodeBase = (byte *) header;
+ buffer = (int *) ((byte *) header + LONG(header->infoOffset));
+
+ ACScriptCount = LONG(*buffer);
+ ++buffer;
+
+ if (ACScriptCount == 0)
+ { // Empty behavior lump
+ return;
+ }
+
+ ACSInfo = Z_Malloc(ACScriptCount * sizeof(acsInfo_t), PU_LEVEL, 0);
+ memset(ACSInfo, 0, ACScriptCount * sizeof(acsInfo_t));
+ for (i = 0, info = ACSInfo; i < ACScriptCount; i++, info++)
+ {
+ info->number = LONG(*buffer);
+ ++buffer;
+
+ info->address = (int *) ((byte *) ActionCodeBase + LONG(*buffer));
+ ++buffer;
+
+ info->argCount = LONG(*buffer);
+ ++buffer;
+
+ if (info->number >= OPEN_SCRIPTS_BASE)
+ { // Auto-activate
+ info->number -= OPEN_SCRIPTS_BASE;
+ StartOpenACS(info->number, i, info->address);
+ info->state = ASTE_RUNNING;
+ }
+ else
+ {
+ info->state = ASTE_INACTIVE;
+ }
+ }
+ ACStringCount = LONG(*buffer);
+ ++buffer;
+
+ ACStrings = Z_Malloc(ACStringCount * sizeof(char *), PU_LEVEL, NULL);
+
+ for (i=0; i<ACStringCount; ++i)
+ {
+ ACStrings[i] = (char *) ActionCodeBase + LONG(buffer[i]);
+ }
+
+ memset(MapVars, 0, sizeof(MapVars));
+}
+
+//==========================================================================
+//
+// StartOpenACS
+//
+//==========================================================================
+
+static void StartOpenACS(int number, int infoIndex, int *address)
+{
+ acs_t *script;
+
+ script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
+ memset(script, 0, sizeof(acs_t));
+ script->number = number;
+
+ // World objects are allotted 1 second for initialization
+ script->delayCount = 35;
+
+ script->infoIndex = infoIndex;
+ script->ip = address;
+ script->thinker.function = T_InterpretACS;
+ P_AddThinker(&script->thinker);
+}
+
+//==========================================================================
+//
+// P_CheckACSStore
+//
+// Scans the ACS store and executes all scripts belonging to the current
+// map.
+//
+//==========================================================================
+
+void P_CheckACSStore(void)
+{
+ acsstore_t *store;
+
+ for (store = ACSStore; store->map != 0; store++)
+ {
+ if (store->map == gamemap)
+ {
+ P_StartACS(store->script, 0, store->args, NULL, NULL, 0);
+ if (NewScript)
+ {
+ NewScript->delayCount = 35;
+ }
+ store->map = -1;
+ }
+ }
+}
+
+//==========================================================================
+//
+// P_StartACS
+//
+//==========================================================================
+
+static char ErrorMsg[128];
+
+boolean P_StartACS(int number, int map, byte * args, mobj_t * activator,
+ line_t * line, int side)
+{
+ int i;
+ acs_t *script;
+ int infoIndex;
+ aste_t *statePtr;
+
+ NewScript = NULL;
+ if (map && map != gamemap)
+ { // Add to the script store
+ return AddToACSStore(map, number, args);
+ }
+ infoIndex = GetACSIndex(number);
+ if (infoIndex == -1)
+ { // Script not found
+ //I_Error("P_StartACS: Unknown script number %d", number);
+ sprintf(ErrorMsg, "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number);
+ P_SetMessage(&players[consoleplayer], ErrorMsg, true);
+ }
+ statePtr = &ACSInfo[infoIndex].state;
+ if (*statePtr == ASTE_SUSPENDED)
+ { // Resume a suspended script
+ *statePtr = ASTE_RUNNING;
+ return true;
+ }
+ if (*statePtr != ASTE_INACTIVE)
+ { // Script is already executing
+ return false;
+ }
+ script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
+ memset(script, 0, sizeof(acs_t));
+ script->number = number;
+ script->infoIndex = infoIndex;
+ script->activator = activator;
+ script->line = line;
+ script->side = side;
+ script->ip = ACSInfo[infoIndex].address;
+ script->thinker.function = T_InterpretACS;
+ for (i = 0; i < ACSInfo[infoIndex].argCount; i++)
+ {
+ script->vars[i] = args[i];
+ }
+ *statePtr = ASTE_RUNNING;
+ P_AddThinker(&script->thinker);
+ NewScript = script;
+ return true;
+}
+
+//==========================================================================
+//
+// AddToACSStore
+//
+//==========================================================================
+
+static boolean AddToACSStore(int map, int number, byte * args)
+{
+ int i;
+ int index;
+
+ index = -1;
+ for (i = 0; ACSStore[i].map != 0; i++)
+ {
+ if (ACSStore[i].script == number && ACSStore[i].map == map)
+ { // Don't allow duplicates
+ return false;
+ }
+ if (index == -1 && ACSStore[i].map == -1)
+ { // Remember first empty slot
+ index = i;
+ }
+ }
+ if (index == -1)
+ { // Append required
+ if (i == MAX_ACS_STORE)
+ {
+ I_Error("AddToACSStore: MAX_ACS_STORE (%d) exceeded.",
+ MAX_ACS_STORE);
+ }
+ index = i;
+ ACSStore[index + 1].map = 0;
+ }
+ ACSStore[index].map = map;
+ ACSStore[index].script = number;
+ memcpy(ACSStore[index].args, args, sizeof(int));
+ return true;
+}
+
+//==========================================================================
+//
+// P_StartLockedACS
+//
+//==========================================================================
+
+
+boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side)
+{
+ int i;
+ int lock;
+ byte newArgs[5];
+ char LockedBuffer[80];
+
+ extern char *TextKeyMessages[11];
+
+ lock = args[4];
+ if (!mo->player)
+ {
+ return false;
+ }
+ if (lock)
+ {
+ if (!(mo->player->keys & (1 << (lock - 1))))
+ {
+ sprintf(LockedBuffer, "YOU NEED THE %s\n",
+ TextKeyMessages[lock - 1]);
+ P_SetMessage(mo->player, LockedBuffer, true);
+ S_StartSound(mo, SFX_DOOR_LOCKED);
+ return false;
+ }
+ }
+ for (i = 0; i < 4; i++)
+ {
+ newArgs[i] = args[i];
+ }
+ newArgs[4] = 0;
+ return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo, line, side);
+}
+
+//==========================================================================
+//
+// P_TerminateACS
+//
+//==========================================================================
+
+boolean P_TerminateACS(int number, int map)
+{
+ int infoIndex;
+
+ infoIndex = GetACSIndex(number);
+ if (infoIndex == -1)
+ { // Script not found
+ return false;
+ }
+ if (ACSInfo[infoIndex].state == ASTE_INACTIVE
+ || ACSInfo[infoIndex].state == ASTE_TERMINATING)
+ { // States that disallow termination
+ return false;
+ }
+ ACSInfo[infoIndex].state = ASTE_TERMINATING;
+ return true;
+}
+
+//==========================================================================
+//
+// P_SuspendACS
+//
+//==========================================================================
+
+boolean P_SuspendACS(int number, int map)
+{
+ int infoIndex;
+
+ infoIndex = GetACSIndex(number);
+ if (infoIndex == -1)
+ { // Script not found
+ return false;
+ }
+ if (ACSInfo[infoIndex].state == ASTE_INACTIVE
+ || ACSInfo[infoIndex].state == ASTE_SUSPENDED
+ || ACSInfo[infoIndex].state == ASTE_TERMINATING)
+ { // States that disallow suspension
+ return false;
+ }
+ ACSInfo[infoIndex].state = ASTE_SUSPENDED;
+ return true;
+}
+
+//==========================================================================
+//
+// P_Init
+//
+//==========================================================================
+
+void P_ACSInitNewGame(void)
+{
+ memset(WorldVars, 0, sizeof(WorldVars));
+ memset(ACSStore, 0, sizeof(ACSStore));
+}
+
+//==========================================================================
+//
+// T_InterpretACS
+//
+//==========================================================================
+
+void T_InterpretACS(acs_t * script)
+{
+ int cmd;
+ int action;
+
+ if (ACSInfo[script->infoIndex].state == ASTE_TERMINATING)
+ {
+ ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
+ ScriptFinished(ACScript->number);
+ P_RemoveThinker(&ACScript->thinker);
+ return;
+ }
+ if (ACSInfo[script->infoIndex].state != ASTE_RUNNING)
+ {
+ return;
+ }
+ if (script->delayCount)
+ {
+ script->delayCount--;
+ return;
+ }
+ ACScript = script;
+ PCodePtr = ACScript->ip;
+
+ do
+ {
+ cmd = LONG(*PCodePtr);
+ ++PCodePtr;
+
+ action = PCodeCmds[cmd] ();
+ } while (action == SCRIPT_CONTINUE);
+
+ ACScript->ip = PCodePtr;
+
+ if (action == SCRIPT_TERMINATE)
+ {
+ ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
+ ScriptFinished(ACScript->number);
+ P_RemoveThinker(&ACScript->thinker);
+ }
+}
+
+//==========================================================================
+//
+// P_TagFinished
+//
+//==========================================================================
+
+void P_TagFinished(int tag)
+{
+ int i;
+
+ if (TagBusy(tag) == true)
+ {
+ return;
+ }
+ for (i = 0; i < ACScriptCount; i++)
+ {
+ if (ACSInfo[i].state == ASTE_WAITINGFORTAG
+ && ACSInfo[i].waitValue == tag)
+ {
+ ACSInfo[i].state = ASTE_RUNNING;
+ }
+ }
+}
+
+//==========================================================================
+//
+// P_PolyobjFinished
+//
+//==========================================================================
+
+void P_PolyobjFinished(int po)
+{
+ int i;
+
+ if (PO_Busy(po) == true)
+ {
+ return;
+ }
+ for (i = 0; i < ACScriptCount; i++)
+ {
+ if (ACSInfo[i].state == ASTE_WAITINGFORPOLY
+ && ACSInfo[i].waitValue == po)
+ {
+ ACSInfo[i].state = ASTE_RUNNING;
+ }
+ }
+}
+
+//==========================================================================
+//
+// ScriptFinished
+//
+//==========================================================================
+
+static void ScriptFinished(int number)
+{
+ int i;
+
+ for (i = 0; i < ACScriptCount; i++)
+ {
+ if (ACSInfo[i].state == ASTE_WAITINGFORSCRIPT
+ && ACSInfo[i].waitValue == number)
+ {
+ ACSInfo[i].state = ASTE_RUNNING;
+ }
+ }
+}
+
+//==========================================================================
+//
+// TagBusy
+//
+//==========================================================================
+
+static boolean TagBusy(int tag)
+{
+ int sectorIndex;
+
+ sectorIndex = -1;
+ while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
+ {
+ if (sectors[sectorIndex].specialdata)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//==========================================================================
+//
+// GetACSIndex
+//
+// Returns the index of a script number. Returns -1 if the script number
+// is not found.
+//
+//==========================================================================
+
+static int GetACSIndex(int number)
+{
+ int i;
+
+ for (i = 0; i < ACScriptCount; i++)
+ {
+ if (ACSInfo[i].number == number)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+//==========================================================================
+//
+// Push
+//
+//==========================================================================
+
+static void Push(int value)
+{
+ ACScript->stack[ACScript->stackPtr++] = value;
+}
+
+//==========================================================================
+//
+// Pop
+//
+//==========================================================================
+
+static int Pop(void)
+{
+ return ACScript->stack[--ACScript->stackPtr];
+}
+
+//==========================================================================
+//
+// Top
+//
+//==========================================================================
+
+static int Top(void)
+{
+ return ACScript->stack[ACScript->stackPtr - 1];
+}
+
+//==========================================================================
+//
+// Drop
+//
+//==========================================================================
+
+static void Drop(void)
+{
+ ACScript->stackPtr--;
+}
+
+//==========================================================================
+//
+// P-Code Commands
+//
+//==========================================================================
+
+static int CmdNOP(void)
+{
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdTerminate(void)
+{
+ return SCRIPT_TERMINATE;
+}
+
+static int CmdSuspend(void)
+{
+ ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED;
+ return SCRIPT_STOP;
+}
+
+static int CmdPushNumber(void)
+{
+ Push(LONG(*PCodePtr));
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec1(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = Pop();
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec2(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[1] = Pop();
+ SpecArgs[0] = Pop();
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec3(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[2] = Pop();
+ SpecArgs[1] = Pop();
+ SpecArgs[0] = Pop();
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec4(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[3] = Pop();
+ SpecArgs[2] = Pop();
+ SpecArgs[1] = Pop();
+ SpecArgs[0] = Pop();
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec5(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[4] = Pop();
+ SpecArgs[3] = Pop();
+ SpecArgs[2] = Pop();
+ SpecArgs[1] = Pop();
+ SpecArgs[0] = Pop();
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec1Direct(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = LONG(*PCodePtr);
+ ++PCodePtr;
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec2Direct(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[1] = LONG(*PCodePtr);
+ ++PCodePtr;
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec3Direct(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[1] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[2] = LONG(*PCodePtr);
+ ++PCodePtr;
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec4Direct(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[1] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[2] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[3] = LONG(*PCodePtr);
+ ++PCodePtr;
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLSpec5Direct(void)
+{
+ int special;
+
+ special = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[0] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[1] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[2] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[3] = LONG(*PCodePtr);
+ ++PCodePtr;
+ SpecArgs[4] = LONG(*PCodePtr);
+ ++PCodePtr;
+ P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
+ ACScript->side, ACScript->activator);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAdd(void)
+{
+ Push(Pop() + Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSubtract(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() - operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdMultiply(void)
+{
+ Push(Pop() * Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDivide(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() / operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdModulus(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() % operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdEQ(void)
+{
+ Push(Pop() == Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdNE(void)
+{
+ Push(Pop() != Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLT(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() < operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdGT(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() > operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLE(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() <= operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdGE(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() >= operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAssignScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] = Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAssignMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] = Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAssignWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] = Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPushScriptVar(void)
+{
+ Push(ACScript->vars[LONG(*PCodePtr)]);
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPushMapVar(void)
+{
+ Push(MapVars[LONG(*PCodePtr)]);
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPushWorldVar(void)
+{
+ Push(WorldVars[LONG(*PCodePtr)]);
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAddScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] += Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAddMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] += Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAddWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] += Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSubScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] -= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSubMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] -= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSubWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] -= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdMulScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] *= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdMulMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] *= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdMulWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] *= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDivScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] /= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDivMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] /= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDivWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] /= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdModScriptVar(void)
+{
+ ACScript->vars[LONG(*PCodePtr)] %= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdModMapVar(void)
+{
+ MapVars[LONG(*PCodePtr)] %= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdModWorldVar(void)
+{
+ WorldVars[LONG(*PCodePtr)] %= Pop();
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdIncScriptVar(void)
+{
+ ++ACScript->vars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdIncMapVar(void)
+{
+ ++MapVars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdIncWorldVar(void)
+{
+ ++WorldVars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDecScriptVar(void)
+{
+ --ACScript->vars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDecMapVar(void)
+{
+ --MapVars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDecWorldVar(void)
+{
+ --WorldVars[LONG(*PCodePtr)];
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdGoto(void)
+{
+ PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdIfGoto(void)
+{
+ if (Pop() != 0)
+ {
+ PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
+ }
+ else
+ {
+ ++PCodePtr;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDrop(void)
+{
+ Drop();
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdDelay(void)
+{
+ ACScript->delayCount = Pop();
+ return SCRIPT_STOP;
+}
+
+static int CmdDelayDirect(void)
+{
+ ACScript->delayCount = LONG(*PCodePtr);
+ ++PCodePtr;
+ return SCRIPT_STOP;
+}
+
+static int CmdRandom(void)
+{
+ int low;
+ int high;
+
+ high = Pop();
+ low = Pop();
+ Push(low + (P_Random() % (high - low + 1)));
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdRandomDirect(void)
+{
+ int low;
+ int high;
+
+ low = LONG(*PCodePtr);
+ ++PCodePtr;
+ high = LONG(*PCodePtr);
+ ++PCodePtr;
+ Push(low + (P_Random() % (high - low + 1)));
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdThingCount(void)
+{
+ int tid;
+
+ tid = Pop();
+ ThingCount(Pop(), tid);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdThingCountDirect(void)
+{
+ int type;
+
+ type = LONG(*PCodePtr);
+ ++PCodePtr;
+ ThingCount(type, LONG(*PCodePtr));
+ ++PCodePtr;
+ return SCRIPT_CONTINUE;
+}
+
+static void ThingCount(int type, int tid)
+{
+ int count;
+ int searcher;
+ mobj_t *mobj;
+ mobjtype_t moType;
+ thinker_t *think;
+
+ if (!(type + tid))
+ { // Nothing to count
+ return;
+ }
+ moType = TranslateThingType[type];
+ count = 0;
+ searcher = -1;
+ if (tid)
+ { // Count TID things
+ while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
+ {
+ if (type == 0)
+ { // Just count TIDs
+ count++;
+ }
+ else if (moType == mobj->type)
+ {
+ if (mobj->flags & MF_COUNTKILL && mobj->health <= 0)
+ { // Don't count dead monsters
+ continue;
+ }
+ count++;
+ }
+ }
+ }
+ else
+ { // Count only types
+ for (think = thinkercap.next; think != &thinkercap;
+ think = think->next)
+ {
+ if (think->function != P_MobjThinker)
+ { // Not a mobj thinker
+ continue;
+ }
+ mobj = (mobj_t *) think;
+ if (mobj->type != moType)
+ { // Doesn't match
+ continue;
+ }
+ if (mobj->flags & MF_COUNTKILL && mobj->health <= 0)
+ { // Don't count dead monsters
+ continue;
+ }
+ count++;
+ }
+ }
+ Push(count);
+}
+
+static int CmdTagWait(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = Pop();
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
+ return SCRIPT_STOP;
+}
+
+static int CmdTagWaitDirect(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
+ ++PCodePtr;
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
+ return SCRIPT_STOP;
+}
+
+static int CmdPolyWait(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = Pop();
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
+ return SCRIPT_STOP;
+}
+
+static int CmdPolyWaitDirect(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
+ ++PCodePtr;
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
+ return SCRIPT_STOP;
+}
+
+static int CmdChangeFloor(void)
+{
+ int tag;
+ int flat;
+ int sectorIndex;
+
+ flat = R_FlatNumForName(ACStrings[Pop()]);
+ tag = Pop();
+ sectorIndex = -1;
+ while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
+ {
+ sectors[sectorIndex].floorpic = flat;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdChangeFloorDirect(void)
+{
+ int tag;
+ int flat;
+ int sectorIndex;
+
+ tag = LONG(*PCodePtr);
+ ++PCodePtr;
+ flat = R_FlatNumForName(ACStrings[LONG(*PCodePtr)]);
+ ++PCodePtr;
+ sectorIndex = -1;
+ while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
+ {
+ sectors[sectorIndex].floorpic = flat;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdChangeCeiling(void)
+{
+ int tag;
+ int flat;
+ int sectorIndex;
+
+ flat = R_FlatNumForName(ACStrings[Pop()]);
+ tag = Pop();
+ sectorIndex = -1;
+ while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
+ {
+ sectors[sectorIndex].ceilingpic = flat;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdChangeCeilingDirect(void)
+{
+ int tag;
+ int flat;
+ int sectorIndex;
+
+ tag = LONG(*PCodePtr);
+ ++PCodePtr;
+ flat = R_FlatNumForName(ACStrings[LONG(*PCodePtr)]);
+ ++PCodePtr;
+ sectorIndex = -1;
+ while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
+ {
+ sectors[sectorIndex].ceilingpic = flat;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdRestart(void)
+{
+ PCodePtr = ACSInfo[ACScript->infoIndex].address;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAndLogical(void)
+{
+ Push(Pop() && Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdOrLogical(void)
+{
+ Push(Pop() || Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAndBitwise(void)
+{
+ Push(Pop() & Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdOrBitwise(void)
+{
+ Push(Pop() | Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdEorBitwise(void)
+{
+ Push(Pop() ^ Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdNegateLogical(void)
+{
+ Push(!Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLShift(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() << operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdRShift(void)
+{
+ int operand2;
+
+ operand2 = Pop();
+ Push(Pop() >> operand2);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdUnaryMinus(void)
+{
+ Push(-Pop());
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdIfNotGoto(void)
+{
+ if (Pop() != 0)
+ {
+ ++PCodePtr;
+ }
+ else
+ {
+ PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdLineSide(void)
+{
+ Push(ACScript->side);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdScriptWait(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = Pop();
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
+ return SCRIPT_STOP;
+}
+
+static int CmdScriptWaitDirect(void)
+{
+ ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
+ ++PCodePtr;
+ ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
+ return SCRIPT_STOP;
+}
+
+static int CmdClearLineSpecial(void)
+{
+ if (ACScript->line)
+ {
+ ACScript->line->special = 0;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdCaseGoto(void)
+{
+ int value;
+
+ value = LONG(*PCodePtr);
+ ++PCodePtr;
+
+ if (Top() == value)
+ {
+ PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
+ Drop();
+ }
+ else
+ {
+ ++PCodePtr;
+ }
+
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdBeginPrint(void)
+{
+ *PrintBuffer = 0;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdEndPrint(void)
+{
+ player_t *player;
+
+ if (ACScript->activator && ACScript->activator->player)
+ {
+ player = ACScript->activator->player;
+ }
+ else
+ {
+ player = &players[consoleplayer];
+ }
+ P_SetMessage(player, PrintBuffer, true);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdEndPrintBold(void)
+{
+ int i;
+
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (playeringame[i])
+ {
+ P_SetYellowMessage(&players[i], PrintBuffer, true);
+ }
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPrintString(void)
+{
+ strcat(PrintBuffer, ACStrings[Pop()]);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPrintNumber(void)
+{
+ char tempStr[16];
+
+ sprintf(tempStr, "%d", Pop());
+ strcat(PrintBuffer, tempStr);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPrintCharacter(void)
+{
+ char *bufferEnd;
+
+ bufferEnd = PrintBuffer + strlen(PrintBuffer);
+ *bufferEnd++ = Pop();
+ *bufferEnd = 0;
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdPlayerCount(void)
+{
+ int i;
+ int count;
+
+ count = 0;
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ count += playeringame[i];
+ }
+ Push(count);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdGameType(void)
+{
+ int gametype;
+
+ if (netgame == false)
+ {
+ gametype = GAME_SINGLE_PLAYER;
+ }
+ else if (deathmatch)
+ {
+ gametype = GAME_NET_DEATHMATCH;
+ }
+ else
+ {
+ gametype = GAME_NET_COOPERATIVE;
+ }
+ Push(gametype);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdGameSkill(void)
+{
+ Push(gameskill);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdTimer(void)
+{
+ Push(leveltime);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSectorSound(void)
+{
+ int volume;
+ mobj_t *mobj;
+
+ mobj = NULL;
+ if (ACScript->line)
+ {
+ mobj = (mobj_t *) & ACScript->line->frontsector->soundorg;
+ }
+ volume = Pop();
+ S_StartSoundAtVolume(mobj, S_GetSoundID(ACStrings[Pop()]), volume);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdThingSound(void)
+{
+ int tid;
+ int sound;
+ int volume;
+ mobj_t *mobj;
+ int searcher;
+
+ volume = Pop();
+ sound = S_GetSoundID(ACStrings[Pop()]);
+ tid = Pop();
+ searcher = -1;
+ while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
+ {
+ S_StartSoundAtVolume(mobj, sound, volume);
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdAmbientSound(void)
+{
+ int volume;
+
+ volume = Pop();
+ S_StartSoundAtVolume(NULL, S_GetSoundID(ACStrings[Pop()]), volume);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSoundSequence(void)
+{
+ mobj_t *mobj;
+
+ mobj = NULL;
+ if (ACScript->line)
+ {
+ mobj = (mobj_t *) & ACScript->line->frontsector->soundorg;
+ }
+ SN_StartSequenceName(mobj, ACStrings[Pop()]);
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSetLineTexture(void)
+{
+ line_t *line;
+ int lineTag;
+ int side;
+ int position;
+ int texture;
+ int searcher;
+
+ texture = R_TextureNumForName(ACStrings[Pop()]);
+ position = Pop();
+ side = Pop();
+ lineTag = Pop();
+ searcher = -1;
+ while ((line = P_FindLine(lineTag, &searcher)) != NULL)
+ {
+ if (position == TEXTURE_MIDDLE)
+ {
+ sides[line->sidenum[side]].midtexture = texture;
+ }
+ else if (position == TEXTURE_BOTTOM)
+ {
+ sides[line->sidenum[side]].bottomtexture = texture;
+ }
+ else
+ { // TEXTURE_TOP
+ sides[line->sidenum[side]].toptexture = texture;
+ }
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSetLineBlocking(void)
+{
+ line_t *line;
+ int lineTag;
+ boolean blocking;
+ int searcher;
+
+ blocking = Pop()? ML_BLOCKING : 0;
+ lineTag = Pop();
+ searcher = -1;
+ while ((line = P_FindLine(lineTag, &searcher)) != NULL)
+ {
+ line->flags = (line->flags & ~ML_BLOCKING) | blocking;
+ }
+ return SCRIPT_CONTINUE;
+}
+
+static int CmdSetLineSpecial(void)
+{
+ line_t *line;
+ int lineTag;
+ int special, arg1, arg2, arg3, arg4, arg5;
+ int searcher;
+
+ arg5 = Pop();
+ arg4 = Pop();
+ arg3 = Pop();
+ arg2 = Pop();
+ arg1 = Pop();
+ special = Pop();
+ lineTag = Pop();
+ searcher = -1;
+ while ((line = P_FindLine(lineTag, &searcher)) != NULL)
+ {
+ line->special = special;
+ line->arg1 = arg1;
+ line->arg2 = arg2;
+ line->arg3 = arg3;
+ line->arg4 = arg4;
+ line->arg5 = arg5;
+ }
+ return SCRIPT_CONTINUE;
+}