1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_lnspec.cpp 4542 2014-02-09 17:39:42Z dr_sean $
5 //
6 // Copyright (C) 1998-2006 by Randy Heit (ZDoom).
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 //	Each function returns true if it caused something to happen
21 //	or false if it couldn't perform the desired action.
22 //
23 //-----------------------------------------------------------------------------
24 
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include "doomstat.h"
30 #include "p_local.h"
31 #include "p_lnspec.h"
32 #include "g_level.h"
33 #include "v_palette.h"
34 #include "tables.h"
35 #include "i_system.h"
36 
37 #define FUNC(a) static BOOL a (line_t *ln, AActor *it, int arg0, int arg1, \
38 							   int arg2, int arg3, int arg4)
39 
40 #define SPEED(a)		((a)*(FRACUNIT/8))
41 #define TICS(a)			(((a)*TICRATE)/35)
42 #define OCTICS(a)		(((a)*TICRATE)/8)
43 #define	BYTEANGLE(a)	((angle_t)((a)<<24))
44 
45 // Used by the teleporters to know if they were
46 // activated by walking across the backside of a line.
47 int TeleportSide;
48 extern bool HasBehavior;
49 
50 // Set true if this special was activated from inside a script.
51 BOOL InScript;
52 
53 // 9/11/10: Add poly action definitions here, even though they're in p_local...
54 // Why are these needed here?  Linux won't compile without these definitions??
55 //
56 BOOL EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, BOOL overRide);
57 BOOL EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, int delay, int distance, podoortype_t type);
58 BOOL EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, BOOL overRide);
59 
60 //
61 // P_LineSpecialMovesSector
62 //
63 // Returns true if the special for line will cause a DMovingFloor or
64 // DMovingCeiling object to be created.
65 //
P_LineSpecialMovesSector(line_t * line)66 bool P_LineSpecialMovesSector(line_t *line)
67 {
68 	if (!line)
69 		return false;
70 
71 	static bool initialized = false;
72 	static bool specials[256];
73 
74 	if (!initialized)
75 	{
76 		// generate a lookup table for line specials
77 		initialized = true;
78 		memset(specials, 0, sizeof(specials));
79 
80 		specials[Door_Close]					= true;		// 10
81 		specials[Door_Open]						= true;		// 11
82 		specials[Door_Raise]					= true;		// 12
83 		specials[Door_LockedRaise]				= true;		// 13
84 		specials[Floor_LowerByValue]			= true;		// 20
85 		specials[Floor_LowerToLowest]			= true;		// 21
86 		specials[Floor_LowerToNearest]			= true;		// 22
87 		specials[Floor_RaiseByValue]			= true;		// 23
88 		specials[Floor_RaiseToHighest]			= true;		// 24
89 		specials[Floor_RaiseToNearest]			= true;		// 25
90 		specials[Stairs_BuildDown]				= true;		// 26
91 		specials[Stairs_BuildUp]				= true;		// 27
92 		specials[Floor_RaiseAndCrush]			= true;		// 28
93 		specials[Pillar_Build]					= true;		// 29
94 		specials[Pillar_Open]					= true;		// 30
95 		specials[Stairs_BuildDownSync]			= true;		// 31
96 		specials[Stairs_BuildUpSync]			= true;		// 32
97 		specials[Floor_RaiseByValueTimes8]		= true;		// 35
98 		specials[Floor_LowerByValueTimes8]		= true;		// 36
99 		specials[Ceiling_LowerByValue]			= true;		// 40
100 		specials[Ceiling_RaiseByValue]			= true;		// 41
101 		specials[Ceiling_CrushAndRaise]			= true;		// 42
102 		specials[Ceiling_LowerAndCrush]			= true;		// 43
103 		specials[Ceiling_CrushStop]				= true;		// 44
104 		specials[Ceiling_CrushRaiseAndStay]		= true;		// 45
105 		specials[Floor_CrushStop]				= true;		// 46
106 		specials[Plat_PerpetualRaise]			= true;		// 60
107 		specials[Plat_Stop]						= true;		// 61
108 		specials[Plat_DownWaitUpStay]			= true;		// 62
109 		specials[Plat_DownByValue]				= true;		// 63
110 		specials[Plat_UpWaitDownStay]			= true;		// 64
111 		specials[Plat_UpByValue]				= true;		// 65
112 		specials[Floor_LowerInstant]			= true;		// 66
113 		specials[Floor_RaiseInstant]			= true;		// 67
114 		specials[Floor_MoveToValueTimes8]		= true;		// 68
115 		specials[Ceiling_MoveToValueTimes8]		= true;		// 69
116 		specials[Pillar_BuildAndCrush]			= true;		// 94
117 		specials[FloorAndCeiling_LowerByValue]	= true;		// 95
118 		specials[FloorAndCeiling_RaiseByValue]	= true;		// 96
119 		specials[Ceiling_LowerToHighestFloor]	= true;		// 192
120 		specials[Ceiling_LowerInstant]			= true;		// 193
121 		specials[Ceiling_RaiseInstant]			= true;		// 194
122 		specials[Ceiling_CrushRaiseAndStayA]	= true;		// 195
123 		specials[Ceiling_CrushAndRaiseA]		= true;		// 196
124 		specials[Ceiling_CrushAndRaiseSilentA]	= true;		// 197
125 		specials[Ceiling_RaiseByValueTimes8]	= true;		// 198
126 		specials[Ceiling_LowerByValueTimes8]	= true;		// 199
127 		specials[Generic_Floor]					= true;		// 200
128 		specials[Generic_Ceiling]				= true;		// 201
129 		specials[Generic_Door]					= true;		// 202
130 		specials[Generic_Lift]					= true;		// 203
131 		specials[Generic_Stairs]				= true;		// 204
132 		specials[Generic_Crusher]				= true;		// 205
133 		specials[Plat_DownWaitUpStayLip]		= true;		// 206
134 		specials[Plat_PerpetualRaiseLip]		= true;		// 207
135 		specials[Stairs_BuildUpDoom]			= true;		// 217
136 		specials[Plat_RaiseAndStayTx0]			= true;		// 228
137 		specials[Plat_UpByValueStayTx]			= true;		// 230
138 		specials[Plat_ToggleCeiling]			= true;		// 231
139 		specials[Floor_RaiseToLowestCeiling]	= true;		// 238
140 		specials[Floor_RaiseByValueTxTy]		= true;		// 239
141 		specials[Floor_RaiseByTexture]			= true;		// 240
142 		specials[Floor_LowerToLowestTxTy]		= true;		// 241
143 		specials[Floor_LowerToHighest]			= true;		// 242
144 		specials[Elevator_RaiseToNearest]		= true;		// 245
145 		specials[Elevator_MoveToFloor]			= true;		// 246
146 		specials[Elevator_LowerToNearest]		= true;		// 247
147 		specials[Door_CloseWaitOpen]			= true;		// 249
148 		specials[Floor_Donut]					= true;		// 250
149 		specials[FloorAndCeiling_LowerRaise]	= true;		// 251
150 		specials[Ceiling_RaiseToNearest]		= true;		// 252
151 		specials[Ceiling_LowerToLowest]			= true;		// 253
152 		specials[Ceiling_LowerToFloor]			= true;		// 254
153 		specials[Ceiling_CrushRaiseAndStaySilA]	= true;		// 255
154 	}
155 
156 	return specials[line->special];
157 }
158 
EXTERN_CVAR(cl_predictsectors)159 EXTERN_CVAR (cl_predictsectors)
160 
161 bool P_CanActivateSpecials(line_t *line)
162 {
163 	return serverside || cl_predictsectors || !P_LineSpecialMovesSector(line);
164 }
165 
FUNC(LS_NOP)166 FUNC(LS_NOP)
167 {
168 	return false;
169 }
170 
FUNC(LS_Polyobj_RotateLeft)171 FUNC(LS_Polyobj_RotateLeft)
172 // Polyobj_RotateLeft (po, speed, angle)
173 {
174 	return EV_RotatePoly (ln, arg0, arg1, arg2, 1, false);
175 }
176 
FUNC(LS_Polyobj_RotateRight)177 FUNC(LS_Polyobj_RotateRight)
178 // Polyobj_rotateRight (po, speed, angle)
179 {
180 	return EV_RotatePoly (ln, arg0, arg1, arg2, -1, false);
181 }
182 
FUNC(LS_Polyobj_Move)183 FUNC(LS_Polyobj_Move)
184 // Polyobj_Move (po, speed, angle, distance)
185 {
186 	return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT, false);
187 }
188 
FUNC(LS_Polyobj_MoveTimes8)189 FUNC(LS_Polyobj_MoveTimes8)
190 // Polyobj_MoveTimes8 (po, speed, angle, distance)
191 {
192 	return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT * 8, false);
193 }
194 
FUNC(LS_Polyobj_DoorSwing)195 FUNC(LS_Polyobj_DoorSwing)
196 // Polyobj_DoorSwing (po, speed, angle, delay)
197 {
198 	return EV_OpenPolyDoor (ln, arg0, arg1, BYTEANGLE(arg2), arg3, 0, PODOOR_SWING);
199 }
200 
FUNC(LS_Polyobj_DoorSlide)201 FUNC(LS_Polyobj_DoorSlide)
202 // Polyobj_DoorSlide (po, speed, angle, distance, delay)
203 {
204 	return EV_OpenPolyDoor (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg4, arg3*FRACUNIT, PODOOR_SLIDE);
205 }
206 
FUNC(LS_Polyobj_OR_RotateLeft)207 FUNC(LS_Polyobj_OR_RotateLeft)
208 // Polyobj_OR_RotateLeft (po, speed, angle)
209 {
210 	return EV_RotatePoly (ln, arg0, arg1, arg2, 1, true);
211 }
212 
FUNC(LS_Polyobj_OR_RotateRight)213 FUNC(LS_Polyobj_OR_RotateRight)
214 // Polyobj_OR_RotateRight (po, speed, angle)
215 {
216 	return EV_RotatePoly (ln, arg0, arg1, arg2, -1, true);
217 }
218 
FUNC(LS_Polyobj_OR_Move)219 FUNC(LS_Polyobj_OR_Move)
220 // Polyobj_OR_Move (po, speed, angle, distance)
221 {
222 	return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT, true);
223 }
224 
FUNC(LS_Polyobj_OR_MoveTimes8)225 FUNC(LS_Polyobj_OR_MoveTimes8)
226 // Polyobj_OR_MoveTimes8 (po, speed, angle, distance)
227 {
228 	return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT * 8, true);
229 }
230 
FUNC(LS_Door_Close)231 FUNC(LS_Door_Close)
232 // Door_Close (tag, speed)
233 {
234 	return EV_DoDoor (DDoor::doorClose, ln, it, arg0, SPEED(arg1), 0, NoKey);
235 }
236 
FUNC(LS_Door_Open)237 FUNC(LS_Door_Open)
238 // Door_Open (tag, speed)
239 {
240 	return EV_DoDoor (DDoor::doorOpen, ln, it, arg0, SPEED(arg1), 0, NoKey);
241 }
242 
FUNC(LS_Door_Raise)243 FUNC(LS_Door_Raise)
244 // Door_Raise (tag, speed, delay)
245 {
246 	return EV_DoDoor (DDoor::doorRaise, ln, it, arg0, SPEED(arg1), TICS(arg2), NoKey);
247 }
248 
FUNC(LS_Door_LockedRaise)249 FUNC(LS_Door_LockedRaise)
250 // Door_LockedRaise (tag, speed, delay, lock)
251 {
252 	return EV_DoDoor (arg2 ? DDoor::doorRaise : DDoor::doorOpen, ln, it,
253                           arg0, SPEED(arg1), TICS(arg2), (card_t)arg3);
254 }
255 
FUNC(LS_Door_CloseWaitOpen)256 FUNC(LS_Door_CloseWaitOpen)
257 // Door_CloseWaitOpen (tag, speed, delay)
258 {
259 	return EV_DoDoor (DDoor::doorCloseWaitOpen, ln, it, arg0, SPEED(arg1), OCTICS(arg2), NoKey);
260 }
261 
FUNC(LS_Generic_Door)262 FUNC(LS_Generic_Door)
263 // Generic_Door (tag, speed, kind, delay, lock)
264 {
265 	DDoor::EVlDoor type;
266 
267 	switch (arg2)
268 	{
269 		case 0: type = DDoor::doorRaise;			break;
270 		case 1: type = DDoor::doorOpen;				break;
271 		case 2: type = DDoor::doorCloseWaitOpen;	break;
272 		case 3: type = DDoor::doorClose;			break;
273 		default: return false;
274 	}
275         return EV_DoDoor (type, ln, it, arg0, SPEED(arg1), OCTICS(arg3), (card_t)arg4);
276 }
277 
FUNC(LS_Floor_LowerByValue)278 FUNC(LS_Floor_LowerByValue)
279 // Floor_LowerByValue (tag, speed, height)
280 {
281 	return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0);
282 }
283 
FUNC(LS_Floor_LowerToLowest)284 FUNC(LS_Floor_LowerToLowest)
285 // Floor_LowerToLowest (tag, speed)
286 {
287 	return EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0);
288 }
289 
FUNC(LS_Floor_LowerToHighest)290 FUNC(LS_Floor_LowerToHighest)
291 // Floor_LowerToHighest (tag, speed, adjust)
292 {
293 	return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), (arg2-128)*FRACUNIT, 0, 0);
294 }
295 
FUNC(LS_Floor_LowerToNearest)296 FUNC(LS_Floor_LowerToNearest)
297 // Floor_LowerToNearest (tag, speed)
298 {
299 	return EV_DoFloor (DFloor::floorLowerToNearest, ln, arg0, SPEED(arg1), 0, 0, 0);
300 }
301 
FUNC(LS_Floor_RaiseByValue)302 FUNC(LS_Floor_RaiseByValue)
303 // Floor_RaiseByValue (tag, speed, height)
304 {
305 	return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0);
306 }
307 
FUNC(LS_Floor_RaiseToHighest)308 FUNC(LS_Floor_RaiseToHighest)
309 // Floor_RaiseToHighest (tag, speed)
310 {
311 	return EV_DoFloor (DFloor::floorRaiseToHighest, ln, arg0, SPEED(arg1), 0, 0, 0);
312 }
313 
FUNC(LS_Floor_RaiseToNearest)314 FUNC(LS_Floor_RaiseToNearest)
315 // Floor_RaiseToNearest (tag, speed)
316 {
317 	return EV_DoFloor (DFloor::floorRaiseToNearest, ln, arg0, SPEED(arg1), 0, 0, 0);
318 }
319 
FUNC(LS_Floor_RaiseAndCrush)320 FUNC(LS_Floor_RaiseAndCrush)
321 // Floor_RaiseAndCrush (tag, speed, crush)
322 {
323 	return EV_DoFloor (DFloor::floorRaiseAndCrush, ln, arg0, SPEED(arg1), 0, (arg2 != 0), 0);
324 }
325 
FUNC(LS_Floor_RaiseByValueTimes8)326 FUNC(LS_Floor_RaiseByValueTimes8)
327 // FLoor_RaiseByValueTimes8 (tag, speed, height)
328 {
329 	return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0);
330 }
331 
FUNC(LS_Floor_LowerByValueTimes8)332 FUNC(LS_Floor_LowerByValueTimes8)
333 // Floor_LowerByValueTimes8 (tag, speed, height)
334 {
335 	return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0);
336 }
337 
FUNC(LS_Floor_CrushStop)338 FUNC(LS_Floor_CrushStop)
339 // Floor_CrushStop (tag)
340 {
341 //	return EV_FloorCrushStop (arg0);
342 	return 0;
343 }
344 
FUNC(LS_Floor_LowerInstant)345 FUNC(LS_Floor_LowerInstant)
346 // Floor_LowerInstant (tag, unused, height)
347 {
348 	return EV_DoFloor (DFloor::floorLowerInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0);
349 }
350 
FUNC(LS_Floor_RaiseInstant)351 FUNC(LS_Floor_RaiseInstant)
352 // Floor_RaiseInstant (tag, unused, height)
353 {
354 	return EV_DoFloor (DFloor::floorRaiseInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0);
355 }
356 
FUNC(LS_Floor_MoveToValueTimes8)357 FUNC(LS_Floor_MoveToValueTimes8)
358 // Floor_MoveToValueTimes8 (tag, speed, height, negative)
359 {
360 	return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1),
361 					   arg2*FRACUNIT*8*(arg3?-1:1), 0, 0);
362 }
363 
FUNC(LS_Floor_RaiseToLowestCeiling)364 FUNC(LS_Floor_RaiseToLowestCeiling)
365 // Floor_RaiseToLowestCeiling (tag, speed)
366 {
367 	return EV_DoFloor (DFloor::floorRaiseToLowestCeiling, ln, arg0, SPEED(arg1), 0, 0, 0);
368 }
369 
FUNC(LS_Floor_RaiseByTexture)370 FUNC(LS_Floor_RaiseByTexture)
371 // Floor_RaiseByTexture (tag, speed)
372 {
373 	return EV_DoFloor (DFloor::floorRaiseByTexture, ln, arg0, SPEED(arg1), 0, 0, 0);
374 }
375 
FUNC(LS_Floor_RaiseByValueTxTy)376 FUNC(LS_Floor_RaiseByValueTxTy)
377 // Floor_RaiseByValueTxTy (tag, speed, height)
378 {
379 	return EV_DoFloor (DFloor::floorRaiseAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0);
380 }
381 
FUNC(LS_Floor_LowerToLowestTxTy)382 FUNC(LS_Floor_LowerToLowestTxTy)
383 // Floor_LowerToLowestTxTy (tag, speed)
384 {
385 	return EV_DoFloor (DFloor::floorLowerAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0);
386 }
387 
FUNC(LS_Floor_Waggle)388 FUNC(LS_Floor_Waggle)
389 // Floor_Waggle (tag, amplitude, frequency, delay, time)
390 {
391 //	return EV_StartFloorWaggle (arg0, arg1, arg2, arg3, arg4);
392 	return 0;
393 }
394 
FUNC(LS_Floor_TransferTrigger)395 FUNC(LS_Floor_TransferTrigger)
396 // Floor_TransferTrigger (tag)
397 {
398 	return EV_DoChange (ln, trigChangeOnly, arg0);
399 }
400 
FUNC(LS_Floor_TransferNumeric)401 FUNC(LS_Floor_TransferNumeric)
402 // Floor_TransferNumeric (tag)
403 {
404 	return EV_DoChange (ln, numChangeOnly, arg0);
405 }
406 
FUNC(LS_Floor_Donut)407 FUNC(LS_Floor_Donut)
408 // Floor_Donut (pillartag, pillarspeed, slimespeed)
409 {
410 	return EV_DoDonut (arg0, SPEED(arg1), SPEED(arg2));
411 }
412 
FUNC(LS_Generic_Floor)413 FUNC(LS_Generic_Floor)
414 // Generic_Floor (tag, speed, height, target, change/model/direct/crush)
415 {
416 	DFloor::EFloor type;
417 
418 	if (arg4 & 8)
419 	{
420 		switch (arg3)
421 		{
422 			case 1: type = DFloor::floorRaiseToHighest;			break;
423 			case 2: type = DFloor::floorRaiseToLowest;			break;
424 			case 3: type = DFloor::floorRaiseToNearest;			break;
425 			case 4: type = DFloor::floorRaiseToLowestCeiling;	break;
426 			case 5: type = DFloor::floorRaiseToCeiling;			break;
427 			case 6: type = DFloor::floorRaiseByTexture;			break;
428 			default:type = DFloor::floorRaiseByValue;			break;
429 		}
430 	}
431 	else
432 	{
433 		switch (arg3)
434 		{
435 			case 1: type = DFloor::floorLowerToHighest;			break;
436 			case 2: type = DFloor::floorLowerToLowest;			break;
437 			case 3: type = DFloor::floorLowerToNearest;			break;
438 			case 4: type = DFloor::floorLowerToLowestCeiling;	break;
439 			case 5: type = DFloor::floorLowerToCeiling;			break;
440 			case 6: type = DFloor::floorLowerByTexture;			break;
441 			default:type = DFloor::floorLowerByValue;			break;
442 		}
443 	}
444 
445 	return EV_DoFloor (type, ln, arg0, SPEED(arg1), arg2*FRACUNIT,
446 					   (arg4 & 16) ? 20 : -1, arg4 & 7);
447 
448 }
449 
FUNC(LS_Stairs_BuildDown)450 FUNC(LS_Stairs_BuildDown)
451 // Stair_BuildDown (tag, speed, height, delay, reset)
452 {
453 	return EV_BuildStairs (arg0, DFloor::buildDown, ln,
454 						   arg2 * FRACUNIT, SPEED(arg1), TICS(arg3), arg4, 0, 1);
455 }
456 
FUNC(LS_Stairs_BuildUp)457 FUNC(LS_Stairs_BuildUp)
458 // Stairs_BuildUp (tag, speed, height, delay, reset)
459 {
460 	return EV_BuildStairs (arg0, DFloor::buildUp, ln,
461 						   arg2 * FRACUNIT, SPEED(arg1), TICS(arg3), arg4, 0, 1);
462 }
463 
FUNC(LS_Stairs_BuildDownSync)464 FUNC(LS_Stairs_BuildDownSync)
465 // Stairs_BuildDownSync (tag, speed, height, reset)
466 {
467 	return EV_BuildStairs (arg0, DFloor::buildDown, ln,
468 						   arg2 * FRACUNIT, SPEED(arg1), 0, arg3, 0, 2);
469 }
470 
FUNC(LS_Stairs_BuildUpSync)471 FUNC(LS_Stairs_BuildUpSync)
472 // Stairs_BuildUpSync (tag, speed, height, reset)
473 {
474 	return EV_BuildStairs (arg0, DFloor::buildUp, ln,
475 						   arg2 * FRACUNIT, SPEED(arg1), 0, arg3, 0, 2);
476 }
477 
FUNC(LS_Stairs_BuildUpDoom)478 FUNC(LS_Stairs_BuildUpDoom)
479 // Stairs_BuildUpDoom (tag, speed, height, delay, reset)
480 {
481 	return EV_BuildStairs (arg0, DFloor::buildUp, ln,
482 						   arg2 * FRACUNIT, SPEED(arg1), TICS(arg3), arg4, 0, 0);
483 }
484 
FUNC(LS_Generic_Stairs)485 FUNC(LS_Generic_Stairs)
486 // Generic_Stairs (tag, speed, step, dir/igntxt, reset)
487 {
488 	DFloor::EStair type = (arg3 & 1) ? DFloor::buildUp : DFloor::buildDown;
489 	BOOL res = EV_BuildStairs (arg0, type, ln,
490 							   arg2 * FRACUNIT, SPEED(arg1), 0, arg4, arg3 & 2, 0);
491 
492 	if (res && ln && (ln->flags & ML_REPEAT_SPECIAL) && ln->special == Generic_Stairs)
493 		// Toggle direction of next activation of repeatable stairs
494 		arg3 ^= 1;
495 
496 	return res;
497 }
498 
FUNC(LS_Pillar_Build)499 FUNC(LS_Pillar_Build)
500 // Pillar_Build (tag, speed, height)
501 {
502 	return EV_DoPillar (DPillar::pillarBuild, arg0, SPEED(arg1), arg2*FRACUNIT, 0, -1);
503 }
504 
FUNC(LS_Pillar_Open)505 FUNC(LS_Pillar_Open)
506 // Pillar_Open (tag, speed, f_height, c_height)
507 {
508 	return EV_DoPillar (DPillar::pillarOpen, arg0, SPEED(arg1), arg2*FRACUNIT, arg3*FRACUNIT, -1);
509 }
510 
FUNC(LS_Ceiling_LowerByValue)511 FUNC(LS_Ceiling_LowerByValue)
512 // Ceiling_LowerByValue (tag, speed, height)
513 {
514 	return EV_DoCeiling (DCeiling::ceilLowerByValue, ln, arg0, SPEED(arg1), 0, arg2*FRACUNIT, 0, 0, 0);
515 }
516 
FUNC(LS_Ceiling_RaiseByValue)517 FUNC(LS_Ceiling_RaiseByValue)
518 // Ceiling_RaiseByValue (tag, speed, height)
519 {
520 	return EV_DoCeiling (DCeiling::ceilRaiseByValue, ln, arg0, SPEED(arg1), 0, arg2*FRACUNIT, 0, 0, 0);
521 }
522 
FUNC(LS_Ceiling_LowerByValueTimes8)523 FUNC(LS_Ceiling_LowerByValueTimes8)
524 // Ceiling_LowerByValueTimes8 (tag, speed, height)
525 {
526 	return EV_DoCeiling (DCeiling::ceilLowerByValue, ln, arg0, SPEED(arg1), 0, arg2*FRACUNIT*8, 0, 0, 0);
527 }
528 
FUNC(LS_Ceiling_RaiseByValueTimes8)529 FUNC(LS_Ceiling_RaiseByValueTimes8)
530 // Ceiling_RaiseByValueTimes8 (tag, speed, height)
531 {
532 	return EV_DoCeiling (DCeiling::ceilRaiseByValue, ln, arg0, SPEED(arg1), 0, arg2*FRACUNIT*8, 0, 0, 0);
533 }
534 
FUNC(LS_Ceiling_CrushAndRaise)535 FUNC(LS_Ceiling_CrushAndRaise)
536 // Ceiling_CrushAndRaise (tag, speed, crush)
537 {
538 	return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), SPEED(arg1)/2, 0, (arg2 != 0), 0, 0);
539 }
540 
FUNC(LS_Ceiling_LowerAndCrush)541 FUNC(LS_Ceiling_LowerAndCrush)
542 // Ceiling_LowerAndCrush (tag, speed, crush)
543 {
544 	return EV_DoCeiling (DCeiling::ceilLowerAndCrush, ln, arg0, SPEED(arg1), SPEED(arg1)/2, 0, (arg2 != 0), 0, 0);
545 }
546 
FUNC(LS_Ceiling_CrushStop)547 FUNC(LS_Ceiling_CrushStop)
548 // Ceiling_CrushStop (tag)
549 {
550 	return EV_CeilingCrushStop (arg0);
551 }
552 
FUNC(LS_Ceiling_CrushRaiseAndStay)553 FUNC(LS_Ceiling_CrushRaiseAndStay)
554 // Ceiling_CrushRaiseAndStay (tag, speed, crush)
555 {
556 	return EV_DoCeiling (DCeiling::ceilCrushRaiseAndStay, ln, arg0, SPEED(arg1), SPEED(arg1)/2, 0, (arg2 != 0), 0, 0);
557 }
558 
FUNC(LS_Ceiling_MoveToValueTimes8)559 FUNC(LS_Ceiling_MoveToValueTimes8)
560 // Ceiling_MoveToValueTimes8 (tag, speed, height, negative)
561 {
562 	return EV_DoCeiling (DCeiling::ceilMoveToValue, ln, arg0, SPEED(arg1), 0,
563 						 arg2*FRACUNIT*8*((arg3) ? -1 : 1), 0, 0, 0);
564 }
565 
FUNC(LS_Ceiling_LowerToHighestFloor)566 FUNC(LS_Ceiling_LowerToHighestFloor)
567 // Ceiling_LowerToHighestFloor (tag, speed)
568 {
569 	return EV_DoCeiling (DCeiling::ceilLowerToHighestFloor, ln, arg0, SPEED(arg1), 0, 0, 0, 0, 0);
570 }
571 
FUNC(LS_Ceiling_LowerInstant)572 FUNC(LS_Ceiling_LowerInstant)
573 // Ceiling_LowerInstant (tag, unused, height)
574 {
575 	return EV_DoCeiling (DCeiling::ceilLowerInstant, ln, arg0, 0, 0, arg2*FRACUNIT*8, 0, 0, 0);
576 }
577 
FUNC(LS_Ceiling_RaiseInstant)578 FUNC(LS_Ceiling_RaiseInstant)
579 // Ceiling_RaiseInstant (tag, unused, height)
580 {
581 	return EV_DoCeiling (DCeiling::ceilRaiseInstant, ln, arg0, 0, 0, arg2*FRACUNIT*8, 0, 0, 0);
582 }
583 
FUNC(LS_Ceiling_CrushRaiseAndStayA)584 FUNC(LS_Ceiling_CrushRaiseAndStayA)
585 // Ceiling_CrushRaiseAndStayA (tag, dnspeed, upspeed, damage)
586 {
587 	return EV_DoCeiling (DCeiling::ceilCrushRaiseAndStay, ln, arg0, SPEED(arg1), SPEED(arg2), 0, (arg3 != 0), 0, 0);
588 }
589 
FUNC(LS_Ceiling_CrushRaiseAndStaySilA)590 FUNC(LS_Ceiling_CrushRaiseAndStaySilA)
591 // Ceiling_CrushRaiseAndStaySilA (tag, dnspeed, upspeed, damage)
592 {
593 	return EV_DoCeiling (DCeiling::ceilCrushRaiseAndStay, ln, arg0, SPEED(arg1), SPEED(arg2), 0, (arg3 != 0), 1, 0);
594 }
595 
FUNC(LS_Ceiling_CrushAndRaiseA)596 FUNC(LS_Ceiling_CrushAndRaiseA)
597 // Ceiling_CrushAndRaiseA (tag, dnspeed, upspeed, damage)
598 {
599 	return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), SPEED(arg2), 0, (arg3 != 0), 0, 0);
600 }
601 
FUNC(LS_Ceiling_CrushAndRaiseSilentA)602 FUNC(LS_Ceiling_CrushAndRaiseSilentA)
603 // Ceiling_CrushAndRaiseSilentA (tag, dnspeed, upspeed, damage)
604 {
605 	return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1), SPEED(arg2), 0, (arg3 != 0), 1, 0);
606 }
607 
FUNC(LS_Ceiling_RaiseToNearest)608 FUNC(LS_Ceiling_RaiseToNearest)
609 // Ceiling_RaiseToNearest (tag, speed)
610 {
611 	return EV_DoCeiling (DCeiling::ceilRaiseToNearest, ln, arg0, SPEED(arg1), 0, 0, 0, 0, 0);
612 }
613 
FUNC(LS_Ceiling_LowerToLowest)614 FUNC(LS_Ceiling_LowerToLowest)
615 // Ceiling_LowerToLowest (tag, speed)
616 {
617 	return EV_DoCeiling (DCeiling::ceilLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0, 0, 0);
618 }
619 
FUNC(LS_Ceiling_LowerToFloor)620 FUNC(LS_Ceiling_LowerToFloor)
621 // Ceiling_LowerToFloor (tag, speed)
622 {
623 	return EV_DoCeiling (DCeiling::ceilLowerToFloor, ln, arg0, SPEED(arg1), 0, 0, 0, 0, 0);
624 }
625 
FUNC(LS_Generic_Ceiling)626 FUNC(LS_Generic_Ceiling)
627 // Generic_Ceiling (tag, speed, height, target, change/model/direct/crush)
628 {
629 	DCeiling::ECeiling type;
630 
631 	if (arg4 & 8) {
632 		switch (arg3) {
633 			case 1:  type = DCeiling::ceilRaiseToHighest;		break;
634 			case 2:  type = DCeiling::ceilRaiseToLowest;		break;
635 			case 3:  type = DCeiling::ceilRaiseToNearest;		break;
636 			case 4:  type = DCeiling::ceilRaiseToHighestFloor;	break;
637 			case 5:  type = DCeiling::ceilRaiseToFloor;			break;
638 			case 6:  type = DCeiling::ceilRaiseByTexture;		break;
639 			default: type = DCeiling::ceilRaiseByValue;			break;
640 		}
641 	} else {
642 		switch (arg3) {
643 			case 1:  type = DCeiling::ceilLowerToHighest;		break;
644 			case 2:  type = DCeiling::ceilLowerToLowest;		break;
645 			case 3:  type = DCeiling::ceilLowerToNearest;		break;
646 			case 4:  type = DCeiling::ceilLowerToHighestFloor;	break;
647 			case 5:  type = DCeiling::ceilLowerToFloor;			break;
648 			case 6:  type = DCeiling::ceilLowerByTexture;		break;
649 			default: type = DCeiling::ceilLowerByValue;			break;
650 		}
651 	}
652 
653 	return EV_DoCeiling (type, ln, arg0, SPEED(arg1), SPEED(arg1), arg2*FRACUNIT,
654 						 (arg4 & 16) ? 20 : -1, 0, arg4 & 7);
655 	return false;
656 }
657 
FUNC(LS_Generic_Crusher)658 FUNC(LS_Generic_Crusher)
659 // Generic_Crusher (tag, dnspeed, upspeed, silent, damage)
660 {
661 	return EV_DoCeiling (DCeiling::ceilCrushAndRaise, ln, arg0, SPEED(arg1),
662 						 SPEED(arg2), 0, (arg4 != 0), arg3 ? 2 : 0, 0);
663 }
664 
FUNC(LS_Plat_PerpetualRaise)665 FUNC(LS_Plat_PerpetualRaise)
666 // Plat_PerpetualRaise (tag, speed, delay)
667 {
668 	return EV_DoPlat (arg0, ln, DPlat::platPerpetualRaise, 0, SPEED(arg1), TICS(arg2), 8*FRACUNIT, 0);
669 }
670 
FUNC(LS_Plat_PerpetualRaiseLip)671 FUNC(LS_Plat_PerpetualRaiseLip)
672 // Plat_PerpetualRaiseLip (tag, speed, delay, lip)
673 {
674 	return EV_DoPlat (arg0, ln, DPlat::platPerpetualRaise, 0, SPEED(arg1), TICS(arg2), arg3*FRACUNIT, 0);
675 }
676 
FUNC(LS_Plat_Stop)677 FUNC(LS_Plat_Stop)
678 // Plat_Stop (tag)
679 {
680 	EV_StopPlat (arg0);
681 	return true;
682 }
683 
FUNC(LS_Plat_DownWaitUpStay)684 FUNC(LS_Plat_DownWaitUpStay)
685 // Plat_DownWaitUpStay (tag, speed, delay)
686 {
687 	return EV_DoPlat (arg0, ln, DPlat::platDownWaitUpStay, 0, SPEED(arg1), TICS(arg2), 8*FRACUNIT, 0);
688 }
689 
FUNC(LS_Plat_DownWaitUpStayLip)690 FUNC(LS_Plat_DownWaitUpStayLip)
691 // Plat_DownWaitUpStayLip (tag, speed, delay, lip)
692 {
693 	return EV_DoPlat (arg0, ln, DPlat::platDownWaitUpStay, 0, SPEED(arg1), TICS(arg2), arg3*FRACUNIT, 0);
694 }
695 
FUNC(LS_Plat_DownByValue)696 FUNC(LS_Plat_DownByValue)
697 // Plat_DownByValue (tag, speed, delay, height)
698 {
699 	return EV_DoPlat (arg0, ln, DPlat::platDownByValue, FRACUNIT*arg3*8, SPEED(arg1), TICS(arg2), 0, 0);
700 }
701 
FUNC(LS_Plat_UpByValue)702 FUNC(LS_Plat_UpByValue)
703 // Plat_UpByValue (tag, speed, delay, height)
704 {
705 	return EV_DoPlat (arg0, ln, DPlat::platUpByValue, FRACUNIT*arg3*8, SPEED(arg1), TICS(arg2), 0, 0);
706 }
707 
FUNC(LS_Plat_UpWaitDownStay)708 FUNC(LS_Plat_UpWaitDownStay)
709 // Plat_UpWaitDownStay (tag, speed, delay)
710 {
711 	return EV_DoPlat (arg0, ln, DPlat::platUpWaitDownStay, 0, SPEED(arg1), TICS(arg2), 0, 0);
712 }
713 
FUNC(LS_Plat_RaiseAndStayTx0)714 FUNC(LS_Plat_RaiseAndStayTx0)
715 // Plat_RaiseAndStayTx0 (tag, speed)
716 {
717 	return EV_DoPlat (arg0, ln, DPlat::platRaiseAndStay, 0, SPEED(arg1), 0, 0, 1);
718 }
719 
FUNC(LS_Plat_UpByValueStayTx)720 FUNC(LS_Plat_UpByValueStayTx)
721 // Plat_UpByValueStayTx (tag, speed, height)
722 {
723 	return EV_DoPlat (arg0, ln, DPlat::platUpByValueStay, FRACUNIT*arg2*8, SPEED(arg1), 0, 0, 2);
724 }
725 
FUNC(LS_Plat_ToggleCeiling)726 FUNC(LS_Plat_ToggleCeiling)
727 // Plat_ToggleCeiling (tag)
728 {
729 	return EV_DoPlat (arg0, ln, DPlat::platToggle, 0, 0, 0, 0, 0);
730 }
731 
FUNC(LS_Generic_Lift)732 FUNC(LS_Generic_Lift)
733 // Generic_Lift (tag, speed, delay, target, height)
734 {
735 	DPlat::EPlatType type;
736 
737 	switch (arg3)
738 	{
739 		case 1:
740 			type = DPlat::platDownWaitUpStay;
741 			break;
742 		case 2:
743 			type = DPlat::platDownToNearestFloor;
744 			break;
745 		case 3:
746 			type = DPlat::platDownToLowestCeiling;
747 			break;
748 		case 4:
749 			type = DPlat::platPerpetualRaise;
750 			break;
751 		default:
752 			type = DPlat::platUpByValue;
753 			break;
754 	}
755 
756 	return EV_DoPlat (arg0, ln, type, arg4*8*FRACUNIT, SPEED(arg1), OCTICS(arg2), 0, 0);
757 }
758 
FUNC(LS_Exit_Normal)759 FUNC(LS_Exit_Normal)
760 // Exit_Normal (position)
761 {
762 	if (it && CheckIfExitIsGood (it))
763 	{
764 		G_ExitLevel (0, 1);
765 		return true;
766 	}
767 	return false;
768 }
769 
FUNC(LS_Exit_Secret)770 FUNC(LS_Exit_Secret)
771 // Exit_Secret (position)
772 {
773 	if (it && CheckIfExitIsGood (it))
774 	{
775 		G_SecretExitLevel (0, 1);
776 		return true;
777 	}
778 	return false;
779 }
780 
FUNC(LS_Teleport_NewMap)781 FUNC(LS_Teleport_NewMap)
782 // Teleport_NewMap (map, position)
783 {
784    	if (!TeleportSide)
785 	{
786         level_info_t *info = FindLevelByNum (arg0);
787 
788         if (it && (info && CheckIfExitIsGood (it)))
789         {
790             strncpy (level.nextmap, info->mapname, 8);
791             G_ExitLevel (arg1, 1);
792             return true;
793         }
794 	}
795 	return false;
796 }
797 
FUNC(LS_Teleport)798 FUNC(LS_Teleport)
799 // Teleport (tid, tag)
800 {
801 	if(!it) return false;
802 	BOOL result;
803 
804 	if (HasBehavior)
805 		// [AM] Use ZDoom-style teleport for Hexen-format maps
806 		result = EV_Teleport(arg0, arg1, TeleportSide, it);
807 	else
808 		// [AM] Use Vanilla-style teleport for Doom-format maps
809 		result = EV_LineTeleport(ln, TeleportSide, it);
810 
811 	return result;
812 }
813 
FUNC(LS_Teleport_NoFog)814 FUNC(LS_Teleport_NoFog)
815 // Teleport_NoFog (tid)
816 {
817 	if(!it) return false;
818 	return EV_SilentTeleport (arg0, ln, TeleportSide, it);
819 }
820 
FUNC(LS_Teleport_EndGame)821 FUNC(LS_Teleport_EndGame)
822 // Teleport_EndGame ()
823 {
824 	if (!TeleportSide && it && CheckIfExitIsGood (it))
825 	{
826 		strncpy (level.nextmap, "EndGameC", 8);
827 		G_ExitLevel (0, 1);
828 		return true;
829 	}
830 	return false;
831 }
832 
FUNC(LS_Teleport_Line)833 FUNC(LS_Teleport_Line)
834 // Teleport_Line (thisid, destid, reversed)
835 {
836 	if(!it) return false;
837 	return EV_SilentLineTeleport (ln, TeleportSide, it, arg1, arg2);
838 }
839 
FUNC(LS_ThrustThing)840 FUNC(LS_ThrustThing)
841 // ThrustThing (angle, force)
842 {
843 	if(!it) return false;
844 
845 	angle_t angle = BYTEANGLE(arg0) >> ANGLETOFINESHIFT;
846 
847 	it->momx = arg1 * finecosine[angle];
848 	it->momy = arg1 * finesine[angle];
849 
850 	return true;
851 }
852 
FUNC(LS_ThrustThingZ)853 FUNC(LS_ThrustThingZ)
854 // ThrustThingZ (tid, zthrust, down/up, set)
855 {
856 	AActor *victim;
857 	fixed_t thrust = arg1*FRACUNIT/4;
858 
859 	// [BC] Up is default
860 	if (arg2)
861 		thrust = -thrust;
862 
863 	if (arg0 != 0)
864 	{
865 		FActorIterator iterator (arg0);
866 
867 		while ( (victim = iterator.Next ()) )
868 		{
869 			if (!arg3)
870 				victim->momz = thrust;
871 			else
872 				victim->momz += thrust;
873 		}
874 		return true;
875 	}
876 	else if (it)
877 	{
878 		if (!arg3)
879 			it->momz = thrust;
880 		else
881 			it->momz += thrust;
882 		return true;
883 	}
884 	return false;
885 }
886 
FUNC(LS_DamageThing)887 FUNC(LS_DamageThing)
888 // DamageThing (damage)
889 {
890 	if(!it) return false;
891 
892 	if (arg0)
893 		P_DamageMobj (it, NULL, NULL, arg0, MOD_UNKNOWN);
894 	else
895 		P_DamageMobj (it, NULL, NULL, 10000, MOD_UNKNOWN);
896 
897 	return true;
898 }
899 
900 BOOL P_GiveBody (player_t *, int);
901 
FUNC(LS_HealThing)902 FUNC(LS_HealThing)
903 // HealThing (amount)
904 {
905 	if(!it) return false;
906 
907 	if (it->player)
908 	{
909 		P_GiveBody (it->player, arg0);
910 	}
911 	else
912 	{
913 		it->health += arg0;
914 		if (mobjinfo[it->type].spawnhealth > it->health)
915 			it->health = mobjinfo[it->type].spawnhealth;
916 	}
917 
918 	return true;
919 }
920 
FUNC(LS_Thing_Activate)921 FUNC(LS_Thing_Activate)
922 // Thing_Activate (tid)
923 {
924 	AActor *mobj = AActor::FindByTID (NULL, arg0);
925 
926 	while (mobj)
927 	{
928 		AActor *temp = mobj->FindByTID (arg0);
929 		P_ActivateMobj (mobj, it);
930 		mobj = temp;
931 	}
932 
933 	return true;
934 }
935 
FUNC(LS_Thing_Deactivate)936 FUNC(LS_Thing_Deactivate)
937 // Thing_Deactivate (tid)
938 {
939 	AActor *mobj = AActor::FindByTID (NULL, arg0);
940 
941 	while (mobj)
942 	{
943 		AActor *temp = mobj->FindByTID (arg0);
944 		P_DeactivateMobj (mobj);
945 		mobj = temp;
946 	}
947 
948 	return true;
949 }
950 
FUNC(LS_Thing_Remove)951 FUNC(LS_Thing_Remove)
952 // Thing_Remove (tid)
953 {
954 	AActor *mobj = AActor::FindByTID (NULL, arg0);
955 
956 	while (mobj)
957 	{
958 		AActor *temp = mobj->FindByTID (arg0);
959 		mobj->Destroy ();
960 		mobj = temp;
961 	}
962 
963 	return true;
964 }
965 
FUNC(LS_Thing_Destroy)966 FUNC(LS_Thing_Destroy)
967 // Thing_Destroy (tid)
968 {
969 	AActor *mobj = AActor::FindByTID (NULL, arg0);
970 
971 	while (mobj)
972 	{
973 		AActor *temp = mobj->FindByTID (arg0);
974 
975 		if (mobj->flags & MF_SHOOTABLE)
976 			P_DamageMobj (mobj, NULL, it, mobj->health, MOD_UNKNOWN);
977 
978 		mobj = temp;
979 	}
980 
981 	return true;
982 }
983 
FUNC(LS_Thing_Projectile)984 FUNC(LS_Thing_Projectile)
985 // Thing_Projectile (tid, type, angle, speed, vspeed)
986 {
987 	return P_Thing_Projectile (arg0, arg1, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
988 		arg4<<(FRACBITS-3), false);
989 }
990 
FUNC(LS_Thing_ProjectileGravity)991 FUNC(LS_Thing_ProjectileGravity)
992 // Thing_ProjectileGravity (tid, type, angle, speed, vspeed)
993 {
994 	return P_Thing_Projectile (arg0, arg1, BYTEANGLE(arg2), arg3<<(FRACBITS-3),
995 		arg4<<(FRACBITS-3), true);
996 }
997 
FUNC(LS_Thing_Spawn)998 FUNC(LS_Thing_Spawn)
999 // Thing_Spawn (tid, type, angle)
1000 {
1001 	return P_Thing_Spawn (arg0, arg1, BYTEANGLE(arg2), true);
1002 }
1003 
FUNC(LS_Thing_SpawnNoFog)1004 FUNC(LS_Thing_SpawnNoFog)
1005 // Thing_SpawnNoFog (tid, type, angle)
1006 {
1007 	return P_Thing_Spawn (arg0, arg1, BYTEANGLE(arg2), false);
1008 }
1009 
FUNC(LS_Thing_SetGoal)1010 FUNC(LS_Thing_SetGoal)
1011 // Thing_SetGoal (tid, goal, delay)
1012 {
1013 	AActor *self = AActor::FindByTID (NULL, arg0);
1014 	AActor *goal = AActor::FindGoal (NULL, arg1, MT_PATHNODE);
1015 
1016 	while (self)
1017 	{
1018 		if (goal && (self->flags & MF_SHOOTABLE))
1019 		{
1020 			self->goal = goal->ptr();
1021 			if (!self->target)
1022 				self->reactiontime = arg2 * TICRATE;
1023 		}
1024 		self = self->FindByTID (arg0);
1025 	}
1026 
1027 	return true;
1028 }
1029 
FUNC(LS_ACS_Execute)1030 FUNC(LS_ACS_Execute)
1031 // ACS_Execute (script, map, s_arg1, s_arg2, s_arg3)
1032 {
1033 	level_info_t *info;
1034 
1035 	if ( (arg1 == 0) || !(info = FindLevelByNum (arg1)) )
1036 		return P_StartScript (it, ln, arg0, level.mapname, TeleportSide, arg2, arg3, arg4, 0);
1037 	else
1038 		return P_StartScript (it, ln, arg0, info->mapname, TeleportSide, arg2, arg3, arg4, 0);
1039 }
1040 
FUNC(LS_ACS_ExecuteAlways)1041 FUNC(LS_ACS_ExecuteAlways)
1042 // ACS_ExecuteAlways (script, map, s_arg1, s_arg2, s_arg3)
1043 {
1044 	level_info_t *info;
1045 
1046 	if ( (arg1 == 0) || !(info = FindLevelByNum (arg1)) )
1047 		return P_StartScript (it, ln, arg0, level.mapname, TeleportSide, arg2, arg3, arg4, 1);
1048 	else
1049 		return P_StartScript (it, ln, arg0, info->mapname, TeleportSide, arg2, arg3, arg4, 1);
1050 }
1051 
FUNC(LS_ACS_LockedExecute)1052 FUNC(LS_ACS_LockedExecute)
1053 // ACS_LockedExecute (script, map, s_arg1, s_arg2, lock)
1054 {
1055 	if (arg4 && !P_CheckKeys (it->player, (card_t)arg4, 1))
1056 		return false;
1057 	else
1058 		return LS_ACS_Execute (ln, it, arg0, arg1, arg2, arg3, 0);
1059 }
1060 
FUNC(LS_ACS_Suspend)1061 FUNC(LS_ACS_Suspend)
1062 // ACS_Suspend (script, map)
1063 {
1064 	level_info_t *info;
1065 
1066 	if ( (arg1 == 0) || !(info = FindLevelByNum (arg1)) )
1067 		P_SuspendScript (arg0, level.mapname);
1068 	else
1069 		P_SuspendScript (arg0, info->mapname);
1070 
1071 	return true;
1072 }
1073 
FUNC(LS_ACS_Terminate)1074 FUNC(LS_ACS_Terminate)
1075 // ACS_Terminate (script, map)
1076 {
1077 	level_info_t *info;
1078 
1079 	if ( (arg1 == 0) || !(info = FindLevelByNum (arg1)) )
1080 		P_TerminateScript (arg0, level.mapname);
1081 	else
1082 		P_TerminateScript (arg0, info->mapname);
1083 
1084 	return true;
1085 }
1086 
FUNC(LS_FloorAndCeiling_LowerByValue)1087 FUNC(LS_FloorAndCeiling_LowerByValue)
1088 // FloorAndCeiling_LowerByValue (tag, speed, height)
1089 {
1090 	return EV_DoElevator (ln, DElevator::elevateLower, SPEED(arg1), arg2*FRACUNIT, arg0);
1091 }
1092 
FUNC(LS_FloorAndCeiling_RaiseByValue)1093 FUNC(LS_FloorAndCeiling_RaiseByValue)
1094 // FloorAndCeiling_RaiseByValue (tag, speed, height)
1095 {
1096 	return EV_DoElevator (ln, DElevator::elevateRaise, SPEED(arg1), arg2*FRACUNIT, arg0);
1097 }
1098 
FUNC(LS_FloorAndCeiling_LowerRaise)1099 FUNC(LS_FloorAndCeiling_LowerRaise)
1100 // FloorAndCeiling_LowerRaise (tag, fspeed, cspeed)
1101 {
1102 	return EV_DoCeiling (DCeiling::ceilRaiseToHighest, ln, arg0, SPEED(arg2), 0, 0, 0, 0, 0) ||
1103 		EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0);
1104 }
1105 
FUNC(LS_Elevator_MoveToFloor)1106 FUNC(LS_Elevator_MoveToFloor)
1107 // Elevator_MoveToFloor (tag, speed)
1108 {
1109 	return EV_DoElevator (ln, DElevator::elevateCurrent, SPEED(arg1), 0, arg0);
1110 }
1111 
FUNC(LS_Elevator_RaiseToNearest)1112 FUNC(LS_Elevator_RaiseToNearest)
1113 // Elevator_RaiseToNearest (tag, speed)
1114 {
1115 	return EV_DoElevator (ln, DElevator::elevateUp, SPEED(arg1), 0, arg0);
1116 }
1117 
FUNC(LS_Elevator_LowerToNearest)1118 FUNC(LS_Elevator_LowerToNearest)
1119 // Elevator_LowerToNearest (tag, speed)
1120 {
1121 	return EV_DoElevator (ln, DElevator::elevateDown, SPEED(arg1), 0, arg0);
1122 }
1123 
FUNC(LS_Light_ForceLightning)1124 FUNC(LS_Light_ForceLightning)
1125 // Light_ForceLightning (tag)
1126 {
1127 	return false;
1128 }
1129 
FUNC(LS_Light_RaiseByValue)1130 FUNC(LS_Light_RaiseByValue)
1131 // Light_RaiseByValue (tag, value)
1132 {
1133 	EV_LightChange (arg0, arg1);
1134 	return true;
1135 }
1136 
FUNC(LS_Light_LowerByValue)1137 FUNC(LS_Light_LowerByValue)
1138 // Light_LowerByValue (tag, value)
1139 {
1140 	EV_LightChange (arg0, -arg1);
1141 	return true;
1142 }
1143 
FUNC(LS_Light_ChangeToValue)1144 FUNC(LS_Light_ChangeToValue)
1145 // Light_ChangeToValue (tag, value)
1146 {
1147 	EV_LightTurnOn (arg0, arg1);
1148 	return true;
1149 }
1150 
FUNC(LS_Light_Fade)1151 FUNC(LS_Light_Fade)
1152 // Light_Fade (tag, value, tics);
1153 {
1154 	EV_StartLightFading (arg0, arg1, TICS(arg2));
1155 	return true;
1156 }
1157 
FUNC(LS_Light_Glow)1158 FUNC(LS_Light_Glow)
1159 // Light_Glow (tag, upper, lower, tics)
1160 {
1161 	EV_StartLightGlowing (arg0, arg1, arg2, TICS(arg3));
1162 	return true;
1163 }
1164 
FUNC(LS_Light_Flicker)1165 FUNC(LS_Light_Flicker)
1166 // Light_Flicker (tag, upper, lower)
1167 {
1168 	EV_StartLightFlickering (arg0, arg1, arg2);
1169 	return true;
1170 }
1171 
FUNC(LS_Light_Strobe)1172 FUNC(LS_Light_Strobe)
1173 // Light_Strobe (tag, upper, lower, u-tics, l-tics)
1174 {
1175 	EV_StartLightStrobing (arg0, arg1, arg2, TICS(arg3), TICS(arg4));
1176 	return true;
1177 }
1178 
FUNC(LS_Light_StrobeDoom)1179 FUNC(LS_Light_StrobeDoom)
1180 // Light_StrobeDoom (tag, u-tics, l-tics)
1181 {
1182 	EV_StartLightStrobing (arg0, TICS(arg1), TICS(arg2));
1183 	return true;
1184 }
1185 
FUNC(LS_Light_MinNeighbor)1186 FUNC(LS_Light_MinNeighbor)
1187 // Light_MinNeighbor (tag)
1188 {
1189 	EV_TurnTagLightsOff (arg0);
1190 	return true;
1191 }
1192 
FUNC(LS_Light_MaxNeighbor)1193 FUNC(LS_Light_MaxNeighbor)
1194 // Light_MaxNeighbor (tag)
1195 {
1196 	EV_LightTurnOn (arg0, -1);
1197 	return true;
1198 }
1199 
FUNC(LS_Radius_Quake)1200 FUNC(LS_Radius_Quake)
1201 // Radius_Quake (intensity, duration, damrad, tremrad, tid)
1202 {
1203 	return P_StartQuake (arg4, arg0, arg1, arg2, arg3);
1204 }
1205 
FUNC(LS_UsePuzzleItem)1206 FUNC(LS_UsePuzzleItem)
1207 // UsePuzzleItem (item, script)
1208 {
1209 	return false;
1210 }
1211 
FUNC(LS_Sector_ChangeSound)1212 FUNC(LS_Sector_ChangeSound)
1213 // Sector_ChangeSound (tag, sound)
1214 {
1215 	return false;
1216 }
1217 
1218 struct FThinkerCollection
1219 {
1220 	int RefNum;
1221 	DThinker *Obj;
1222 };
1223 
1224 static TArray<FThinkerCollection> Collection;
1225 
AdjustPusher(int tag,int magnitude,int angle,DPusher::EPusher type)1226 void AdjustPusher (int tag, int magnitude, int angle, DPusher::EPusher type)
1227 {
1228 	// Find pushers already attached to the sector, and change their parameters.
1229 	{
1230 		TThinkerIterator<DPusher> iterator;
1231 		FThinkerCollection collect;
1232 
1233 		while ( (collect.Obj = iterator.Next ()) )
1234 		{
1235 			if ((collect.RefNum = ((DPusher *)collect.Obj)->CheckForSectorMatch (type, tag)) >= 0)
1236 			{
1237 				((DPusher *)collect.Obj)->ChangeValues (magnitude, angle);
1238 				Collection.Push (collect);
1239 			}
1240 		}
1241 	}
1242 
1243 	int numcollected = Collection.Size ();
1244 	int secnum = -1;
1245 
1246 	// Now create pushers for any sectors that don't already have them.
1247 	while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
1248 	{
1249 		int i;
1250 		for (i = 0; i < numcollected; i++)
1251 		{
1252 			if (Collection[i].RefNum == sectors[secnum].tag)
1253 				break;
1254 		}
1255 		if (i == numcollected)
1256 		{
1257 			new DPusher (type, NULL, magnitude, angle, NULL, secnum);
1258 		}
1259 	}
1260 	Collection.Clear ();
1261 }
1262 
FUNC(LS_Sector_SetWind)1263 FUNC(LS_Sector_SetWind)
1264 // Sector_SetWind (tag, amount, angle)
1265 {
1266 	if (ln || arg3)
1267 		return false;
1268 
1269 	AdjustPusher (arg0, arg1, arg2, DPusher::p_wind);
1270 	return true;
1271 }
1272 
FUNC(LS_Sector_SetCurrent)1273 FUNC(LS_Sector_SetCurrent)
1274 // Sector_SetCurrent (tag, amount, angle)
1275 {
1276 	if (ln || arg3)
1277 		return false;
1278 
1279 	AdjustPusher (arg0, arg1, arg2, DPusher::p_current);
1280 	return true;
1281 }
1282 
FUNC(LS_Sector_SetFriction)1283 FUNC(LS_Sector_SetFriction)
1284 // Sector_SetFriction ()
1285 {
1286 	return false;
1287 }
1288 
FUNC(LS_Scroll_Texture_Both)1289 FUNC(LS_Scroll_Texture_Both)
1290 // Scroll_Texture_Both (id, left, right, up, down)
1291 {
1292 	if (arg0 == 0)
1293 		return false;
1294 
1295 	fixed_t dx = (arg1 - arg2) * (FRACUNIT/64);
1296 	fixed_t dy = (arg4 - arg3) * (FRACUNIT/64);
1297 	int sidechoice;
1298 
1299 	if (arg0 < 0)
1300 	{
1301 		sidechoice = 1;
1302 		arg0 = -arg0;
1303 	}
1304 	else
1305 	{
1306 		sidechoice = 0;
1307 	}
1308 
1309 	if (dx == 0 && dy == 0)
1310 	{
1311 		// Special case: Remove the scroller, because the deltas are both 0.
1312 		TThinkerIterator<DScroller> iterator;
1313 		DScroller *scroller;
1314 
1315 		while ( (scroller = iterator.Next ()) )
1316 		{
1317 			int wallnum = scroller->GetWallNum ();
1318 
1319 			if (wallnum >= 0 && lines[sides[wallnum].linenum].id == arg0 &&
1320 				lines[sides[wallnum].linenum].sidenum[sidechoice] == wallnum)
1321 			{
1322 				scroller->Destroy ();
1323 			}
1324 		}
1325 	}
1326 	else
1327 	{
1328 		// Find scrollers already attached to the matching walls, and change
1329 		// their rates.
1330 		{
1331 			TThinkerIterator<DScroller> iterator;
1332 			FThinkerCollection collect;
1333 
1334 			while ( (collect.Obj = iterator.Next ()) )
1335 			{
1336 				if ((collect.RefNum = ((DScroller *)collect.Obj)->GetWallNum ()) != -1 &&
1337 					lines[sides[collect.RefNum].linenum].id == arg0 &&
1338 					lines[sides[collect.RefNum].linenum].sidenum[sidechoice] == collect.RefNum)
1339 				{
1340 					((DScroller *)collect.Obj)->SetRate (dx, dy);
1341 					Collection.Push (collect);
1342 				}
1343 			}
1344 		}
1345 
1346 		int numcollected = Collection.Size ();
1347 		int linenum = -1;
1348 
1349 		// Now create scrollers for any walls that don't already have them.
1350 		while ((linenum = P_FindLineFromID (arg0, linenum)) >= 0)
1351 		{
1352 			int i;
1353 			for (i = 0; i < numcollected; i++)
1354 			{
1355 				if (Collection[i].RefNum == lines[linenum].sidenum[sidechoice])
1356 					break;
1357 			}
1358 			if (i == numcollected)
1359 			{
1360 				new DScroller (DScroller::sc_side, dx, dy, -1, lines[linenum].sidenum[sidechoice], 0);
1361 			}
1362 		}
1363 		Collection.Clear ();
1364 	}
1365 
1366 	return true;
1367 }
1368 
FUNC(LS_Scroll_Floor)1369 FUNC(LS_Scroll_Floor)
1370 {
1371 	return false;
1372 }
1373 
FUNC(LS_Scroll_Ceiling)1374 FUNC(LS_Scroll_Ceiling)
1375 {
1376 	return false;
1377 }
1378 
FUNC(LS_PointPush_SetForce)1379 FUNC(LS_PointPush_SetForce)
1380 // PointPush_SetForce ()
1381 {
1382 	return false;
1383 }
1384 
FUNC(LS_Sector_SetDamage)1385 FUNC(LS_Sector_SetDamage)
1386 // Sector_SetDamage (tag, amount, mod)
1387 {
1388 	int secnum = -1;
1389 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0) {
1390 		sectors[secnum].damage = arg1;
1391 		sectors[secnum].mod = arg2;
1392 	}
1393 	return true;
1394 }
1395 
FUNC(LS_Sector_SetGravity)1396 FUNC(LS_Sector_SetGravity)
1397 // Sector_SetGravity (tag, intpart, fracpart)
1398 {
1399 	int secnum = -1;
1400 	float gravity;
1401 
1402 	if (arg2 > 99)
1403 		arg2 = 99;
1404 	gravity = (float)arg1 + (float)arg2 * 0.01f;
1405 
1406 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1407 		sectors[secnum].gravity = gravity;
1408 
1409 	return true;
1410 }
1411 
FUNC(LS_Sector_SetColor)1412 FUNC(LS_Sector_SetColor)
1413 // Sector_SetColor (tag, r, g, b)
1414 {
1415 	int secnum = -1;
1416 
1417 	if (clientside)
1418 	{
1419         while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1420         {
1421             sectors[secnum].floorcolormap = GetSpecialLights (arg1, arg2, arg3,
1422                 RPART(sectors[secnum].floorcolormap->fade),
1423                 GPART(sectors[secnum].floorcolormap->fade),
1424                 BPART(sectors[secnum].floorcolormap->fade));
1425             sectors[secnum].ceilingcolormap = GetSpecialLights (arg1, arg2, arg3,
1426                 RPART(sectors[secnum].ceilingcolormap->fade),
1427                 GPART(sectors[secnum].ceilingcolormap->fade),
1428                 BPART(sectors[secnum].ceilingcolormap->fade));
1429         }
1430 	}
1431 	return true;
1432 }
1433 
FUNC(LS_Sector_SetFade)1434 FUNC(LS_Sector_SetFade)
1435 // Sector_SetFade (tag, r, g, b)
1436 {
1437 	int secnum = -1;
1438 
1439 	if (clientside)
1440 	{
1441         while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1442         {
1443             sectors[secnum].floorcolormap = GetSpecialLights (
1444                 RPART(sectors[secnum].floorcolormap->color),
1445                 GPART(sectors[secnum].floorcolormap->color),
1446                 BPART(sectors[secnum].floorcolormap->color),
1447                 arg1, arg2, arg3);
1448             sectors[secnum].ceilingcolormap = GetSpecialLights (
1449                 RPART(sectors[secnum].ceilingcolormap->color),
1450                 GPART(sectors[secnum].ceilingcolormap->color),
1451                 BPART(sectors[secnum].ceilingcolormap->color),
1452                 arg1, arg2, arg3);
1453         }
1454 	}
1455 	return true;
1456 }
1457 
FUNC(LS_Sector_SetCeilingPanning)1458 FUNC(LS_Sector_SetCeilingPanning)
1459 // Sector_SetCeilingPanning (tag, x-int, x-frac, y-int, y-frac)
1460 {
1461 	int secnum = -1;
1462 	fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
1463 	fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
1464 
1465 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1466 	{
1467 		sectors[secnum].ceiling_xoffs = xofs;
1468 		sectors[secnum].ceiling_yoffs = yofs;
1469 	}
1470 	return true;
1471 }
1472 
FUNC(LS_Sector_SetFloorPanning)1473 FUNC(LS_Sector_SetFloorPanning)
1474 // Sector_SetCeilingPanning (tag, x-int, x-frac, y-int, y-frac)
1475 {
1476 	int secnum = -1;
1477 	fixed_t xofs = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
1478 	fixed_t yofs = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
1479 
1480 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1481 	{
1482 		sectors[secnum].floor_xoffs = xofs;
1483 		sectors[secnum].floor_yoffs = yofs;
1484 	}
1485 	return true;
1486 }
1487 
FUNC(LS_Sector_SetCeilingScale)1488 FUNC(LS_Sector_SetCeilingScale)
1489 // Sector_SetCeilingScale (tag, x-int, x-frac, y-int, y-frac)
1490 {
1491 	int secnum = -1;
1492 	fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
1493 	fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
1494 
1495 	if (xscale)
1496 		xscale = FixedDiv (FRACUNIT, xscale);
1497 	if (yscale)
1498 		yscale = FixedDiv (FRACUNIT, yscale);
1499 
1500 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1501 	{
1502 		if (xscale)
1503 			sectors[secnum].ceiling_xscale = xscale;
1504 		if (yscale)
1505 			sectors[secnum].ceiling_yscale = yscale;
1506 	}
1507 	return true;
1508 }
1509 
FUNC(LS_Sector_SetFloorScale)1510 FUNC(LS_Sector_SetFloorScale)
1511 // Sector_SetFloorScale (tag, x-int, x-frac, y-int, y-frac)
1512 {
1513 	int secnum = -1;
1514 	fixed_t xscale = arg1 * FRACUNIT + arg2 * (FRACUNIT/100);
1515 	fixed_t yscale = arg3 * FRACUNIT + arg4 * (FRACUNIT/100);
1516 
1517 	if (xscale)
1518 		xscale = FixedDiv (FRACUNIT, xscale);
1519 	if (yscale)
1520 		yscale = FixedDiv (FRACUNIT, yscale);
1521 
1522 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1523 	{
1524 		if (xscale)
1525 			sectors[secnum].floor_xscale = xscale;
1526 		if (yscale)
1527 			sectors[secnum].floor_yscale = yscale;
1528 	}
1529 	return true;
1530 }
1531 
FUNC(LS_Sector_SetRotation)1532 FUNC(LS_Sector_SetRotation)
1533 // Sector_SetRotation (tag, floor-angle, ceiling-angle)
1534 {
1535 	int secnum = -1;
1536 	angle_t ceiling = arg2 * ANG(1);
1537 	angle_t floor = arg1 * ANG(1);
1538 
1539 	while ((secnum = P_FindSectorFromTag (arg0, secnum)) >= 0)
1540 	{
1541 		sectors[secnum].floor_angle = floor;
1542 		sectors[secnum].ceiling_angle = ceiling;
1543 	}
1544 	return true;
1545 }
1546 
FUNC(LS_Line_AlignCeiling)1547 FUNC(LS_Line_AlignCeiling)
1548 // Line_AlignCeiling (lineid, side)
1549 {
1550 	int line = P_FindLineFromID (arg0, -1);
1551 	BOOL ret = 0;
1552 
1553 	if (line < 0)
1554 		I_Error ("Sector_AlignCeiling: Lineid %d is undefined", arg0);
1555 	do
1556 	{
1557 		ret |= R_AlignFlat (line, !!arg1, 1);
1558 	} while ( (line = P_FindLineFromID (arg0, line)) >= 0);
1559 	return ret;
1560 }
1561 
FUNC(LS_Line_AlignFloor)1562 FUNC(LS_Line_AlignFloor)
1563 // Line_AlignFloor (lineid, side)
1564 {
1565 	int line = P_FindLineFromID (arg0, -1);
1566 	BOOL ret = 0;
1567 
1568 	if (line < 0)
1569 		I_Error ("Sector_AlignFloor: Lineid %d is undefined", arg0);
1570 	do
1571 	{
1572 		ret |= R_AlignFlat (line, !!arg1, 0);
1573 	} while ( (line = P_FindLineFromID (arg0, line)) >= 0);
1574 	return ret;
1575 }
1576 
FUNC(LS_ChangeCamera)1577 FUNC(LS_ChangeCamera)
1578 // ChangeCamera (tid, who, revert?)
1579 {
1580 	AActor *camera = AActor::FindGoal (NULL, arg0, MT_CAMERA);
1581 
1582 	if (!it || !it->player || arg1)
1583 	{
1584 		for (Players::iterator itr = players.begin();itr != players.end();++itr)
1585 		{
1586 			if (!(itr->ingame()))
1587 				continue;
1588 
1589 			if (camera)
1590 			{
1591 				itr->camera = camera->ptr();
1592 				if (arg2)
1593 					itr->cheats |= CF_REVERTPLEASE;
1594 			}
1595 			else
1596 			{
1597 				itr->camera = itr->mo;
1598 				itr->cheats &= ~CF_REVERTPLEASE;
1599 			}
1600 		}
1601 	}
1602 	else
1603 	{
1604 		if (camera) {
1605 			it->player->camera = camera->ptr();
1606 			if (arg2)
1607 				it->player->cheats |= CF_REVERTPLEASE;
1608 		} else {
1609 			it->player->camera = it->ptr();
1610 			it->player->cheats &= ~CF_REVERTPLEASE;
1611 		}
1612 	}
1613 
1614 	return true;
1615 }
1616 
FUNC(LS_SetPlayerProperty)1617 FUNC(LS_SetPlayerProperty)
1618 // SetPlayerProperty (who, set, which)
1619 {
1620 #define PROP_FROZEN		0
1621 #define PROP_NOTARGET	1
1622 
1623 	if(!it) return false;
1624 
1625 	int mask = 0;
1626 
1627 	if (!it->player && !arg0)
1628 		return false;
1629 
1630 	switch (arg2)
1631 	{
1632 		case PROP_FROZEN:
1633 			mask = CF_FROZEN;
1634 			break;
1635 		case PROP_NOTARGET:
1636 			mask = CF_NOTARGET;
1637 			break;
1638 	}
1639 
1640 	if (arg1 == 0)
1641 	{
1642 		if (arg1)
1643 			it->player->cheats |= mask;
1644 		else
1645 			it->player->cheats &= ~mask;
1646 	}
1647 	else
1648 	{
1649 		for (Players::iterator itr = players.begin();itr != players.end();++itr)
1650 		{
1651 			if (!(itr->ingame()))
1652 				continue;
1653 
1654 			if (arg1)
1655 				itr->cheats |= mask;
1656 			else
1657 				itr->cheats &= ~mask;
1658 		}
1659 	}
1660 
1661 	return !!mask;
1662 }
1663 
FUNC(LS_TranslucentLine)1664 FUNC(LS_TranslucentLine)
1665 // TranslucentLine (id, amount)
1666 {
1667 	if (ln)
1668 		return false;
1669 
1670 	int linenum = -1;
1671 	while ((linenum = P_FindLineFromID (arg0, linenum)) >= 0)
1672 	{
1673 		lines[linenum].lucency = arg1 & 255;
1674 	}
1675 
1676 	return true;
1677 }
1678 
1679 lnSpecFunc LineSpecials[256] =
1680 {
1681 	LS_NOP,
1682 	LS_NOP,		// Polyobj_StartLine,
1683 	LS_Polyobj_RotateLeft,
1684 	LS_Polyobj_RotateRight,
1685 	LS_Polyobj_Move,
1686 	LS_NOP,		// Polyobj_ExplicitLine
1687 	LS_Polyobj_MoveTimes8,
1688 	LS_Polyobj_DoorSwing,
1689 	LS_Polyobj_DoorSlide,
1690 	LS_NOP,		// 9
1691 	LS_Door_Close,
1692 	LS_Door_Open,
1693 	LS_Door_Raise,
1694 	LS_Door_LockedRaise,
1695 	LS_NOP,		// 14
1696 	LS_NOP,		// 15
1697 	LS_NOP,		// 16
1698 	LS_NOP,		// 17
1699 	LS_NOP,		// 18
1700 	LS_NOP,		// 19
1701 	LS_Floor_LowerByValue,
1702 	LS_Floor_LowerToLowest,
1703 	LS_Floor_LowerToNearest,
1704 	LS_Floor_RaiseByValue,
1705 	LS_Floor_RaiseToHighest,
1706 	LS_Floor_RaiseToNearest,
1707 	LS_Stairs_BuildDown,
1708 	LS_Stairs_BuildUp,
1709 	LS_Floor_RaiseAndCrush,
1710 	LS_Pillar_Build,
1711 	LS_Pillar_Open,
1712 	LS_Stairs_BuildDownSync,
1713 	LS_Stairs_BuildUpSync,
1714 	LS_NOP,		// 33
1715 	LS_NOP,		// 34
1716 	LS_Floor_RaiseByValueTimes8,
1717 	LS_Floor_LowerByValueTimes8,
1718 	LS_NOP,		// 37
1719 	LS_NOP,		// 38
1720 	LS_NOP,		// 39
1721 	LS_Ceiling_LowerByValue,
1722 	LS_Ceiling_RaiseByValue,
1723 	LS_Ceiling_CrushAndRaise,
1724 	LS_Ceiling_LowerAndCrush,
1725 	LS_Ceiling_CrushStop,
1726 	LS_Ceiling_CrushRaiseAndStay,
1727 	LS_Floor_CrushStop,
1728 	LS_NOP,		// 47
1729 	LS_NOP,		// 48
1730 	LS_NOP,		// 49
1731 	LS_NOP,		// 50
1732 	LS_NOP,		// 51
1733 	LS_NOP,		// 52
1734 	LS_NOP,		// 53
1735 	LS_NOP,		// 54
1736 	LS_NOP,		// 55
1737 	LS_NOP,		// 56
1738 	LS_NOP,		// 57
1739 	LS_NOP,		// 58
1740 	LS_NOP,		// 59
1741 	LS_Plat_PerpetualRaise,
1742 	LS_Plat_Stop,
1743 	LS_Plat_DownWaitUpStay,
1744 	LS_Plat_DownByValue,
1745 	LS_Plat_UpWaitDownStay,
1746 	LS_Plat_UpByValue,
1747 	LS_Floor_LowerInstant,
1748 	LS_Floor_RaiseInstant,
1749 	LS_Floor_MoveToValueTimes8,
1750 	LS_Ceiling_MoveToValueTimes8,
1751 	LS_Teleport,
1752 	LS_Teleport_NoFog,
1753 	LS_ThrustThing,
1754 	LS_DamageThing,
1755 	LS_Teleport_NewMap,
1756 	LS_Teleport_EndGame,
1757 	LS_NOP,		// 76
1758 	LS_NOP,		// 77
1759 	LS_NOP,		// 78
1760 	LS_NOP,		// 79
1761 	LS_ACS_Execute,
1762 	LS_ACS_Suspend,
1763 	LS_ACS_Terminate,
1764 	LS_ACS_LockedExecute,
1765 	LS_NOP,		// 84
1766 	LS_NOP,		// 85
1767 	LS_NOP,		// 86
1768 	LS_NOP,		// 87
1769 	LS_NOP,		// 88
1770 	LS_NOP,		// 89
1771 	LS_Polyobj_OR_RotateLeft,
1772 	LS_Polyobj_OR_RotateRight,
1773 	LS_Polyobj_OR_Move,
1774 	LS_Polyobj_OR_MoveTimes8,
1775 	LS_NOP,
1776 	LS_FloorAndCeiling_LowerByValue,
1777 	LS_FloorAndCeiling_RaiseByValue,
1778 	LS_NOP,		// 97
1779 	LS_NOP,		// 98
1780 	LS_NOP,		// 99
1781 	LS_NOP,		// Scroll_Texture_Left
1782 	LS_NOP,		// Scroll_Texture_Right
1783 	LS_NOP,		// Scroll_Texture_Up
1784 	LS_NOP,		// Scroll_Texture_Down
1785 	LS_NOP,		// 104
1786 	LS_NOP,		// 105
1787 	LS_NOP,		// 106
1788 	LS_NOP,		// 107
1789 	LS_NOP,		// 108
1790 	LS_Light_ForceLightning,
1791 	LS_Light_RaiseByValue,
1792 	LS_Light_LowerByValue,
1793 	LS_Light_ChangeToValue,
1794 	LS_Light_Fade,
1795 	LS_Light_Glow,
1796 	LS_Light_Flicker,
1797 	LS_Light_Strobe,
1798 	LS_NOP,		// 117
1799 	LS_NOP,		// 118
1800 	LS_NOP,		// 119
1801 	LS_Radius_Quake,
1802 	LS_NOP,		// Line_SetIdentification
1803 	LS_NOP,		// 122
1804 	LS_NOP,		// 123
1805 	LS_NOP,		// 124
1806 	LS_NOP,		// 125
1807 	LS_NOP,		// 126
1808 	LS_NOP,		// 127
1809 	LS_ThrustThingZ,		// 128
1810 	LS_UsePuzzleItem,
1811 	LS_Thing_Activate,
1812 	LS_Thing_Deactivate,
1813 	LS_Thing_Remove,
1814 	LS_Thing_Destroy,
1815 	LS_Thing_Projectile,
1816 	LS_Thing_Spawn,
1817 	LS_Thing_ProjectileGravity,
1818 	LS_Thing_SpawnNoFog,
1819 	LS_Floor_Waggle,
1820 	LS_NOP,		// 139
1821 	LS_Sector_ChangeSound,
1822 	LS_NOP,		// 141
1823 	LS_NOP,		// 142
1824 	LS_NOP,		// 143
1825 	LS_NOP,		// 144
1826 	LS_NOP,		// 145
1827 	LS_NOP,		// 146
1828 	LS_NOP,		// 147
1829 	LS_NOP,		// 148
1830 	LS_NOP,		// 149
1831 	LS_NOP,		// 150
1832 	LS_NOP,		// 151
1833 	LS_NOP,		// 152
1834 	LS_NOP,		// 153
1835 	LS_NOP,		// 154
1836 	LS_NOP,		// 155
1837 	LS_NOP,		// 156
1838 	LS_NOP,		// 157
1839 	LS_NOP,		// 158
1840 	LS_NOP,		// 159
1841 	LS_NOP,		// 160
1842 	LS_NOP,		// 161
1843 	LS_NOP,		// 162
1844 	LS_NOP,		// 163
1845 	LS_NOP,		// 164
1846 	LS_NOP,		// 165
1847 	LS_NOP,		// 166
1848 	LS_NOP,		// 167
1849 	LS_NOP,		// 168
1850 	LS_NOP,		// 169
1851 	LS_NOP,		// 170
1852 	LS_NOP,		// 171
1853 	LS_NOP,		// 172
1854 	LS_NOP,		// 173
1855 	LS_NOP,		// 174
1856 	LS_NOP,		// 175
1857 	LS_NOP,		// 176
1858 	LS_NOP,		// 177
1859 	LS_NOP,		// 178
1860 	LS_NOP,		// 179
1861 	LS_NOP,		// 180
1862 	LS_NOP,		// 181
1863 	LS_NOP,		// 182
1864 	LS_Line_AlignCeiling,
1865 	LS_Line_AlignFloor,
1866 	LS_Sector_SetRotation,
1867 	LS_Sector_SetCeilingPanning,
1868 	LS_Sector_SetFloorPanning,
1869 	LS_Sector_SetCeilingScale,
1870 	LS_Sector_SetFloorScale,
1871 	LS_NOP,		// Static_Init
1872 	LS_SetPlayerProperty,
1873 	LS_Ceiling_LowerToHighestFloor,
1874 	LS_Ceiling_LowerInstant,
1875 	LS_Ceiling_RaiseInstant,
1876 	LS_Ceiling_CrushRaiseAndStayA,
1877 	LS_Ceiling_CrushAndRaiseA,
1878 	LS_Ceiling_CrushAndRaiseSilentA,
1879 	LS_Ceiling_RaiseByValueTimes8,
1880 	LS_Ceiling_LowerByValueTimes8,
1881 	LS_Generic_Floor,
1882 	LS_Generic_Ceiling,
1883 	LS_Generic_Door,
1884 	LS_Generic_Lift,
1885 	LS_Generic_Stairs,
1886 	LS_Generic_Crusher,
1887 	LS_Plat_DownWaitUpStayLip,
1888 	LS_Plat_PerpetualRaiseLip,
1889 	LS_TranslucentLine,
1890 	LS_NOP,		// Transfer_Heights
1891 	LS_NOP,		// Transfer_FloorLight
1892 	LS_NOP,		// Transfer_CeilingLight
1893 	LS_Sector_SetColor,
1894 	LS_Sector_SetFade,
1895 	LS_Sector_SetDamage,
1896 	LS_Teleport_Line,
1897 	LS_Sector_SetGravity,
1898 	LS_Stairs_BuildUpDoom,
1899 	LS_Sector_SetWind,
1900 	LS_Sector_SetFriction,
1901 	LS_Sector_SetCurrent,
1902 	LS_Scroll_Texture_Both,
1903 	LS_NOP,		// Scroll_Texture_Model
1904 	LS_Scroll_Floor,
1905 	LS_Scroll_Ceiling,
1906 	LS_NOP,		// Scroll_Texture_Offsets
1907 	LS_ACS_ExecuteAlways,
1908 	LS_PointPush_SetForce,
1909 	LS_Plat_RaiseAndStayTx0,
1910 	LS_Thing_SetGoal,
1911 	LS_Plat_UpByValueStayTx,
1912 	LS_Plat_ToggleCeiling,
1913 	LS_Light_StrobeDoom,
1914 	LS_Light_MinNeighbor,
1915 	LS_Light_MaxNeighbor,
1916 	LS_Floor_TransferTrigger,
1917 	LS_Floor_TransferNumeric,
1918 	LS_ChangeCamera,
1919 	LS_Floor_RaiseToLowestCeiling,
1920 	LS_Floor_RaiseByValueTxTy,
1921 	LS_Floor_RaiseByTexture,
1922 	LS_Floor_LowerToLowestTxTy,
1923 	LS_Floor_LowerToHighest,
1924 	LS_Exit_Normal,
1925 	LS_Exit_Secret,
1926 	LS_Elevator_RaiseToNearest,
1927 	LS_Elevator_MoveToFloor,
1928 	LS_Elevator_LowerToNearest,
1929 	LS_HealThing,
1930 	LS_Door_CloseWaitOpen,
1931 	LS_Floor_Donut,
1932 	LS_FloorAndCeiling_LowerRaise,
1933 	LS_Ceiling_RaiseToNearest,
1934 	LS_Ceiling_LowerToLowest,
1935 	LS_Ceiling_LowerToFloor,
1936 	LS_Ceiling_CrushRaiseAndStaySilA
1937 };
1938 
1939 
1940 EXTERN_CVAR (sv_fraglimit)
EXTERN_CVAR(sv_allowexit)1941 EXTERN_CVAR (sv_allowexit)
1942 EXTERN_CVAR (sv_fragexitswitch)
1943 
1944 BOOL CheckIfExitIsGood (AActor *self)
1945 {
1946 	if (self == NULL)
1947 		return false;
1948 
1949 	// [Toke - dmflags] Old location of DF_NO_EXIT
1950 
1951 	if (sv_gametype != GM_COOP && self)
1952 	{
1953         if (!sv_allowexit)
1954         {
1955 			if (sv_fragexitswitch && serverside)
1956 				P_DamageMobj(self, NULL, NULL, 10000, MOD_SUICIDE);
1957 
1958 			return false;
1959 		}
1960 	}
1961 
1962 	if (self->player)
1963 		Printf (PRINT_HIGH, "%s exited the level.\n", self->player->userinfo.netname.c_str());
1964 
1965 	return true;
1966 }
1967 
1968 VERSION_CONTROL (p_lnspec_cpp, "$Id: p_lnspec.cpp 4542 2014-02-09 17:39:42Z dr_sean $")
1969 
1970