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