1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 1993-2008 Raven Software
4 // Copyright(C) 2005-2014 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16
17
18 // HEADER FILES ------------------------------------------------------------
19
20 #include "h2def.h"
21 #include "m_misc.h"
22 #include "m_random.h"
23 #include "s_sound.h"
24 #include "i_swap.h"
25 #include "i_system.h"
26 #include "p_local.h"
27
28 // MACROS ------------------------------------------------------------------
29
30 #define MAX_SCRIPT_ARGS 3
31 #define SCRIPT_CONTINUE 0
32 #define SCRIPT_STOP 1
33 #define SCRIPT_TERMINATE 2
34 #define OPEN_SCRIPTS_BASE 1000
35 #define PRINT_BUFFER_SIZE 256
36 #define GAME_SINGLE_PLAYER 0
37 #define GAME_NET_COOPERATIVE 1
38 #define GAME_NET_DEATHMATCH 2
39 #define TEXTURE_TOP 0
40 #define TEXTURE_MIDDLE 1
41 #define TEXTURE_BOTTOM 2
42 #define S_DROP ACScript->stackPtr--
43 #define S_POP ACScript->stack[--ACScript->stackPtr]
44 #define S_PUSH(x) ACScript->stack[ACScript->stackPtr++] = x
45
46 // TYPES -------------------------------------------------------------------
47
48 typedef PACKED_STRUCT (
49 {
50 int marker;
51 int infoOffset;
52 int code;
53 }) acsHeader_t;
54
55 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
56
57 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
58
59 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
60
61 static void StartOpenACS(int number, int infoIndex, int *address);
62 static void ScriptFinished(int number);
63 static boolean TagBusy(int tag);
64 static boolean AddToACSStore(int map, int number, byte * args);
65 static int GetACSIndex(int number);
66 static void Push(int value);
67 static int Pop(void);
68 static int Top(void);
69 static void Drop(void);
70
71 static int CmdNOP(void);
72 static int CmdTerminate(void);
73 static int CmdSuspend(void);
74 static int CmdPushNumber(void);
75 static int CmdLSpec1(void);
76 static int CmdLSpec2(void);
77 static int CmdLSpec3(void);
78 static int CmdLSpec4(void);
79 static int CmdLSpec5(void);
80 static int CmdLSpec1Direct(void);
81 static int CmdLSpec2Direct(void);
82 static int CmdLSpec3Direct(void);
83 static int CmdLSpec4Direct(void);
84 static int CmdLSpec5Direct(void);
85 static int CmdAdd(void);
86 static int CmdSubtract(void);
87 static int CmdMultiply(void);
88 static int CmdDivide(void);
89 static int CmdModulus(void);
90 static int CmdEQ(void);
91 static int CmdNE(void);
92 static int CmdLT(void);
93 static int CmdGT(void);
94 static int CmdLE(void);
95 static int CmdGE(void);
96 static int CmdAssignScriptVar(void);
97 static int CmdAssignMapVar(void);
98 static int CmdAssignWorldVar(void);
99 static int CmdPushScriptVar(void);
100 static int CmdPushMapVar(void);
101 static int CmdPushWorldVar(void);
102 static int CmdAddScriptVar(void);
103 static int CmdAddMapVar(void);
104 static int CmdAddWorldVar(void);
105 static int CmdSubScriptVar(void);
106 static int CmdSubMapVar(void);
107 static int CmdSubWorldVar(void);
108 static int CmdMulScriptVar(void);
109 static int CmdMulMapVar(void);
110 static int CmdMulWorldVar(void);
111 static int CmdDivScriptVar(void);
112 static int CmdDivMapVar(void);
113 static int CmdDivWorldVar(void);
114 static int CmdModScriptVar(void);
115 static int CmdModMapVar(void);
116 static int CmdModWorldVar(void);
117 static int CmdIncScriptVar(void);
118 static int CmdIncMapVar(void);
119 static int CmdIncWorldVar(void);
120 static int CmdDecScriptVar(void);
121 static int CmdDecMapVar(void);
122 static int CmdDecWorldVar(void);
123 static int CmdGoto(void);
124 static int CmdIfGoto(void);
125 static int CmdDrop(void);
126 static int CmdDelay(void);
127 static int CmdDelayDirect(void);
128 static int CmdRandom(void);
129 static int CmdRandomDirect(void);
130 static int CmdThingCount(void);
131 static int CmdThingCountDirect(void);
132 static int CmdTagWait(void);
133 static int CmdTagWaitDirect(void);
134 static int CmdPolyWait(void);
135 static int CmdPolyWaitDirect(void);
136 static int CmdChangeFloor(void);
137 static int CmdChangeFloorDirect(void);
138 static int CmdChangeCeiling(void);
139 static int CmdChangeCeilingDirect(void);
140 static int CmdRestart(void);
141 static int CmdAndLogical(void);
142 static int CmdOrLogical(void);
143 static int CmdAndBitwise(void);
144 static int CmdOrBitwise(void);
145 static int CmdEorBitwise(void);
146 static int CmdNegateLogical(void);
147 static int CmdLShift(void);
148 static int CmdRShift(void);
149 static int CmdUnaryMinus(void);
150 static int CmdIfNotGoto(void);
151 static int CmdLineSide(void);
152 static int CmdScriptWait(void);
153 static int CmdScriptWaitDirect(void);
154 static int CmdClearLineSpecial(void);
155 static int CmdCaseGoto(void);
156 static int CmdBeginPrint(void);
157 static int CmdEndPrint(void);
158 static int CmdPrintString(void);
159 static int CmdPrintNumber(void);
160 static int CmdPrintCharacter(void);
161 static int CmdPlayerCount(void);
162 static int CmdGameType(void);
163 static int CmdGameSkill(void);
164 static int CmdTimer(void);
165 static int CmdSectorSound(void);
166 static int CmdAmbientSound(void);
167 static int CmdSoundSequence(void);
168 static int CmdSetLineTexture(void);
169 static int CmdSetLineBlocking(void);
170 static int CmdSetLineSpecial(void);
171 static int CmdThingSound(void);
172 static int CmdEndPrintBold(void);
173
174 static void ThingCount(int type, int tid);
175
176 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
177
178 // PUBLIC DATA DEFINITIONS -------------------------------------------------
179
180 int ACScriptCount;
181 byte *ActionCodeBase;
182 acsInfo_t *ACSInfo;
183 int MapVars[MAX_ACS_MAP_VARS];
184 int WorldVars[MAX_ACS_WORLD_VARS];
185 acsstore_t ACSStore[MAX_ACS_STORE + 1]; // +1 for termination marker
186
187 // PRIVATE DATA DEFINITIONS ------------------------------------------------
188
189 static acs_t *ACScript;
190 static int *PCodePtr;
191 static byte SpecArgs[8];
192 static int ACStringCount;
193 static char **ACStrings;
194 static char PrintBuffer[PRINT_BUFFER_SIZE];
195 static acs_t *NewScript;
196
197 static int (*PCodeCmds[]) (void) =
198 {
199 CmdNOP,
200 CmdTerminate,
201 CmdSuspend,
202 CmdPushNumber,
203 CmdLSpec1,
204 CmdLSpec2,
205 CmdLSpec3,
206 CmdLSpec4,
207 CmdLSpec5,
208 CmdLSpec1Direct,
209 CmdLSpec2Direct,
210 CmdLSpec3Direct,
211 CmdLSpec4Direct,
212 CmdLSpec5Direct,
213 CmdAdd,
214 CmdSubtract,
215 CmdMultiply,
216 CmdDivide,
217 CmdModulus,
218 CmdEQ,
219 CmdNE,
220 CmdLT,
221 CmdGT,
222 CmdLE,
223 CmdGE,
224 CmdAssignScriptVar,
225 CmdAssignMapVar,
226 CmdAssignWorldVar,
227 CmdPushScriptVar,
228 CmdPushMapVar,
229 CmdPushWorldVar,
230 CmdAddScriptVar,
231 CmdAddMapVar,
232 CmdAddWorldVar,
233 CmdSubScriptVar,
234 CmdSubMapVar,
235 CmdSubWorldVar,
236 CmdMulScriptVar,
237 CmdMulMapVar,
238 CmdMulWorldVar,
239 CmdDivScriptVar,
240 CmdDivMapVar,
241 CmdDivWorldVar,
242 CmdModScriptVar,
243 CmdModMapVar,
244 CmdModWorldVar,
245 CmdIncScriptVar,
246 CmdIncMapVar,
247 CmdIncWorldVar,
248 CmdDecScriptVar,
249 CmdDecMapVar,
250 CmdDecWorldVar,
251 CmdGoto,
252 CmdIfGoto,
253 CmdDrop,
254 CmdDelay,
255 CmdDelayDirect,
256 CmdRandom,
257 CmdRandomDirect,
258 CmdThingCount,
259 CmdThingCountDirect,
260 CmdTagWait,
261 CmdTagWaitDirect,
262 CmdPolyWait,
263 CmdPolyWaitDirect,
264 CmdChangeFloor,
265 CmdChangeFloorDirect,
266 CmdChangeCeiling,
267 CmdChangeCeilingDirect,
268 CmdRestart,
269 CmdAndLogical,
270 CmdOrLogical,
271 CmdAndBitwise,
272 CmdOrBitwise,
273 CmdEorBitwise,
274 CmdNegateLogical,
275 CmdLShift,
276 CmdRShift,
277 CmdUnaryMinus,
278 CmdIfNotGoto,
279 CmdLineSide,
280 CmdScriptWait,
281 CmdScriptWaitDirect,
282 CmdClearLineSpecial,
283 CmdCaseGoto,
284 CmdBeginPrint,
285 CmdEndPrint,
286 CmdPrintString,
287 CmdPrintNumber,
288 CmdPrintCharacter,
289 CmdPlayerCount,
290 CmdGameType,
291 CmdGameSkill,
292 CmdTimer,
293 CmdSectorSound,
294 CmdAmbientSound,
295 CmdSoundSequence,
296 CmdSetLineTexture,
297 CmdSetLineBlocking,
298 CmdSetLineSpecial,
299 CmdThingSound,
300 CmdEndPrintBold,
301 };
302
303 // CODE --------------------------------------------------------------------
304
305 //==========================================================================
306 //
307 // P_LoadACScripts
308 //
309 //==========================================================================
310
P_LoadACScripts(int lump)311 void P_LoadACScripts(int lump)
312 {
313 int i;
314 int *buffer;
315 acsHeader_t *header;
316 acsInfo_t *info;
317
318 header = W_CacheLumpNum(lump, PU_LEVEL);
319 ActionCodeBase = (byte *) header;
320 buffer = (int *) ((byte *) header + LONG(header->infoOffset));
321
322 ACScriptCount = LONG(*buffer);
323 ++buffer;
324
325 if (ACScriptCount == 0)
326 { // Empty behavior lump
327 return;
328 }
329
330 ACSInfo = Z_Malloc(ACScriptCount * sizeof(acsInfo_t), PU_LEVEL, 0);
331 memset(ACSInfo, 0, ACScriptCount * sizeof(acsInfo_t));
332 for (i = 0, info = ACSInfo; i < ACScriptCount; i++, info++)
333 {
334 info->number = LONG(*buffer);
335 ++buffer;
336
337 info->address = (int *) ((byte *) ActionCodeBase + LONG(*buffer));
338 ++buffer;
339
340 info->argCount = LONG(*buffer);
341 ++buffer;
342
343 if (info->argCount > MAX_SCRIPT_ARGS)
344 {
345 fprintf(stderr, "Warning: ACS script #%i has %i arguments, more "
346 "than the maximum of %i. Enforcing limit.\n"
347 "If you are seeing this message, please report "
348 "the name of the WAD where you saw it.\n",
349 i, info->argCount, MAX_SCRIPT_ARGS);
350 info->argCount = MAX_SCRIPT_ARGS;
351 }
352
353 if (info->number >= OPEN_SCRIPTS_BASE)
354 { // Auto-activate
355 info->number -= OPEN_SCRIPTS_BASE;
356 StartOpenACS(info->number, i, info->address);
357 info->state = ASTE_RUNNING;
358 }
359 else
360 {
361 info->state = ASTE_INACTIVE;
362 }
363 }
364 ACStringCount = LONG(*buffer);
365 ++buffer;
366
367 ACStrings = Z_Malloc(ACStringCount * sizeof(char *), PU_LEVEL, NULL);
368
369 for (i=0; i<ACStringCount; ++i)
370 {
371 ACStrings[i] = (char *) ActionCodeBase + LONG(buffer[i]);
372 }
373
374 memset(MapVars, 0, sizeof(MapVars));
375 }
376
377 //==========================================================================
378 //
379 // StartOpenACS
380 //
381 //==========================================================================
382
StartOpenACS(int number,int infoIndex,int * address)383 static void StartOpenACS(int number, int infoIndex, int *address)
384 {
385 acs_t *script;
386
387 script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
388 memset(script, 0, sizeof(acs_t));
389 script->number = number;
390
391 // World objects are allotted 1 second for initialization
392 script->delayCount = 35;
393
394 script->infoIndex = infoIndex;
395 script->ip = address;
396 script->thinker.function = T_InterpretACS;
397 P_AddThinker(&script->thinker);
398 }
399
400 //==========================================================================
401 //
402 // P_CheckACSStore
403 //
404 // Scans the ACS store and executes all scripts belonging to the current
405 // map.
406 //
407 //==========================================================================
408
P_CheckACSStore(void)409 void P_CheckACSStore(void)
410 {
411 acsstore_t *store;
412
413 for (store = ACSStore; store->map != 0; store++)
414 {
415 if (store->map == gamemap)
416 {
417 P_StartACS(store->script, 0, store->args, NULL, NULL, 0);
418 if (NewScript)
419 {
420 NewScript->delayCount = 35;
421 }
422 store->map = -1;
423 }
424 }
425 }
426
427 //==========================================================================
428 //
429 // P_StartACS
430 //
431 // Start an ACS script. The 'args' array should be at least MAX_SCRIPT_ARGS
432 // elements in length.
433 //
434 //==========================================================================
435
436 static char ErrorMsg[128];
437
P_StartACS(int number,int map,byte * args,mobj_t * activator,line_t * line,int side)438 boolean P_StartACS(int number, int map, byte * args, mobj_t * activator,
439 line_t * line, int side)
440 {
441 int i;
442 acs_t *script;
443 int infoIndex;
444 aste_t *statePtr;
445
446 NewScript = NULL;
447 if (map && map != gamemap)
448 { // Add to the script store
449 return AddToACSStore(map, number, args);
450 }
451 infoIndex = GetACSIndex(number);
452 if (infoIndex == -1)
453 { // Script not found
454 //I_Error("P_StartACS: Unknown script number %d", number);
455 M_snprintf(ErrorMsg, sizeof(ErrorMsg),
456 "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number);
457 P_SetMessage(&players[consoleplayer], ErrorMsg, true);
458 }
459 statePtr = &ACSInfo[infoIndex].state;
460 if (*statePtr == ASTE_SUSPENDED)
461 { // Resume a suspended script
462 *statePtr = ASTE_RUNNING;
463 return true;
464 }
465 if (*statePtr != ASTE_INACTIVE)
466 { // Script is already executing
467 return false;
468 }
469 script = Z_Malloc(sizeof(acs_t), PU_LEVSPEC, 0);
470 memset(script, 0, sizeof(acs_t));
471 script->number = number;
472 script->infoIndex = infoIndex;
473 script->activator = activator;
474 script->line = line;
475 script->side = side;
476 script->ip = ACSInfo[infoIndex].address;
477 script->thinker.function = T_InterpretACS;
478 for (i = 0; i < MAX_SCRIPT_ARGS && i < ACSInfo[infoIndex].argCount; i++)
479 {
480 script->vars[i] = args[i];
481 }
482 *statePtr = ASTE_RUNNING;
483 P_AddThinker(&script->thinker);
484 NewScript = script;
485 return true;
486 }
487
488 //==========================================================================
489 //
490 // AddToACSStore
491 //
492 //==========================================================================
493
AddToACSStore(int map,int number,byte * args)494 static boolean AddToACSStore(int map, int number, byte * args)
495 {
496 int i;
497 int index;
498
499 index = -1;
500 for (i = 0; ACSStore[i].map != 0; i++)
501 {
502 if (ACSStore[i].script == number && ACSStore[i].map == map)
503 { // Don't allow duplicates
504 return false;
505 }
506 if (index == -1 && ACSStore[i].map == -1)
507 { // Remember first empty slot
508 index = i;
509 }
510 }
511 if (index == -1)
512 { // Append required
513 if (i == MAX_ACS_STORE)
514 {
515 I_Error("AddToACSStore: MAX_ACS_STORE (%d) exceeded.",
516 MAX_ACS_STORE);
517 }
518 index = i;
519 ACSStore[index + 1].map = 0;
520 }
521 ACSStore[index].map = map;
522 ACSStore[index].script = number;
523 memcpy(ACSStore[index].args, args, MAX_SCRIPT_ARGS);
524 return true;
525 }
526
527 //==========================================================================
528 //
529 // P_StartLockedACS
530 //
531 //==========================================================================
532
533
P_StartLockedACS(line_t * line,byte * args,mobj_t * mo,int side)534 boolean P_StartLockedACS(line_t * line, byte * args, mobj_t * mo, int side)
535 {
536 int i;
537 int lock;
538 byte newArgs[5];
539 char LockedBuffer[80];
540
541 extern char *TextKeyMessages[11];
542
543 lock = args[4];
544 if (!mo->player)
545 {
546 return false;
547 }
548 if (lock)
549 {
550 if (!(mo->player->keys & (1 << (lock - 1))))
551 {
552 M_snprintf(LockedBuffer, sizeof(LockedBuffer),
553 "YOU NEED THE %s\n", TextKeyMessages[lock - 1]);
554 P_SetMessage(mo->player, LockedBuffer, true);
555 S_StartSound(mo, SFX_DOOR_LOCKED);
556 return false;
557 }
558 }
559 for (i = 0; i < 4; i++)
560 {
561 newArgs[i] = args[i];
562 }
563 newArgs[4] = 0;
564 return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo, line, side);
565 }
566
567 //==========================================================================
568 //
569 // P_TerminateACS
570 //
571 //==========================================================================
572
P_TerminateACS(int number,int map)573 boolean P_TerminateACS(int number, int map)
574 {
575 int infoIndex;
576
577 infoIndex = GetACSIndex(number);
578 if (infoIndex == -1)
579 { // Script not found
580 return false;
581 }
582 if (ACSInfo[infoIndex].state == ASTE_INACTIVE
583 || ACSInfo[infoIndex].state == ASTE_TERMINATING)
584 { // States that disallow termination
585 return false;
586 }
587 ACSInfo[infoIndex].state = ASTE_TERMINATING;
588 return true;
589 }
590
591 //==========================================================================
592 //
593 // P_SuspendACS
594 //
595 //==========================================================================
596
P_SuspendACS(int number,int map)597 boolean P_SuspendACS(int number, int map)
598 {
599 int infoIndex;
600
601 infoIndex = GetACSIndex(number);
602 if (infoIndex == -1)
603 { // Script not found
604 return false;
605 }
606 if (ACSInfo[infoIndex].state == ASTE_INACTIVE
607 || ACSInfo[infoIndex].state == ASTE_SUSPENDED
608 || ACSInfo[infoIndex].state == ASTE_TERMINATING)
609 { // States that disallow suspension
610 return false;
611 }
612 ACSInfo[infoIndex].state = ASTE_SUSPENDED;
613 return true;
614 }
615
616 //==========================================================================
617 //
618 // P_Init
619 //
620 //==========================================================================
621
P_ACSInitNewGame(void)622 void P_ACSInitNewGame(void)
623 {
624 memset(WorldVars, 0, sizeof(WorldVars));
625 memset(ACSStore, 0, sizeof(ACSStore));
626 }
627
628 //==========================================================================
629 //
630 // T_InterpretACS
631 //
632 //==========================================================================
633
T_InterpretACS(acs_t * script)634 void T_InterpretACS(acs_t * script)
635 {
636 int cmd;
637 int action;
638
639 if (ACSInfo[script->infoIndex].state == ASTE_TERMINATING)
640 {
641 ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
642 ScriptFinished(ACScript->number);
643 P_RemoveThinker(&ACScript->thinker);
644 return;
645 }
646 if (ACSInfo[script->infoIndex].state != ASTE_RUNNING)
647 {
648 return;
649 }
650 if (script->delayCount)
651 {
652 script->delayCount--;
653 return;
654 }
655 ACScript = script;
656 PCodePtr = ACScript->ip;
657
658 do
659 {
660 cmd = LONG(*PCodePtr);
661 ++PCodePtr;
662
663 action = PCodeCmds[cmd] ();
664 } while (action == SCRIPT_CONTINUE);
665
666 ACScript->ip = PCodePtr;
667
668 if (action == SCRIPT_TERMINATE)
669 {
670 ACSInfo[script->infoIndex].state = ASTE_INACTIVE;
671 ScriptFinished(ACScript->number);
672 P_RemoveThinker(&ACScript->thinker);
673 }
674 }
675
676 //==========================================================================
677 //
678 // P_TagFinished
679 //
680 //==========================================================================
681
P_TagFinished(int tag)682 void P_TagFinished(int tag)
683 {
684 int i;
685
686 if (TagBusy(tag) == true)
687 {
688 return;
689 }
690 for (i = 0; i < ACScriptCount; i++)
691 {
692 if (ACSInfo[i].state == ASTE_WAITINGFORTAG
693 && ACSInfo[i].waitValue == tag)
694 {
695 ACSInfo[i].state = ASTE_RUNNING;
696 }
697 }
698 }
699
700 //==========================================================================
701 //
702 // P_PolyobjFinished
703 //
704 //==========================================================================
705
P_PolyobjFinished(int po)706 void P_PolyobjFinished(int po)
707 {
708 int i;
709
710 if (PO_Busy(po) == true)
711 {
712 return;
713 }
714 for (i = 0; i < ACScriptCount; i++)
715 {
716 if (ACSInfo[i].state == ASTE_WAITINGFORPOLY
717 && ACSInfo[i].waitValue == po)
718 {
719 ACSInfo[i].state = ASTE_RUNNING;
720 }
721 }
722 }
723
724 //==========================================================================
725 //
726 // ScriptFinished
727 //
728 //==========================================================================
729
ScriptFinished(int number)730 static void ScriptFinished(int number)
731 {
732 int i;
733
734 for (i = 0; i < ACScriptCount; i++)
735 {
736 if (ACSInfo[i].state == ASTE_WAITINGFORSCRIPT
737 && ACSInfo[i].waitValue == number)
738 {
739 ACSInfo[i].state = ASTE_RUNNING;
740 }
741 }
742 }
743
744 //==========================================================================
745 //
746 // TagBusy
747 //
748 //==========================================================================
749
TagBusy(int tag)750 static boolean TagBusy(int tag)
751 {
752 int sectorIndex;
753
754 sectorIndex = -1;
755 while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
756 {
757 if (sectors[sectorIndex].specialdata)
758 {
759 return true;
760 }
761 }
762 return false;
763 }
764
765 //==========================================================================
766 //
767 // GetACSIndex
768 //
769 // Returns the index of a script number. Returns -1 if the script number
770 // is not found.
771 //
772 //==========================================================================
773
GetACSIndex(int number)774 static int GetACSIndex(int number)
775 {
776 int i;
777
778 for (i = 0; i < ACScriptCount; i++)
779 {
780 if (ACSInfo[i].number == number)
781 {
782 return i;
783 }
784 }
785 return -1;
786 }
787
788 //==========================================================================
789 //
790 // CheckACSPresent
791 //
792 // Placing Korax in a PWAD without extra steps will result in a crash in
793 // Vanilla because the relevant ACS scripts are not initialised
794 //
795 //==========================================================================
796
CheckACSPresent(int number)797 void CheckACSPresent(int number)
798 {
799 if (GetACSIndex(number) == -1)
800 {
801 I_Error("Required ACS script %d not initialised", number);
802 }
803 }
804
805 //==========================================================================
806 //
807 // Push
808 //
809 //==========================================================================
810
Push(int value)811 static void Push(int value)
812 {
813 ACScript->stack[ACScript->stackPtr++] = value;
814 }
815
816 //==========================================================================
817 //
818 // Pop
819 //
820 //==========================================================================
821
Pop(void)822 static int Pop(void)
823 {
824 return ACScript->stack[--ACScript->stackPtr];
825 }
826
827 //==========================================================================
828 //
829 // Top
830 //
831 //==========================================================================
832
Top(void)833 static int Top(void)
834 {
835 return ACScript->stack[ACScript->stackPtr - 1];
836 }
837
838 //==========================================================================
839 //
840 // Drop
841 //
842 //==========================================================================
843
Drop(void)844 static void Drop(void)
845 {
846 ACScript->stackPtr--;
847 }
848
849 //==========================================================================
850 //
851 // P-Code Commands
852 //
853 //==========================================================================
854
CmdNOP(void)855 static int CmdNOP(void)
856 {
857 return SCRIPT_CONTINUE;
858 }
859
CmdTerminate(void)860 static int CmdTerminate(void)
861 {
862 return SCRIPT_TERMINATE;
863 }
864
CmdSuspend(void)865 static int CmdSuspend(void)
866 {
867 ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED;
868 return SCRIPT_STOP;
869 }
870
CmdPushNumber(void)871 static int CmdPushNumber(void)
872 {
873 Push(LONG(*PCodePtr));
874 ++PCodePtr;
875 return SCRIPT_CONTINUE;
876 }
877
CmdLSpec1(void)878 static int CmdLSpec1(void)
879 {
880 int special;
881
882 special = LONG(*PCodePtr);
883 ++PCodePtr;
884 SpecArgs[0] = Pop();
885 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
886 ACScript->side, ACScript->activator);
887 return SCRIPT_CONTINUE;
888 }
889
CmdLSpec2(void)890 static int CmdLSpec2(void)
891 {
892 int special;
893
894 special = LONG(*PCodePtr);
895 ++PCodePtr;
896 SpecArgs[1] = Pop();
897 SpecArgs[0] = Pop();
898 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
899 ACScript->side, ACScript->activator);
900 return SCRIPT_CONTINUE;
901 }
902
CmdLSpec3(void)903 static int CmdLSpec3(void)
904 {
905 int special;
906
907 special = LONG(*PCodePtr);
908 ++PCodePtr;
909 SpecArgs[2] = Pop();
910 SpecArgs[1] = Pop();
911 SpecArgs[0] = Pop();
912 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
913 ACScript->side, ACScript->activator);
914 return SCRIPT_CONTINUE;
915 }
916
CmdLSpec4(void)917 static int CmdLSpec4(void)
918 {
919 int special;
920
921 special = LONG(*PCodePtr);
922 ++PCodePtr;
923 SpecArgs[3] = Pop();
924 SpecArgs[2] = Pop();
925 SpecArgs[1] = Pop();
926 SpecArgs[0] = Pop();
927 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
928 ACScript->side, ACScript->activator);
929 return SCRIPT_CONTINUE;
930 }
931
CmdLSpec5(void)932 static int CmdLSpec5(void)
933 {
934 int special;
935
936 special = LONG(*PCodePtr);
937 ++PCodePtr;
938 SpecArgs[4] = Pop();
939 SpecArgs[3] = Pop();
940 SpecArgs[2] = Pop();
941 SpecArgs[1] = Pop();
942 SpecArgs[0] = Pop();
943 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
944 ACScript->side, ACScript->activator);
945 return SCRIPT_CONTINUE;
946 }
947
CmdLSpec1Direct(void)948 static int CmdLSpec1Direct(void)
949 {
950 int special;
951
952 special = LONG(*PCodePtr);
953 ++PCodePtr;
954 SpecArgs[0] = LONG(*PCodePtr);
955 ++PCodePtr;
956 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
957 ACScript->side, ACScript->activator);
958 return SCRIPT_CONTINUE;
959 }
960
CmdLSpec2Direct(void)961 static int CmdLSpec2Direct(void)
962 {
963 int special;
964
965 special = LONG(*PCodePtr);
966 ++PCodePtr;
967 SpecArgs[0] = LONG(*PCodePtr);
968 ++PCodePtr;
969 SpecArgs[1] = LONG(*PCodePtr);
970 ++PCodePtr;
971 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
972 ACScript->side, ACScript->activator);
973 return SCRIPT_CONTINUE;
974 }
975
CmdLSpec3Direct(void)976 static int CmdLSpec3Direct(void)
977 {
978 int special;
979
980 special = LONG(*PCodePtr);
981 ++PCodePtr;
982 SpecArgs[0] = LONG(*PCodePtr);
983 ++PCodePtr;
984 SpecArgs[1] = LONG(*PCodePtr);
985 ++PCodePtr;
986 SpecArgs[2] = LONG(*PCodePtr);
987 ++PCodePtr;
988 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
989 ACScript->side, ACScript->activator);
990 return SCRIPT_CONTINUE;
991 }
992
CmdLSpec4Direct(void)993 static int CmdLSpec4Direct(void)
994 {
995 int special;
996
997 special = LONG(*PCodePtr);
998 ++PCodePtr;
999 SpecArgs[0] = LONG(*PCodePtr);
1000 ++PCodePtr;
1001 SpecArgs[1] = LONG(*PCodePtr);
1002 ++PCodePtr;
1003 SpecArgs[2] = LONG(*PCodePtr);
1004 ++PCodePtr;
1005 SpecArgs[3] = LONG(*PCodePtr);
1006 ++PCodePtr;
1007 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
1008 ACScript->side, ACScript->activator);
1009 return SCRIPT_CONTINUE;
1010 }
1011
CmdLSpec5Direct(void)1012 static int CmdLSpec5Direct(void)
1013 {
1014 int special;
1015
1016 special = LONG(*PCodePtr);
1017 ++PCodePtr;
1018 SpecArgs[0] = LONG(*PCodePtr);
1019 ++PCodePtr;
1020 SpecArgs[1] = LONG(*PCodePtr);
1021 ++PCodePtr;
1022 SpecArgs[2] = LONG(*PCodePtr);
1023 ++PCodePtr;
1024 SpecArgs[3] = LONG(*PCodePtr);
1025 ++PCodePtr;
1026 SpecArgs[4] = LONG(*PCodePtr);
1027 ++PCodePtr;
1028 P_ExecuteLineSpecial(special, SpecArgs, ACScript->line,
1029 ACScript->side, ACScript->activator);
1030 return SCRIPT_CONTINUE;
1031 }
1032
CmdAdd(void)1033 static int CmdAdd(void)
1034 {
1035 Push(Pop() + Pop());
1036 return SCRIPT_CONTINUE;
1037 }
1038
CmdSubtract(void)1039 static int CmdSubtract(void)
1040 {
1041 int operand2;
1042
1043 operand2 = Pop();
1044 Push(Pop() - operand2);
1045 return SCRIPT_CONTINUE;
1046 }
1047
CmdMultiply(void)1048 static int CmdMultiply(void)
1049 {
1050 Push(Pop() * Pop());
1051 return SCRIPT_CONTINUE;
1052 }
1053
CmdDivide(void)1054 static int CmdDivide(void)
1055 {
1056 int operand2;
1057
1058 operand2 = Pop();
1059 Push(Pop() / operand2);
1060 return SCRIPT_CONTINUE;
1061 }
1062
CmdModulus(void)1063 static int CmdModulus(void)
1064 {
1065 int operand2;
1066
1067 operand2 = Pop();
1068 Push(Pop() % operand2);
1069 return SCRIPT_CONTINUE;
1070 }
1071
CmdEQ(void)1072 static int CmdEQ(void)
1073 {
1074 Push(Pop() == Pop());
1075 return SCRIPT_CONTINUE;
1076 }
1077
CmdNE(void)1078 static int CmdNE(void)
1079 {
1080 Push(Pop() != Pop());
1081 return SCRIPT_CONTINUE;
1082 }
1083
CmdLT(void)1084 static int CmdLT(void)
1085 {
1086 int operand2;
1087
1088 operand2 = Pop();
1089 Push(Pop() < operand2);
1090 return SCRIPT_CONTINUE;
1091 }
1092
CmdGT(void)1093 static int CmdGT(void)
1094 {
1095 int operand2;
1096
1097 operand2 = Pop();
1098 Push(Pop() > operand2);
1099 return SCRIPT_CONTINUE;
1100 }
1101
CmdLE(void)1102 static int CmdLE(void)
1103 {
1104 int operand2;
1105
1106 operand2 = Pop();
1107 Push(Pop() <= operand2);
1108 return SCRIPT_CONTINUE;
1109 }
1110
CmdGE(void)1111 static int CmdGE(void)
1112 {
1113 int operand2;
1114
1115 operand2 = Pop();
1116 Push(Pop() >= operand2);
1117 return SCRIPT_CONTINUE;
1118 }
1119
CmdAssignScriptVar(void)1120 static int CmdAssignScriptVar(void)
1121 {
1122 ACScript->vars[LONG(*PCodePtr)] = Pop();
1123 ++PCodePtr;
1124 return SCRIPT_CONTINUE;
1125 }
1126
CmdAssignMapVar(void)1127 static int CmdAssignMapVar(void)
1128 {
1129 MapVars[LONG(*PCodePtr)] = Pop();
1130 ++PCodePtr;
1131 return SCRIPT_CONTINUE;
1132 }
1133
CmdAssignWorldVar(void)1134 static int CmdAssignWorldVar(void)
1135 {
1136 WorldVars[LONG(*PCodePtr)] = Pop();
1137 ++PCodePtr;
1138 return SCRIPT_CONTINUE;
1139 }
1140
CmdPushScriptVar(void)1141 static int CmdPushScriptVar(void)
1142 {
1143 Push(ACScript->vars[LONG(*PCodePtr)]);
1144 ++PCodePtr;
1145 return SCRIPT_CONTINUE;
1146 }
1147
CmdPushMapVar(void)1148 static int CmdPushMapVar(void)
1149 {
1150 Push(MapVars[LONG(*PCodePtr)]);
1151 ++PCodePtr;
1152 return SCRIPT_CONTINUE;
1153 }
1154
CmdPushWorldVar(void)1155 static int CmdPushWorldVar(void)
1156 {
1157 Push(WorldVars[LONG(*PCodePtr)]);
1158 ++PCodePtr;
1159 return SCRIPT_CONTINUE;
1160 }
1161
CmdAddScriptVar(void)1162 static int CmdAddScriptVar(void)
1163 {
1164 ACScript->vars[LONG(*PCodePtr)] += Pop();
1165 ++PCodePtr;
1166 return SCRIPT_CONTINUE;
1167 }
1168
CmdAddMapVar(void)1169 static int CmdAddMapVar(void)
1170 {
1171 MapVars[LONG(*PCodePtr)] += Pop();
1172 ++PCodePtr;
1173 return SCRIPT_CONTINUE;
1174 }
1175
CmdAddWorldVar(void)1176 static int CmdAddWorldVar(void)
1177 {
1178 WorldVars[LONG(*PCodePtr)] += Pop();
1179 ++PCodePtr;
1180 return SCRIPT_CONTINUE;
1181 }
1182
CmdSubScriptVar(void)1183 static int CmdSubScriptVar(void)
1184 {
1185 ACScript->vars[LONG(*PCodePtr)] -= Pop();
1186 ++PCodePtr;
1187 return SCRIPT_CONTINUE;
1188 }
1189
CmdSubMapVar(void)1190 static int CmdSubMapVar(void)
1191 {
1192 MapVars[LONG(*PCodePtr)] -= Pop();
1193 ++PCodePtr;
1194 return SCRIPT_CONTINUE;
1195 }
1196
CmdSubWorldVar(void)1197 static int CmdSubWorldVar(void)
1198 {
1199 WorldVars[LONG(*PCodePtr)] -= Pop();
1200 ++PCodePtr;
1201 return SCRIPT_CONTINUE;
1202 }
1203
CmdMulScriptVar(void)1204 static int CmdMulScriptVar(void)
1205 {
1206 ACScript->vars[LONG(*PCodePtr)] *= Pop();
1207 ++PCodePtr;
1208 return SCRIPT_CONTINUE;
1209 }
1210
CmdMulMapVar(void)1211 static int CmdMulMapVar(void)
1212 {
1213 MapVars[LONG(*PCodePtr)] *= Pop();
1214 ++PCodePtr;
1215 return SCRIPT_CONTINUE;
1216 }
1217
CmdMulWorldVar(void)1218 static int CmdMulWorldVar(void)
1219 {
1220 WorldVars[LONG(*PCodePtr)] *= Pop();
1221 ++PCodePtr;
1222 return SCRIPT_CONTINUE;
1223 }
1224
CmdDivScriptVar(void)1225 static int CmdDivScriptVar(void)
1226 {
1227 ACScript->vars[LONG(*PCodePtr)] /= Pop();
1228 ++PCodePtr;
1229 return SCRIPT_CONTINUE;
1230 }
1231
CmdDivMapVar(void)1232 static int CmdDivMapVar(void)
1233 {
1234 MapVars[LONG(*PCodePtr)] /= Pop();
1235 ++PCodePtr;
1236 return SCRIPT_CONTINUE;
1237 }
1238
CmdDivWorldVar(void)1239 static int CmdDivWorldVar(void)
1240 {
1241 WorldVars[LONG(*PCodePtr)] /= Pop();
1242 ++PCodePtr;
1243 return SCRIPT_CONTINUE;
1244 }
1245
CmdModScriptVar(void)1246 static int CmdModScriptVar(void)
1247 {
1248 ACScript->vars[LONG(*PCodePtr)] %= Pop();
1249 ++PCodePtr;
1250 return SCRIPT_CONTINUE;
1251 }
1252
CmdModMapVar(void)1253 static int CmdModMapVar(void)
1254 {
1255 MapVars[LONG(*PCodePtr)] %= Pop();
1256 ++PCodePtr;
1257 return SCRIPT_CONTINUE;
1258 }
1259
CmdModWorldVar(void)1260 static int CmdModWorldVar(void)
1261 {
1262 WorldVars[LONG(*PCodePtr)] %= Pop();
1263 ++PCodePtr;
1264 return SCRIPT_CONTINUE;
1265 }
1266
CmdIncScriptVar(void)1267 static int CmdIncScriptVar(void)
1268 {
1269 ++ACScript->vars[LONG(*PCodePtr)];
1270 ++PCodePtr;
1271 return SCRIPT_CONTINUE;
1272 }
1273
CmdIncMapVar(void)1274 static int CmdIncMapVar(void)
1275 {
1276 ++MapVars[LONG(*PCodePtr)];
1277 ++PCodePtr;
1278 return SCRIPT_CONTINUE;
1279 }
1280
CmdIncWorldVar(void)1281 static int CmdIncWorldVar(void)
1282 {
1283 ++WorldVars[LONG(*PCodePtr)];
1284 ++PCodePtr;
1285 return SCRIPT_CONTINUE;
1286 }
1287
CmdDecScriptVar(void)1288 static int CmdDecScriptVar(void)
1289 {
1290 --ACScript->vars[LONG(*PCodePtr)];
1291 ++PCodePtr;
1292 return SCRIPT_CONTINUE;
1293 }
1294
CmdDecMapVar(void)1295 static int CmdDecMapVar(void)
1296 {
1297 --MapVars[LONG(*PCodePtr)];
1298 ++PCodePtr;
1299 return SCRIPT_CONTINUE;
1300 }
1301
CmdDecWorldVar(void)1302 static int CmdDecWorldVar(void)
1303 {
1304 --WorldVars[LONG(*PCodePtr)];
1305 ++PCodePtr;
1306 return SCRIPT_CONTINUE;
1307 }
1308
CmdGoto(void)1309 static int CmdGoto(void)
1310 {
1311 PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
1312 return SCRIPT_CONTINUE;
1313 }
1314
CmdIfGoto(void)1315 static int CmdIfGoto(void)
1316 {
1317 if (Pop() != 0)
1318 {
1319 PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
1320 }
1321 else
1322 {
1323 ++PCodePtr;
1324 }
1325 return SCRIPT_CONTINUE;
1326 }
1327
CmdDrop(void)1328 static int CmdDrop(void)
1329 {
1330 Drop();
1331 return SCRIPT_CONTINUE;
1332 }
1333
CmdDelay(void)1334 static int CmdDelay(void)
1335 {
1336 ACScript->delayCount = Pop();
1337 return SCRIPT_STOP;
1338 }
1339
CmdDelayDirect(void)1340 static int CmdDelayDirect(void)
1341 {
1342 ACScript->delayCount = LONG(*PCodePtr);
1343 ++PCodePtr;
1344 return SCRIPT_STOP;
1345 }
1346
CmdRandom(void)1347 static int CmdRandom(void)
1348 {
1349 int low;
1350 int high;
1351
1352 high = Pop();
1353 low = Pop();
1354 Push(low + (P_Random() % (high - low + 1)));
1355 return SCRIPT_CONTINUE;
1356 }
1357
CmdRandomDirect(void)1358 static int CmdRandomDirect(void)
1359 {
1360 int low;
1361 int high;
1362
1363 low = LONG(*PCodePtr);
1364 ++PCodePtr;
1365 high = LONG(*PCodePtr);
1366 ++PCodePtr;
1367 Push(low + (P_Random() % (high - low + 1)));
1368 return SCRIPT_CONTINUE;
1369 }
1370
CmdThingCount(void)1371 static int CmdThingCount(void)
1372 {
1373 int tid;
1374
1375 tid = Pop();
1376 ThingCount(Pop(), tid);
1377 return SCRIPT_CONTINUE;
1378 }
1379
CmdThingCountDirect(void)1380 static int CmdThingCountDirect(void)
1381 {
1382 int type;
1383
1384 type = LONG(*PCodePtr);
1385 ++PCodePtr;
1386 ThingCount(type, LONG(*PCodePtr));
1387 ++PCodePtr;
1388 return SCRIPT_CONTINUE;
1389 }
1390
ThingCount(int type,int tid)1391 static void ThingCount(int type, int tid)
1392 {
1393 int count;
1394 int searcher;
1395 mobj_t *mobj;
1396 mobjtype_t moType;
1397 thinker_t *think;
1398
1399 if (!(type + tid))
1400 { // Nothing to count
1401 return;
1402 }
1403 moType = TranslateThingType[type];
1404 count = 0;
1405 searcher = -1;
1406 if (tid)
1407 { // Count TID things
1408 while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
1409 {
1410 if (type == 0)
1411 { // Just count TIDs
1412 count++;
1413 }
1414 else if (moType == mobj->type)
1415 {
1416 if (mobj->flags & MF_COUNTKILL && mobj->health <= 0)
1417 { // Don't count dead monsters
1418 continue;
1419 }
1420 count++;
1421 }
1422 }
1423 }
1424 else
1425 { // Count only types
1426 for (think = thinkercap.next; think != &thinkercap;
1427 think = think->next)
1428 {
1429 if (think->function != P_MobjThinker)
1430 { // Not a mobj thinker
1431 continue;
1432 }
1433 mobj = (mobj_t *) think;
1434 if (mobj->type != moType)
1435 { // Doesn't match
1436 continue;
1437 }
1438 if (mobj->flags & MF_COUNTKILL && mobj->health <= 0)
1439 { // Don't count dead monsters
1440 continue;
1441 }
1442 count++;
1443 }
1444 }
1445 Push(count);
1446 }
1447
CmdTagWait(void)1448 static int CmdTagWait(void)
1449 {
1450 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1451 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
1452 return SCRIPT_STOP;
1453 }
1454
CmdTagWaitDirect(void)1455 static int CmdTagWaitDirect(void)
1456 {
1457 ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
1458 ++PCodePtr;
1459 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORTAG;
1460 return SCRIPT_STOP;
1461 }
1462
CmdPolyWait(void)1463 static int CmdPolyWait(void)
1464 {
1465 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1466 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
1467 return SCRIPT_STOP;
1468 }
1469
CmdPolyWaitDirect(void)1470 static int CmdPolyWaitDirect(void)
1471 {
1472 ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
1473 ++PCodePtr;
1474 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORPOLY;
1475 return SCRIPT_STOP;
1476 }
1477
CmdChangeFloor(void)1478 static int CmdChangeFloor(void)
1479 {
1480 int tag;
1481 int flat;
1482 int sectorIndex;
1483
1484 flat = R_FlatNumForName(ACStrings[Pop()]);
1485 tag = Pop();
1486 sectorIndex = -1;
1487 while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1488 {
1489 sectors[sectorIndex].floorpic = flat;
1490 }
1491 return SCRIPT_CONTINUE;
1492 }
1493
CmdChangeFloorDirect(void)1494 static int CmdChangeFloorDirect(void)
1495 {
1496 int tag;
1497 int flat;
1498 int sectorIndex;
1499
1500 tag = LONG(*PCodePtr);
1501 ++PCodePtr;
1502 flat = R_FlatNumForName(ACStrings[LONG(*PCodePtr)]);
1503 ++PCodePtr;
1504 sectorIndex = -1;
1505 while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1506 {
1507 sectors[sectorIndex].floorpic = flat;
1508 }
1509 return SCRIPT_CONTINUE;
1510 }
1511
CmdChangeCeiling(void)1512 static int CmdChangeCeiling(void)
1513 {
1514 int tag;
1515 int flat;
1516 int sectorIndex;
1517
1518 flat = R_FlatNumForName(ACStrings[Pop()]);
1519 tag = Pop();
1520 sectorIndex = -1;
1521 while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1522 {
1523 sectors[sectorIndex].ceilingpic = flat;
1524 }
1525 return SCRIPT_CONTINUE;
1526 }
1527
CmdChangeCeilingDirect(void)1528 static int CmdChangeCeilingDirect(void)
1529 {
1530 int tag;
1531 int flat;
1532 int sectorIndex;
1533
1534 tag = LONG(*PCodePtr);
1535 ++PCodePtr;
1536 flat = R_FlatNumForName(ACStrings[LONG(*PCodePtr)]);
1537 ++PCodePtr;
1538 sectorIndex = -1;
1539 while ((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
1540 {
1541 sectors[sectorIndex].ceilingpic = flat;
1542 }
1543 return SCRIPT_CONTINUE;
1544 }
1545
CmdRestart(void)1546 static int CmdRestart(void)
1547 {
1548 PCodePtr = ACSInfo[ACScript->infoIndex].address;
1549 return SCRIPT_CONTINUE;
1550 }
1551
CmdAndLogical(void)1552 static int CmdAndLogical(void)
1553 {
1554 Push(Pop() && Pop());
1555 return SCRIPT_CONTINUE;
1556 }
1557
CmdOrLogical(void)1558 static int CmdOrLogical(void)
1559 {
1560 Push(Pop() || Pop());
1561 return SCRIPT_CONTINUE;
1562 }
1563
CmdAndBitwise(void)1564 static int CmdAndBitwise(void)
1565 {
1566 Push(Pop() & Pop());
1567 return SCRIPT_CONTINUE;
1568 }
1569
CmdOrBitwise(void)1570 static int CmdOrBitwise(void)
1571 {
1572 Push(Pop() | Pop());
1573 return SCRIPT_CONTINUE;
1574 }
1575
CmdEorBitwise(void)1576 static int CmdEorBitwise(void)
1577 {
1578 Push(Pop() ^ Pop());
1579 return SCRIPT_CONTINUE;
1580 }
1581
CmdNegateLogical(void)1582 static int CmdNegateLogical(void)
1583 {
1584 Push(!Pop());
1585 return SCRIPT_CONTINUE;
1586 }
1587
CmdLShift(void)1588 static int CmdLShift(void)
1589 {
1590 int operand2;
1591
1592 operand2 = Pop();
1593 Push(Pop() << operand2);
1594 return SCRIPT_CONTINUE;
1595 }
1596
CmdRShift(void)1597 static int CmdRShift(void)
1598 {
1599 int operand2;
1600
1601 operand2 = Pop();
1602 Push(Pop() >> operand2);
1603 return SCRIPT_CONTINUE;
1604 }
1605
CmdUnaryMinus(void)1606 static int CmdUnaryMinus(void)
1607 {
1608 Push(-Pop());
1609 return SCRIPT_CONTINUE;
1610 }
1611
CmdIfNotGoto(void)1612 static int CmdIfNotGoto(void)
1613 {
1614 if (Pop() != 0)
1615 {
1616 ++PCodePtr;
1617 }
1618 else
1619 {
1620 PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
1621 }
1622 return SCRIPT_CONTINUE;
1623 }
1624
CmdLineSide(void)1625 static int CmdLineSide(void)
1626 {
1627 Push(ACScript->side);
1628 return SCRIPT_CONTINUE;
1629 }
1630
CmdScriptWait(void)1631 static int CmdScriptWait(void)
1632 {
1633 ACSInfo[ACScript->infoIndex].waitValue = Pop();
1634 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
1635 return SCRIPT_STOP;
1636 }
1637
CmdScriptWaitDirect(void)1638 static int CmdScriptWaitDirect(void)
1639 {
1640 ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr);
1641 ++PCodePtr;
1642 ACSInfo[ACScript->infoIndex].state = ASTE_WAITINGFORSCRIPT;
1643 return SCRIPT_STOP;
1644 }
1645
CmdClearLineSpecial(void)1646 static int CmdClearLineSpecial(void)
1647 {
1648 if (ACScript->line)
1649 {
1650 ACScript->line->special = 0;
1651 }
1652 return SCRIPT_CONTINUE;
1653 }
1654
CmdCaseGoto(void)1655 static int CmdCaseGoto(void)
1656 {
1657 int value;
1658
1659 value = LONG(*PCodePtr);
1660 ++PCodePtr;
1661
1662 if (Top() == value)
1663 {
1664 PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr));
1665 Drop();
1666 }
1667 else
1668 {
1669 ++PCodePtr;
1670 }
1671
1672 return SCRIPT_CONTINUE;
1673 }
1674
CmdBeginPrint(void)1675 static int CmdBeginPrint(void)
1676 {
1677 *PrintBuffer = 0;
1678 return SCRIPT_CONTINUE;
1679 }
1680
CmdEndPrint(void)1681 static int CmdEndPrint(void)
1682 {
1683 player_t *player;
1684
1685 if (ACScript->activator && ACScript->activator->player)
1686 {
1687 player = ACScript->activator->player;
1688 }
1689 else
1690 {
1691 player = &players[consoleplayer];
1692 }
1693 P_SetMessage(player, PrintBuffer, true);
1694 return SCRIPT_CONTINUE;
1695 }
1696
CmdEndPrintBold(void)1697 static int CmdEndPrintBold(void)
1698 {
1699 int i;
1700
1701 for (i = 0; i < maxplayers; i++)
1702 {
1703 if (playeringame[i])
1704 {
1705 P_SetYellowMessage(&players[i], PrintBuffer, true);
1706 }
1707 }
1708 return SCRIPT_CONTINUE;
1709 }
1710
CmdPrintString(void)1711 static int CmdPrintString(void)
1712 {
1713 M_StringConcat(PrintBuffer, ACStrings[Pop()], sizeof(PrintBuffer));
1714 return SCRIPT_CONTINUE;
1715 }
1716
CmdPrintNumber(void)1717 static int CmdPrintNumber(void)
1718 {
1719 char tempStr[16];
1720
1721 M_snprintf(tempStr, sizeof(tempStr), "%d", Pop());
1722 M_StringConcat(PrintBuffer, tempStr, sizeof(PrintBuffer));
1723 return SCRIPT_CONTINUE;
1724 }
1725
CmdPrintCharacter(void)1726 static int CmdPrintCharacter(void)
1727 {
1728 char *bufferEnd;
1729
1730 bufferEnd = PrintBuffer + strlen(PrintBuffer);
1731 *bufferEnd++ = Pop();
1732 *bufferEnd = 0;
1733 return SCRIPT_CONTINUE;
1734 }
1735
CmdPlayerCount(void)1736 static int CmdPlayerCount(void)
1737 {
1738 int i;
1739 int count;
1740
1741 count = 0;
1742 for (i = 0; i < maxplayers; i++)
1743 {
1744 count += playeringame[i];
1745 }
1746 Push(count);
1747 return SCRIPT_CONTINUE;
1748 }
1749
CmdGameType(void)1750 static int CmdGameType(void)
1751 {
1752 int gametype;
1753
1754 if (netgame == false)
1755 {
1756 gametype = GAME_SINGLE_PLAYER;
1757 }
1758 else if (deathmatch)
1759 {
1760 gametype = GAME_NET_DEATHMATCH;
1761 }
1762 else
1763 {
1764 gametype = GAME_NET_COOPERATIVE;
1765 }
1766 Push(gametype);
1767 return SCRIPT_CONTINUE;
1768 }
1769
CmdGameSkill(void)1770 static int CmdGameSkill(void)
1771 {
1772 Push(gameskill);
1773 return SCRIPT_CONTINUE;
1774 }
1775
CmdTimer(void)1776 static int CmdTimer(void)
1777 {
1778 Push(leveltime);
1779 return SCRIPT_CONTINUE;
1780 }
1781
CmdSectorSound(void)1782 static int CmdSectorSound(void)
1783 {
1784 int volume;
1785 mobj_t *mobj;
1786
1787 mobj = NULL;
1788 if (ACScript->line)
1789 {
1790 mobj = (mobj_t *) & ACScript->line->frontsector->soundorg;
1791 }
1792 volume = Pop();
1793 S_StartSoundAtVolume(mobj, S_GetSoundID(ACStrings[Pop()]), volume);
1794 return SCRIPT_CONTINUE;
1795 }
1796
CmdThingSound(void)1797 static int CmdThingSound(void)
1798 {
1799 int tid;
1800 int sound;
1801 int volume;
1802 mobj_t *mobj;
1803 int searcher;
1804
1805 volume = Pop();
1806 sound = S_GetSoundID(ACStrings[Pop()]);
1807 tid = Pop();
1808 searcher = -1;
1809 while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
1810 {
1811 S_StartSoundAtVolume(mobj, sound, volume);
1812 }
1813 return SCRIPT_CONTINUE;
1814 }
1815
CmdAmbientSound(void)1816 static int CmdAmbientSound(void)
1817 {
1818 int volume;
1819
1820 volume = Pop();
1821 S_StartSoundAtVolume(NULL, S_GetSoundID(ACStrings[Pop()]), volume);
1822 return SCRIPT_CONTINUE;
1823 }
1824
CmdSoundSequence(void)1825 static int CmdSoundSequence(void)
1826 {
1827 mobj_t *mobj;
1828
1829 mobj = NULL;
1830 if (ACScript->line)
1831 {
1832 mobj = (mobj_t *) & ACScript->line->frontsector->soundorg;
1833 }
1834 SN_StartSequenceName(mobj, ACStrings[Pop()]);
1835 return SCRIPT_CONTINUE;
1836 }
1837
CmdSetLineTexture(void)1838 static int CmdSetLineTexture(void)
1839 {
1840 line_t *line;
1841 int lineTag;
1842 int side;
1843 int position;
1844 int texture;
1845 int searcher;
1846
1847 texture = R_TextureNumForName(ACStrings[Pop()]);
1848 position = Pop();
1849 side = Pop();
1850 lineTag = Pop();
1851 searcher = -1;
1852 while ((line = P_FindLine(lineTag, &searcher)) != NULL)
1853 {
1854 if (position == TEXTURE_MIDDLE)
1855 {
1856 sides[line->sidenum[side]].midtexture = texture;
1857 }
1858 else if (position == TEXTURE_BOTTOM)
1859 {
1860 sides[line->sidenum[side]].bottomtexture = texture;
1861 }
1862 else
1863 { // TEXTURE_TOP
1864 sides[line->sidenum[side]].toptexture = texture;
1865 }
1866 }
1867 return SCRIPT_CONTINUE;
1868 }
1869
CmdSetLineBlocking(void)1870 static int CmdSetLineBlocking(void)
1871 {
1872 line_t *line;
1873 int lineTag;
1874 boolean blocking;
1875 int searcher;
1876
1877 blocking = Pop()? ML_BLOCKING : 0;
1878 lineTag = Pop();
1879 searcher = -1;
1880 while ((line = P_FindLine(lineTag, &searcher)) != NULL)
1881 {
1882 line->flags = (line->flags & ~ML_BLOCKING) | blocking;
1883 }
1884 return SCRIPT_CONTINUE;
1885 }
1886
CmdSetLineSpecial(void)1887 static int CmdSetLineSpecial(void)
1888 {
1889 line_t *line;
1890 int lineTag;
1891 int special, arg1, arg2, arg3, arg4, arg5;
1892 int searcher;
1893
1894 arg5 = Pop();
1895 arg4 = Pop();
1896 arg3 = Pop();
1897 arg2 = Pop();
1898 arg1 = Pop();
1899 special = Pop();
1900 lineTag = Pop();
1901 searcher = -1;
1902 while ((line = P_FindLine(lineTag, &searcher)) != NULL)
1903 {
1904 line->special = special;
1905 line->arg1 = arg1;
1906 line->arg2 = arg2;
1907 line->arg3 = arg3;
1908 line->arg4 = arg4;
1909 line->arg5 = arg5;
1910 }
1911 return SCRIPT_CONTINUE;
1912 }
1913