hexen/Hexen Source/P_ACS.C

1783 lines
34 KiB
C++
Raw Normal View History

2008-09-04 00:00:00 +00:00
//**************************************************************************
//**
//** p_acs.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: p_acs.c,v $
//** $Revision: 1.31 $
//** $Date: 95/10/09 16:25:17 $
//** $Author: cjr $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "h2def.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;
} 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+header->infoOffset);
ACScriptCount = *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 = *buffer++;
info->address = (int *)((byte *)ActionCodeBase+*buffer++);
info->argCount = *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 = *buffer++;
ACStrings = (char **)buffer;
for(i = 0; i < ACStringCount; i++)
{
ACStrings[i] += (int)ActionCodeBase;
}
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;
*((int *)ACSStore[index].args) = *((int *)args);
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 = *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(*PCodePtr++);
return SCRIPT_CONTINUE;
}
static int CmdLSpec1(void)
{
int special;
special = *PCodePtr++;
SpecArgs[0] = Pop();
P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
ACScript->side, ACScript->activator);
return SCRIPT_CONTINUE;
}
static int CmdLSpec2(void)
{
int special;
special = *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 = *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 = *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 = *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 = *PCodePtr++;
SpecArgs[0] = *PCodePtr++;
P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
ACScript->side, ACScript->activator);
return SCRIPT_CONTINUE;
}
static int CmdLSpec2Direct(void)
{
int special;
special = *PCodePtr++;
SpecArgs[0] = *PCodePtr++;
SpecArgs[1] = *PCodePtr++;
P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
ACScript->side, ACScript->activator);
return SCRIPT_CONTINUE;
}
static int CmdLSpec3Direct(void)
{
int special;
special = *PCodePtr++;
SpecArgs[0] = *PCodePtr++;
SpecArgs[1] = *PCodePtr++;
SpecArgs[2] = *PCodePtr++;
P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
ACScript->side, ACScript->activator);
return SCRIPT_CONTINUE;
}
static int CmdLSpec4Direct(void)
{
int special;
special = *PCodePtr++;
SpecArgs[0] = *PCodePtr++;
SpecArgs[1] = *PCodePtr++;
SpecArgs[2] = *PCodePtr++;
SpecArgs[3] = *PCodePtr++;
P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
ACScript->side, ACScript->activator);
return SCRIPT_CONTINUE;
}
static int CmdLSpec5Direct(void)
{
int special;
special = *PCodePtr++;
SpecArgs[0] = *PCodePtr++;
SpecArgs[1] = *PCodePtr++;
SpecArgs[2] = *PCodePtr++;
SpecArgs[3] = *PCodePtr++;
SpecArgs[4] = *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[*PCodePtr++] = Pop();
return SCRIPT_CONTINUE;
}
static int CmdAssignMapVar(void)
{
MapVars[*PCodePtr++] = Pop();
return SCRIPT_CONTINUE;
}
static int CmdAssignWorldVar(void)
{
WorldVars[*PCodePtr++] = Pop();
return SCRIPT_CONTINUE;
}
static int CmdPushScriptVar(void)
{
Push(ACScript->vars[*PCodePtr++]);
return SCRIPT_CONTINUE;
}
static int CmdPushMapVar(void)
{
Push(MapVars[*PCodePtr++]);
return SCRIPT_CONTINUE;
}
static int CmdPushWorldVar(void)
{
Push(WorldVars[*PCodePtr++]);
return SCRIPT_CONTINUE;
}
static int CmdAddScriptVar(void)
{
ACScript->vars[*PCodePtr++] += Pop();
return SCRIPT_CONTINUE;
}
static int CmdAddMapVar(void)
{
MapVars[*PCodePtr++] += Pop();
return SCRIPT_CONTINUE;
}
static int CmdAddWorldVar(void)
{
WorldVars[*PCodePtr++] += Pop();
return SCRIPT_CONTINUE;
}
static int CmdSubScriptVar(void)
{
ACScript->vars[*PCodePtr++] -= Pop();
return SCRIPT_CONTINUE;
}
static int CmdSubMapVar(void)
{
MapVars[*PCodePtr++] -= Pop();
return SCRIPT_CONTINUE;
}
static int CmdSubWorldVar(void)
{
WorldVars[*PCodePtr++] -= Pop();
return SCRIPT_CONTINUE;
}
static int CmdMulScriptVar(void)
{
ACScript->vars[*PCodePtr++] *= Pop();
return SCRIPT_CONTINUE;
}
static int CmdMulMapVar(void)
{
MapVars[*PCodePtr++] *= Pop();
return SCRIPT_CONTINUE;
}
static int CmdMulWorldVar(void)
{
WorldVars[*PCodePtr++] *= Pop();
return SCRIPT_CONTINUE;
}
static int CmdDivScriptVar(void)
{
ACScript->vars[*PCodePtr++] /= Pop();
return SCRIPT_CONTINUE;
}
static int CmdDivMapVar(void)
{
MapVars[*PCodePtr++] /= Pop();
return SCRIPT_CONTINUE;
}
static int CmdDivWorldVar(void)
{
WorldVars[*PCodePtr++] /= Pop();
return SCRIPT_CONTINUE;
}
static int CmdModScriptVar(void)
{
ACScript->vars[*PCodePtr++] %= Pop();
return SCRIPT_CONTINUE;
}
static int CmdModMapVar(void)
{
MapVars[*PCodePtr++] %= Pop();
return SCRIPT_CONTINUE;
}
static int CmdModWorldVar(void)
{
WorldVars[*PCodePtr++] %= Pop();
return SCRIPT_CONTINUE;
}
static int CmdIncScriptVar(void)
{
ACScript->vars[*PCodePtr++]++;
return SCRIPT_CONTINUE;
}
static int CmdIncMapVar(void)
{
MapVars[*PCodePtr++]++;
return SCRIPT_CONTINUE;
}
static int CmdIncWorldVar(void)
{
WorldVars[*PCodePtr++]++;
return SCRIPT_CONTINUE;
}
static int CmdDecScriptVar(void)
{
ACScript->vars[*PCodePtr++]--;
return SCRIPT_CONTINUE;
}
static int CmdDecMapVar(void)
{
MapVars[*PCodePtr++]--;
return SCRIPT_CONTINUE;
}
static int CmdDecWorldVar(void)
{
WorldVars[*PCodePtr++]--;
return SCRIPT_CONTINUE;
}
static int CmdGoto(void)
{
PCodePtr = (int *)(ActionCodeBase+*PCodePtr);
return SCRIPT_CONTINUE;
}
static int CmdIfGoto(void)
{
if(Pop())
{
PCodePtr = (int *)(ActionCodeBase+*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 = *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 = *PCodePtr++;
high = *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 = *PCodePtr++;
ThingCount(type, *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 = *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 = *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 = *PCodePtr++;
flat = R_FlatNumForName(ACStrings[*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 = *PCodePtr++;
flat = R_FlatNumForName(ACStrings[*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())
{
PCodePtr++;
}
else
{
PCodePtr = (int *)(ActionCodeBase+*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 = *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)
{
if(Top() == *PCodePtr++)
{
PCodePtr = (int *)(ActionCodeBase+*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;
}