2 //**************************************************************************
4 //** p_acs.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
18 // MACROS ------------------------------------------------------------------
20 #define SCRIPT_CONTINUE 0
22 #define SCRIPT_TERMINATE 2
23 #define OPEN_SCRIPTS_BASE 1000
24 #define PRINT_BUFFER_SIZE 256
25 #define GAME_SINGLE_PLAYER 0
26 #define GAME_NET_COOPERATIVE 1
27 #define GAME_NET_DEATHMATCH 2
29 #define TEXTURE_MIDDLE 1
30 #define TEXTURE_BOTTOM 2
31 #define S_DROP ACScript->stackPtr--
32 #define S_POP ACScript->stack[--ACScript->stackPtr]
33 #define S_PUSH(x) ACScript->stack[ACScript->stackPtr++] = x
35 // TYPES -------------------------------------------------------------------
44 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
46 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
48 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
50 static void StartOpenACS(int number, int infoIndex, int *address);
51 static void ScriptFinished(int number);
52 static boolean TagBusy(int tag);
53 static boolean AddToACSStore(int map, int number, byte *args);
54 static int GetACSIndex(int number);
55 static void Push(int value);
58 static void Drop(void);
60 static int CmdNOP(void);
61 static int CmdTerminate(void);
62 static int CmdSuspend(void);
63 static int CmdPushNumber(void);
64 static int CmdLSpec1(void);
65 static int CmdLSpec2(void);
66 static int CmdLSpec3(void);
67 static int CmdLSpec4(void);
68 static int CmdLSpec5(void);
69 static int CmdLSpec1Direct(void);
70 static int CmdLSpec2Direct(void);
71 static int CmdLSpec3Direct(void);
72 static int CmdLSpec4Direct(void);
73 static int CmdLSpec5Direct(void);
74 static int CmdAdd(void);
75 static int CmdSubtract(void);
76 static int CmdMultiply(void);
77 static int CmdDivide(void);
78 static int CmdModulus(void);
79 static int CmdEQ(void);
80 static int CmdNE(void);
81 static int CmdLT(void);
82 static int CmdGT(void);
83 static int CmdLE(void);
84 static int CmdGE(void);
85 static int CmdAssignScriptVar(void);
86 static int CmdAssignMapVar(void);
87 static int CmdAssignWorldVar(void);
88 static int CmdPushScriptVar(void);
89 static int CmdPushMapVar(void);
90 static int CmdPushWorldVar(void);
91 static int CmdAddScriptVar(void);
92 static int CmdAddMapVar(void);
93 static int CmdAddWorldVar(void);
94 static int CmdSubScriptVar(void);
95 static int CmdSubMapVar(void);
96 static int CmdSubWorldVar(void);
97 static int CmdMulScriptVar(void);
98 static int CmdMulMapVar(void);
99 static int CmdMulWorldVar(void);
100 static int CmdDivScriptVar(void);
101 static int CmdDivMapVar(void);
102 static int CmdDivWorldVar(void);
103 static int CmdModScriptVar(void);
104 static int CmdModMapVar(void);
105 static int CmdModWorldVar(void);
106 static int CmdIncScriptVar(void);
107 static int CmdIncMapVar(void);
108 static int CmdIncWorldVar(void);
109 static int CmdDecScriptVar(void);
110 static int CmdDecMapVar(void);
111 static int CmdDecWorldVar(void);
112 static int CmdGoto(void);
113 static int CmdIfGoto(void);
114 static int CmdDrop(void);
115 static int CmdDelay(void);
116 static int CmdDelayDirect(void);
117 static int CmdRandom(void);
118 static int CmdRandomDirect(void);
119 static int CmdThingCount(void);
120 static int CmdThingCountDirect(void);
121 static int CmdTagWait(void);
122 static int CmdTagWaitDirect(void);
123 static int CmdPolyWait(void);
124 static int CmdPolyWaitDirect(void);
125 static int CmdChangeFloor(void);
126 static int CmdChangeFloorDirect(void);
127 static int CmdChangeCeiling(void);
128 static int CmdChangeCeilingDirect(void);
129 static int CmdRestart(void);
130 static int CmdAndLogical(void);
131 static int CmdOrLogical(void);
132 static int CmdAndBitwise(void);
133 static int CmdOrBitwise(void);
134 static int CmdEorBitwise(void);
135 static int CmdNegateLogical(void);
136 static int CmdLShift(void);
137 static int CmdRShift(void);
138 static int CmdUnaryMinus(void);
139 static int CmdIfNotGoto(void);
140 static int CmdLineSide(void);
141 static int CmdScriptWait(void);
142 static int CmdScriptWaitDirect(void);
143 static int CmdClearLineSpecial(void);
144 static int CmdCaseGoto(void);
145 static int CmdBeginPrint(void);
146 static int CmdEndPrint(void);
147 static int CmdPrintString(void);
148 static int CmdPrintNumber(void);
149 static int CmdPrintCharacter(void);
150 static int CmdPlayerCount(void);
151 static int CmdGameType(void);
152 static int CmdGameSkill(void);
153 static int CmdTimer(void);
154 static int CmdSectorSound(void);
155 static int CmdAmbientSound(void);
156 static int CmdSoundSequence(void);
157 static int CmdSetLineTexture(void);
158 static int CmdSetLineBlocking(void);
159 static int CmdSetLineSpecial(void);
160 static int CmdThingSound(void);
161 static int CmdEndPrintBold(void);
163 static void ThingCount(int type, int tid);
165 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
167 // PUBLIC DATA DEFINITIONS -------------------------------------------------
170 byte *ActionCodeBase;
172 int MapVars[MAX_ACS_MAP_VARS];
173 int WorldVars[MAX_ACS_WORLD_VARS];
174 acsstore_t ACSStore[MAX_ACS_STORE+1]; // +1 for termination marker
176 // PRIVATE DATA DEFINITIONS ------------------------------------------------
178 static acs_t *ACScript;
179 static int *PCodePtr;
180 static byte SpecArgs[8];
181 static int ACStringCount;
182 static char **ACStrings;
183 static char PrintBuffer[PRINT_BUFFER_SIZE];
184 static acs_t *NewScript;
186 static int (*PCodeCmds[])(void) =
254 CmdChangeFloorDirect,
256 CmdChangeCeilingDirect,
292 // CODE --------------------------------------------------------------------
294 //==========================================================================
298 //==========================================================================
300 void P_LoadACScripts(int lump)
307 header = W_CacheLumpNum(lump, PU_LEVEL);
308 ActionCodeBase = (byte *)header;
309 buffer = (int *)((byte *)header+header->infoOffset);
310 ACScriptCount = *buffer++;
311 if(ACScriptCount == 0)
312 { // Empty behavior lump
315 ACSInfo = Z_Malloc(ACScriptCount*sizeof(acsInfo_t), PU_LEVEL, 0);
316 memset(ACSInfo, 0, ACScriptCount*sizeof(acsInfo_t));
317 for(i = 0, info = ACSInfo; i < ACScriptCount; i++, info++)
319 info->number = *buffer++;
320 info->address = (int *)((byte *)ActionCodeBase+*buffer++);
321 info->argCount = *buffer++;
322 if(info->number >= OPEN_SCRIPTS_BASE)
324 info->number -= OPEN_SCRIPTS_BASE;
325 StartOpenACS(info->number, i, info->address);
326 info->state = ASTE_RUNNING;
330 info->state = ASTE_INACTIVE;
333 ACStringCount = *buffer++;
334 ACStrings = (char **)buffer;
335 for(i = 0; i < ACStringCount; i++)
337 ACStrings[i] += (int)ActionCodeBase;
339 memset(MapVars, 0, sizeof(MapVars));
342 //==========================================================================
346 //==========================================================================
348 static void StartOpenACS(int number, int infoIndex, int *address)
352 script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
353 memset(script, 0, sizeof(acs_t));
354 script->number = number;
356 // World objects are allotted 1 second for initialization
357 script->delayCount = 35;
359 script->infoIndex = infoIndex;
360 script->ip = address;
361 script->thinker.function = T_InterpretACS;
362 P_AddThinker(&script->thinker);
365 //==========================================================================
369 // Scans the ACS store and executes all scripts belonging to the current
372 //==========================================================================
374 void P_CheckACSStore(void)
378 for(store = ACSStore; store->map != 0; store++)
380 if(store->map == gamemap)
382 P_StartACS(store->script, 0, store->args, NULL, NULL, 0);
385 NewScript->delayCount = 35;
392 //==========================================================================
396 //==========================================================================
398 static char ErrorMsg[128];
400 boolean P_StartACS(int number, int map, byte *args, mobj_t *activator,
401 line_t *line, int side)
409 if(map && map != gamemap)
410 { // Add to the script store
411 return AddToACSStore(map, number, args);
413 infoIndex = GetACSIndex(number);
415 { // Script not found
416 //I_Error("P_StartACS: Unknown script number %d", number);
417 sprintf(ErrorMsg, "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number);
418 P_SetMessage(&players[consoleplayer], ErrorMsg, true);
420 statePtr = &ACSInfo[infoIndex].state;
421 if(*statePtr == ASTE_SUSPENDED)
422 { // Resume a suspended script
423 *statePtr = ASTE_RUNNING;
426 if(*statePtr != ASTE_INACTIVE)
427 { // Script is already executing
430 script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
431 memset(script, 0, sizeof(acs_t));
432 script->number = number;
433 script->infoIndex = infoIndex;
434 script->activator = activator;
437 script->ip = ACSInfo[infoIndex].address;
438 script->thinker.function = T_InterpretACS;
439 for(i = 0; i < ACSInfo[infoIndex].argCount; i++)
441 script->vars[i] = args[i];
443 *statePtr = ASTE_RUNNING;
444 P_AddThinker(&script->thinker);
449 //==========================================================================
453 //==========================================================================
455 static boolean AddToACSStore(int map, int number, byte *args)
461 for(i = 0; ACSStore[i].map != 0; i++)
463 if(ACSStore[i].script == number
464 && ACSStore[i].map == map)
465 { // Don't allow duplicates
468 if(index == -1 && ACSStore[i].map == -1)
469 { // Remember first empty slot
475 if(i == MAX_ACS_STORE)
477 I_Error("AddToACSStore: MAX_ACS_STORE (%d) exceeded.",
481 ACSStore[index+1].map = 0;
483 ACSStore[index].map = map;
484 ACSStore[index].script = number;
485 *((int *)ACSStore[index].args) = *((int *)args);
489 //==========================================================================
493 //==========================================================================
496 boolean P_StartLockedACS(line_t *line, byte *args, mobj_t *mo, int side)
501 char LockedBuffer[80];
503 extern char *TextKeyMessages[11];
512 if(!(mo->player->keys&(1<<(lock-1))))
514 sprintf(LockedBuffer, "YOU NEED THE %s\n",
515 TextKeyMessages[lock-1]);
516 P_SetMessage(mo->player, LockedBuffer, true);
517 S_StartSound(mo, SFX_DOOR_LOCKED);
521 for(i = 0; i < 4; i++)
523 newArgs[i] = args[i];
526 return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo,
530 //==========================================================================
534 //==========================================================================
536 boolean P_TerminateACS(int number, int map)
540 infoIndex = GetACSIndex(number);
542 { // Script not found
545 if(ACSInfo[infoIndex].state == ASTE_INACTIVE
546 || ACSInfo[infoIndex].state == ASTE_TERMINATING)
547 { // States that disallow termination
550 ACSInfo[infoIndex].state = ASTE_TERMINATING;
554 //==========================================================================
558 //==========================================================================
560 boolean P_SuspendACS(int number, int map)
564 infoIndex = GetACSIndex(number);
566 { // Script not found
569 if(ACSInfo[infoIndex].state == ASTE_INACTIVE
570 || ACSInfo[infoIndex].state == ASTE_SUSPENDED
571 || ACSInfo[infoIndex].state == ASTE_TERMINATING)
572 { // States that disallow suspension
575 ACSInfo[infoIndex].state = ASTE_SUSPENDED;
579 //==========================================================================
583 //==========================================================================
585 void P_ACSInitNewGame(void)
587 memset(WorldVars, 0, sizeof(WorldVars));
588 memset(ACSStore, 0, sizeof(ACSStore));
591 //==========================================================================
595 //==========================================================================
597 void T_InterpretACS(acs_t *script)
602 if(ACSInfo[script->infoIndex].state == ASTE_TERMINATING)
604 ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
605 ScriptFinished(ACScript->number);
606 P_RemoveThinker(&ACScript->thinker);
609 if(ACSInfo[script->infoIndex].state != ASTE_RUNNING)
613 if(script->delayCount)
615 script->delayCount--;
619 PCodePtr = ACScript->ip;
623 action = PCodeCmds[cmd]();
624 } while(action == SCRIPT_CONTINUE);
625 ACScript->ip = PCodePtr;
626 if(action == SCRIPT_TERMINATE)
628 ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
629 ScriptFinished(ACScript->number);
630 P_RemoveThinker(&ACScript->thinker);
634 //==========================================================================
638 //==========================================================================
640 void P_TagFinished(int tag)
644 if(TagBusy(tag) == true)
648 for(i = 0; i < ACScriptCount; i++)
650 if(ACSInfo[i].state == ASTE_WAITINGFORTAG
651 && ACSInfo[i].waitValue == tag)
653 ACSInfo[i].state = ASTE_RUNNING;
658 //==========================================================================
662 //==========================================================================
664 void P_PolyobjFinished(int po)
668 if(PO_Busy(po) == true)
672 for(i = 0; i < ACScriptCount; i++)
674 if(ACSInfo[i].state == ASTE_WAITINGFORPOLY
675 && ACSInfo[i].waitValue == po)
677 ACSInfo[i].state = ASTE_RUNNING;
682 //==========================================================================
686 //==========================================================================
688 static void ScriptFinished(int number)
692 for(i = 0; i < ACScriptCount; i++)
694 if(ACSInfo[i].state == ASTE_WAITINGFORSCRIPT
695 && ACSInfo[i].waitValue == number)
697 ACSInfo[i].state = ASTE_RUNNING;
702 //==========================================================================
706 //==========================================================================
708 static boolean TagBusy(int tag)
713 while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
715 if(sectors[sectorIndex].specialdata)
723 //==========================================================================
727 // Returns the index of a script number. Returns -1 if the script number
730 //==========================================================================
732 static int GetACSIndex(int number)
736 for(i = 0; i < ACScriptCount; i++)
738 if(ACSInfo[i].number == number)
746 //==========================================================================
750 //==========================================================================
752 static void Push(int value)
754 ACScript->stack[ACScript->stackPtr++] = value;
757 //==========================================================================
761 //==========================================================================
765 return ACScript->stack[--ACScript->stackPtr];
768 //==========================================================================
772 //==========================================================================
776 return ACScript->stack[ACScript->stackPtr-1];
779 //==========================================================================
783 //==========================================================================
785 static void Drop(void)
787 ACScript->stackPtr--;
790 //==========================================================================
794 //==========================================================================
796 static int CmdNOP(void)
798 return SCRIPT_CONTINUE;
801 static int CmdTerminate(void)
803 return SCRIPT_TERMINATE;
806 static int CmdSuspend(void)
808 ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED;
812 static int CmdPushNumber(void)
815 return SCRIPT_CONTINUE;
818 static int CmdLSpec1(void)
822 special = *PCodePtr++;
824 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
825 ACScript->side, ACScript->activator);
826 return SCRIPT_CONTINUE;
829 static int CmdLSpec2(void)
833 special = *PCodePtr++;
836 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
837 ACScript->side, ACScript->activator);
838 return SCRIPT_CONTINUE;
841 static int CmdLSpec3(void)
845 special = *PCodePtr++;
849 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
850 ACScript->side, ACScript->activator);
851 return SCRIPT_CONTINUE;
854 static int CmdLSpec4(void)
858 special = *PCodePtr++;
863 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
864 ACScript->side, ACScript->activator);
865 return SCRIPT_CONTINUE;
868 static int CmdLSpec5(void)
872 special = *PCodePtr++;
878 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
879 ACScript->side, ACScript->activator);
880 return SCRIPT_CONTINUE;
883 static int CmdLSpec1Direct(void)
887 special = *PCodePtr++;
888 SpecArgs[0] = *PCodePtr++;
889 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
890 ACScript->side, ACScript->activator);
891 return SCRIPT_CONTINUE;
894 static int CmdLSpec2Direct(void)
898 special = *PCodePtr++;
899 SpecArgs[0] = *PCodePtr++;
900 SpecArgs[1] = *PCodePtr++;
901 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
902 ACScript->side, ACScript->activator);
903 return SCRIPT_CONTINUE;
906 static int CmdLSpec3Direct(void)
910 special = *PCodePtr++;
911 SpecArgs[0] = *PCodePtr++;
912 SpecArgs[1] = *PCodePtr++;
913 SpecArgs[2] = *PCodePtr++;
914 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
915 ACScript->side, ACScript->activator);
916 return SCRIPT_CONTINUE;
919 static int CmdLSpec4Direct(void)
923 special = *PCodePtr++;
924 SpecArgs[0] = *PCodePtr++;
925 SpecArgs[1] = *PCodePtr++;
926 SpecArgs[2] = *PCodePtr++;
927 SpecArgs[3] = *PCodePtr++;
928 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
929 ACScript->side, ACScript->activator);
930 return SCRIPT_CONTINUE;
933 static int CmdLSpec5Direct(void)
937 special = *PCodePtr++;
938 SpecArgs[0] = *PCodePtr++;
939 SpecArgs[1] = *PCodePtr++;
940 SpecArgs[2] = *PCodePtr++;
941 SpecArgs[3] = *PCodePtr++;
942 SpecArgs[4] = *PCodePtr++;
943 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
944 ACScript->side, ACScript->activator);
945 return SCRIPT_CONTINUE;
948 static int CmdAdd(void)
951 return SCRIPT_CONTINUE;
954 static int CmdSubtract(void)
959 Push(Pop()-operand2);
960 return SCRIPT_CONTINUE;
963 static int CmdMultiply(void)
966 return SCRIPT_CONTINUE;
969 static int CmdDivide(void)
974 Push(Pop()/operand2);
975 return SCRIPT_CONTINUE;
978 static int CmdModulus(void)
983 Push(Pop()%operand2);
984 return SCRIPT_CONTINUE;
987 static int CmdEQ(void)
989 Push(Pop() == Pop());
990 return SCRIPT_CONTINUE;
993 static int CmdNE(void)
995 Push(Pop() != Pop());
996 return SCRIPT_CONTINUE;
999 static int CmdLT(void)
1004 Push(Pop() < operand2);
1005 return SCRIPT_CONTINUE;
1008 static int CmdGT(void)
1013 Push(Pop() > operand2);
1014 return SCRIPT_CONTINUE;
1017 static int CmdLE(void)
1022 Push(Pop() <= operand2);
1023 return SCRIPT_CONTINUE;
1026 static int CmdGE(void)
1031 Push(Pop() >= operand2);
1032 return SCRIPT_CONTINUE;
1035 static int CmdAssignScriptVar(void)
1037 ACScript->vars[*PCodePtr++] = Pop();
1038 return SCRIPT_CONTINUE;
1041 static int CmdAssignMapVar(void)
1043 MapVars[*PCodePtr++] = Pop();
1044 return SCRIPT_CONTINUE;
1047 static int CmdAssignWorldVar(void)
1049 WorldVars[*PCodePtr++] = Pop();
1050 return SCRIPT_CONTINUE;
1053 static int CmdPushScriptVar(void)
1055 Push(ACScript->vars[*PCodePtr++]);
1056 return SCRIPT_CONTINUE;
1059 static int CmdPushMapVar(void)
1061 Push(MapVars[*PCodePtr++]);
1062 return SCRIPT_CONTINUE;
1065 static int CmdPushWorldVar(void)
1067 Push(WorldVars[*PCodePtr++]);
1068 return SCRIPT_CONTINUE;
1071 static int CmdAddScriptVar(void)
1073 ACScript->vars[*PCodePtr++] += Pop();
1074 return SCRIPT_CONTINUE;
1077 static int CmdAddMapVar(void)
1079 MapVars[*PCodePtr++] += Pop();
1080 return SCRIPT_CONTINUE;
1083 static int CmdAddWorldVar(void)
1085 WorldVars[*PCodePtr++] += Pop();
1086 return SCRIPT_CONTINUE;
1089 static int CmdSubScriptVar(void)
1091 ACScript->vars[*PCodePtr++] -= Pop();
1092 return SCRIPT_CONTINUE;
1095 static int CmdSubMapVar(void)
1097 MapVars[*PCodePtr++] -= Pop();
1098 return SCRIPT_CONTINUE;
1101 static int CmdSubWorldVar(void)
1103 WorldVars[*PCodePtr++] -= Pop();
1104 return SCRIPT_CONTINUE;
1107 static int CmdMulScriptVar(void)
1109 ACScript->vars[*PCodePtr++] *= Pop();
1110 return SCRIPT_CONTINUE;
1113 static int CmdMulMapVar(void)
1115 MapVars[*PCodePtr++] *= Pop();
1116 return SCRIPT_CONTINUE;
1119 static int CmdMulWorldVar(void)
1121 WorldVars[*PCodePtr++] *= Pop();
1122 return SCRIPT_CONTINUE;
1125 static int CmdDivScriptVar(void)
1127 ACScript->vars[*PCodePtr++] /= Pop();
1128 return SCRIPT_CONTINUE;
1131 static int CmdDivMapVar(void)
1133 MapVars[*PCodePtr++] /= Pop();
1134 return SCRIPT_CONTINUE;
1137 static int CmdDivWorldVar(void)
1139 WorldVars[*PCodePtr++] /= Pop();
1140 return SCRIPT_CONTINUE;
1143 static int CmdModScriptVar(void)
1145 ACScript->vars[*PCodePtr++] %= Pop();
1146 return SCRIPT_CONTINUE;
1149 static int CmdModMapVar(void)
1151 MapVars[*PCodePtr++] %= Pop();
1152 return SCRIPT_CONTINUE;
1155 static int CmdModWorldVar(void)
1157 WorldVars[*PCodePtr++] %= Pop();
1158 return SCRIPT_CONTINUE;
1161 static int CmdIncScriptVar(void)
1163 ACScript->vars[*PCodePtr++]++;
1164 return SCRIPT_CONTINUE;
1167 static int CmdIncMapVar(void)
1169 MapVars[*PCodePtr++]++;
1170 return SCRIPT_CONTINUE;
1173 static int CmdIncWorldVar(void)
1175 WorldVars[*PCodePtr++]++;
1176 return SCRIPT_CONTINUE;
1179 static int CmdDecScriptVar(void)
1181 ACScript->vars[*PCodePtr++]--;
1182 return SCRIPT_CONTINUE;
1185 static int CmdDecMapVar(void)
1187 MapVars[*PCodePtr++]--;
1188 return SCRIPT_CONTINUE;
1191 static int CmdDecWorldVar(void)
1193 WorldVars[*PCodePtr++]--;
1194 return SCRIPT_CONTINUE;
1197 static int CmdGoto(void)
1199 PCodePtr = (int *)(ActionCodeBase+*PCodePtr);
1200 return SCRIPT_CONTINUE;
1203 static int CmdIfGoto(void)
1207 PCodePtr = (int *)(ActionCodeBase+*PCodePtr);
1213 return SCRIPT_CONTINUE;
1216 static int CmdDrop(void)
1219 return SCRIPT_CONTINUE;
1222 static int CmdDelay(void)
1224 ACScript->delayCount = Pop();
1228 static int CmdDelayDirect(void)
1230 ACScript->delayCount = *PCodePtr++;
1234 static int CmdRandom(void)
1241 Push(low+(P_Random()%(high-low+1)));
1242 return SCRIPT_CONTINUE;
1245 static int CmdRandomDirect(void)
1252 Push(low+(P_Random()%(high-low+1)));
1253 return SCRIPT_CONTINUE;
1256 static int CmdThingCount(void)
1261 ThingCount(Pop(), tid);
1262 return SCRIPT_CONTINUE;
1265 static int CmdThingCountDirect(void)
1270 ThingCount(type, *PCodePtr++);
1271 return SCRIPT_CONTINUE;
1274 static void ThingCount(int type, int tid)
1283 { // Nothing to count
1286 moType = TranslateThingType[type];
1290 { // Count TID things
1291 while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
1294 { // Just count TIDs
1297 else if(moType == mobj->type)
1299 if(mobj->flags&MF_COUNTKILL && mobj->health <= 0)
1300 { // Don't count dead monsters
1308 { // Count only types
1309 for(think = thinkercap.next; think != &thinkercap;
1310 think = think->next)
1312 if(think->function != P_MobjThinker)
1313 { // Not a mobj thinker
1316 mobj = (mobj_t *)think;
1317 if(mobj->type != moType)
1321 if(mobj->flags&MF_COUNTKILL && mobj->health <= 0)
1322 { // Don't count dead monsters
1331 static int CmdTagWait(void)
1333 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1334 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
1338 static int CmdTagWaitDirect(void)
1340 ACSInfo[ACScript->infoIndex].waitValue = *PCodePtr++;
1341 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
1345 static int CmdPolyWait(void)
1347 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1348 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
1352 static int CmdPolyWaitDirect(void)
1354 ACSInfo[ACScript->infoIndex].waitValue = *PCodePtr++;
1355 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
1359 static int CmdChangeFloor(void)
1365 flat = R_FlatNumForName(ACStrings[Pop()]);
1368 while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1370 sectors[sectorIndex].floorpic = flat;
1372 return SCRIPT_CONTINUE;
1375 static int CmdChangeFloorDirect(void)
1382 flat = R_FlatNumForName(ACStrings[*PCodePtr++]);
1384 while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1386 sectors[sectorIndex].floorpic = flat;
1388 return SCRIPT_CONTINUE;
1391 static int CmdChangeCeiling(void)
1397 flat = R_FlatNumForName(ACStrings[Pop()]);
1400 while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1402 sectors[sectorIndex].ceilingpic = flat;
1404 return SCRIPT_CONTINUE;
1407 static int CmdChangeCeilingDirect(void)
1414 flat = R_FlatNumForName(ACStrings[*PCodePtr++]);
1416 while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1418 sectors[sectorIndex].ceilingpic = flat;
1420 return SCRIPT_CONTINUE;
1423 static int CmdRestart(void)
1425 PCodePtr = ACSInfo[ACScript->infoIndex].address;
1426 return SCRIPT_CONTINUE;
1429 static int CmdAndLogical(void)
1431 Push(Pop() && Pop());
1432 return SCRIPT_CONTINUE;
1435 static int CmdOrLogical(void)
1437 Push(Pop() || Pop());
1438 return SCRIPT_CONTINUE;
1441 static int CmdAndBitwise(void)
1444 return SCRIPT_CONTINUE;
1447 static int CmdOrBitwise(void)
1450 return SCRIPT_CONTINUE;
1453 static int CmdEorBitwise(void)
1456 return SCRIPT_CONTINUE;
1459 static int CmdNegateLogical(void)
1462 return SCRIPT_CONTINUE;
1465 static int CmdLShift(void)
1470 Push(Pop()<<operand2);
1471 return SCRIPT_CONTINUE;
1474 static int CmdRShift(void)
1479 Push(Pop()>>operand2);
1480 return SCRIPT_CONTINUE;
1483 static int CmdUnaryMinus(void)
1486 return SCRIPT_CONTINUE;
1489 static int CmdIfNotGoto(void)
1497 PCodePtr = (int *)(ActionCodeBase+*PCodePtr);
1499 return SCRIPT_CONTINUE;
1502 static int CmdLineSide(void)
1504 Push(ACScript->side);
1505 return SCRIPT_CONTINUE;
1508 static int CmdScriptWait(void)
1510 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1511 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
1515 static int CmdScriptWaitDirect(void)
1517 ACSInfo[ACScript->infoIndex].waitValue = *PCodePtr++;
1518 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
1522 static int CmdClearLineSpecial(void)
1526 ACScript->line->special = 0;
1528 return SCRIPT_CONTINUE;
1531 static int CmdCaseGoto(void)
1533 if(Top() == *PCodePtr++)
1535 PCodePtr = (int *)(ActionCodeBase+*PCodePtr);
1542 return SCRIPT_CONTINUE;
1545 static int CmdBeginPrint(void)
1548 return SCRIPT_CONTINUE;
1551 static int CmdEndPrint(void)
1555 if(ACScript->activator && ACScript->activator->player)
1557 player = ACScript->activator->player;
1561 player = &players[consoleplayer];
1563 P_SetMessage(player, PrintBuffer, true);
1564 return SCRIPT_CONTINUE;
1567 static int CmdEndPrintBold(void)
1571 for(i = 0; i < MAXPLAYERS; i++)
1575 P_SetYellowMessage(&players[i], PrintBuffer, true);
1578 return SCRIPT_CONTINUE;
1581 static int CmdPrintString(void)
1583 strcat(PrintBuffer, ACStrings[Pop()]);
1584 return SCRIPT_CONTINUE;
1587 static int CmdPrintNumber(void)
1591 sprintf(tempStr, "%d", Pop());
1592 strcat(PrintBuffer, tempStr);
1593 return SCRIPT_CONTINUE;
1596 static int CmdPrintCharacter(void)
1600 bufferEnd = PrintBuffer+strlen(PrintBuffer);
1601 *bufferEnd++ = Pop();
1603 return SCRIPT_CONTINUE;
1606 static int CmdPlayerCount(void)
1612 for(i = 0; i < MAXPLAYERS; i++)
1614 count += playeringame[i];
1617 return SCRIPT_CONTINUE;
1620 static int CmdGameType(void)
1624 if(netgame == false)
1626 gametype = GAME_SINGLE_PLAYER;
1630 gametype = GAME_NET_DEATHMATCH;
1634 gametype = GAME_NET_COOPERATIVE;
1637 return SCRIPT_CONTINUE;
1640 static int CmdGameSkill(void)
1643 return SCRIPT_CONTINUE;
1646 static int CmdTimer(void)
1649 return SCRIPT_CONTINUE;
1652 static int CmdSectorSound(void)
1660 mobj = (mobj_t *)&ACScript->line->frontsector->soundorg;
1663 S_StartSoundAtVolume(mobj, S_GetSoundID(ACStrings[Pop()]), volume);
1664 return SCRIPT_CONTINUE;
1667 static int CmdThingSound(void)
1676 sound = S_GetSoundID(ACStrings[Pop()]);
1679 while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
1681 S_StartSoundAtVolume(mobj, sound, volume);
1683 return SCRIPT_CONTINUE;
1686 static int CmdAmbientSound(void)
1691 S_StartSoundAtVolume(NULL, S_GetSoundID(ACStrings[Pop()]), volume);
1692 return SCRIPT_CONTINUE;
1695 static int CmdSoundSequence(void)
1702 mobj = (mobj_t *)&ACScript->line->frontsector->soundorg;
1704 SN_StartSequenceName(mobj, ACStrings[Pop()]);
1705 return SCRIPT_CONTINUE;
1708 static int CmdSetLineTexture(void)
1717 texture = R_TextureNumForName(ACStrings[Pop()]);
1722 while((line = P_FindLine(lineTag, &searcher)) != NULL)
1724 if(position == TEXTURE_MIDDLE)
1726 sides[line->sidenum[side]].midtexture = texture;
1728 else if(position == TEXTURE_BOTTOM)
1730 sides[line->sidenum[side]].bottomtexture = texture;
1734 sides[line->sidenum[side]].toptexture = texture;
1737 return SCRIPT_CONTINUE;
1740 static int CmdSetLineBlocking(void)
1747 blocking = Pop() ? ML_BLOCKING : 0;
1750 while((line = P_FindLine(lineTag, &searcher)) != NULL)
1752 line->flags = (line->flags&~ML_BLOCKING)|blocking;
1754 return SCRIPT_CONTINUE;
1757 static int CmdSetLineSpecial(void)
1761 int special, arg1, arg2, arg3, arg4, arg5;
1772 while((line = P_FindLine(lineTag, &searcher)) != NULL)
1774 line->special = special;
1781 return SCRIPT_CONTINUE;