1 // SONIC ROBO BLAST 2
2 //-----------------------------------------------------------------------------
3 // Copyright (C) 1993-1996 by id Software, Inc.
4 // Copyright (C) 1998-2000 by DooM Legacy Team.
5 // Copyright (C) 1999-2020 by Sonic Team Junior.
6 //
7 // This program is free software distributed under the
8 // terms of the GNU General Public License, version 2.
9 // See the 'LICENSE' file for more details.
10 //-----------------------------------------------------------------------------
11 /// \file  p_spec.h
12 /// \brief Implements special effects:
13 ///        Texture animation, height or lighting changes
14 ///        according to adjacent sectors, respective
15 ///        utility functions, etc.
16 
17 #ifndef __P_SPEC__
18 #define __P_SPEC__
19 
20 extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint
21 extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
22 extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
23 
24 // GETSECSPECIAL (specialval, section)
25 //
26 // Pulls out the special # from a particular section.
27 //
28 #define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15)
29 
30 // This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
31 #define MAXFLATSIZE (2048<<FRACBITS)
32 
33 // at game start
34 void P_InitPicAnims(void);
35 
36 // at map load (sectors)
37 void P_SetupLevelFlatAnims(void);
38 
39 // at map load
40 void P_InitSpecials(void);
41 void P_SpawnSpecials(boolean fromnetsave);
42 
43 // every tic
44 void P_UpdateSpecials(void);
45 sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number);
46 void P_PlayerInSpecialSector(player_t *player);
47 void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
48 
49 fixed_t P_FindLowestFloorSurrounding(sector_t *sec);
50 fixed_t P_FindHighestFloorSurrounding(sector_t *sec);
51 
52 fixed_t P_FindNextHighestFloor(sector_t *sec, fixed_t currentheight);
53 fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
54 
55 fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
56 fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
57 
58 INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
59 
60 void P_SetupSignExit(player_t *player);
61 boolean P_IsFlagAtBase(mobjtype_t flag);
62 
63 void P_SwitchWeather(INT32 weathernum);
64 
65 boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
66 void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
67 void P_RunNightserizeExecutors(mobj_t *actor);
68 void P_RunDeNightserizeExecutors(mobj_t *actor);
69 void P_RunNightsLapExecutors(mobj_t *actor);
70 void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres);
71 
72 UINT16 P_GetFFloorID(ffloor_t *fflr);
73 ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id);
74 
75 //
76 // P_LIGHTS
77 //
78 /** Fire flicker action structure.
79   */
80 typedef struct
81 {
82 	thinker_t thinker; ///< The thinker in use for the effect.
83 	sector_t *sector;  ///< The sector where action is taking place.
84 	INT32 count;
85 	INT32 resetcount;
86 	INT32 maxlight;    ///< The brightest light level to use.
87 	INT32 minlight;    ///< The darkest light level to use.
88 } fireflicker_t;
89 
90 typedef struct
91 {
92 	thinker_t thinker;
93 	sector_t *sector;
94 	INT32 maxlight;
95 	INT32 minlight;
96 } lightflash_t;
97 
98 /** Laser block thinker.
99   */
100 typedef struct
101 {
102 	thinker_t thinker; ///< Thinker structure for laser.
103 	INT16 tag;
104 	line_t *sourceline;
105 	UINT8 nobosses;
106 } laserthink_t;
107 
108 /** Strobe light action structure..
109   */
110 typedef struct
111 {
112 	thinker_t thinker; ///< The thinker in use for the effect.
113 	sector_t *sector;  ///< The sector where the action is taking place.
114 	INT32 count;
115 	INT32 minlight;    ///< The minimum light level to use.
116 	INT32 maxlight;    ///< The maximum light level to use.
117 	INT32 darktime;    ///< How INT32 to use minlight.
118 	INT32 brighttime;  ///< How INT32 to use maxlight.
119 } strobe_t;
120 
121 typedef struct
122 {
123 	thinker_t thinker;
124 	sector_t *sector;
125 	INT32 minlight;
126 	INT32 maxlight;
127 	INT32 direction;
128 	INT32 speed;
129 } glow_t;
130 
131 /** Thinker struct for fading lights.
132   */
133 typedef struct
134 {
135 	thinker_t thinker;		///< Thinker in use for the effect.
136 	sector_t *sector;		///< Sector where action is taking place.
137 	INT16 sourcelevel;		///< Light level we're fading from.
138 	INT16 destlevel;		///< Light level we're fading to.
139 
140 	fixed_t fixedcurlevel;	///< Fixed point for current light level.
141 	fixed_t fixedpertic;	///< Fixed point for increment per tic.
142 	// The reason for those two above to be fixed point is to deal with decimal values that would otherwise get trimmed away.
143 	INT32 timer;			///< Internal timer.
144 } lightlevel_t;
145 
146 #define GLOWSPEED 8
147 #define STROBEBRIGHT 5
148 #define FASTDARK 15
149 #define SLOWDARK 35
150 
151 void P_RemoveLighting(sector_t *sector);
152 
153 void T_FireFlicker(fireflicker_t *flick);
154 fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxsector, INT32 length);
155 void T_LightningFlash(lightflash_t *flash);
156 void T_StrobeFlash(strobe_t *flash);
157 
158 void P_SpawnLightningFlash(sector_t *sector);
159 strobe_t * P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, INT32 darktime, INT32 brighttime, boolean inSync);
160 
161 void T_Glow(glow_t *g);
162 glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, INT32 length);
163 
164 void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased);
165 void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, boolean force);
166 void T_LightFade(lightlevel_t *ll);
167 
168 typedef enum
169 {
170 	floor_special,
171 	ceiling_special,
172 	lighting_special,
173 } special_e;
174 
175 //
176 // P_CEILNG
177 //
178 typedef enum
179 {
180 	raiseToHighest,
181 	lowerToLowest,
182 	raiseToLowest,
183 	lowerToLowestFast,
184 
185 	instantRaise, // instant-move for ceilings
186 
187 	lowerAndCrush,
188 	crushAndRaise,
189 	fastCrushAndRaise,
190 	crushCeilOnce,
191 	crushBothOnce,
192 
193 	moveCeilingByFrontSector,
194 	instantMoveCeilingByFrontSector,
195 
196 	moveCeilingByFrontTexture,
197 
198 	bounceCeiling,
199 	bounceCeilingCrush,
200 } ceiling_e;
201 
202 /** Ceiling movement structure.
203   */
204 typedef struct
205 {
206 	thinker_t thinker;    ///< Thinker for the type of movement.
207 	ceiling_e type;       ///< Type of movement.
208 	sector_t *sector;     ///< Sector where the action is taking place.
209 	fixed_t bottomheight; ///< The lowest height to move to.
210 	fixed_t topheight;    ///< The highest height to move to.
211 	fixed_t speed;        ///< Ceiling speed.
212 	fixed_t oldspeed;
213 	fixed_t delay;
214 	fixed_t delaytimer;
215 	UINT8 crush;           ///< Whether to crush things or not.
216 
217 	INT32 texture;        ///< The number of a flat to use when done.
218 	INT32 direction;      ///< 1 = up, 0 = waiting, -1 = down.
219 
220 	// ID
221 	INT32 tag;
222 	INT32 olddirection;
223 	fixed_t origspeed;    ///< The original, "real" speed.
224 	INT32 sourceline;     ///< Index of the source linedef
225 } ceiling_t;
226 
227 #define CEILSPEED (FRACUNIT)
228 
229 INT32 EV_DoCeiling(line_t *line, ceiling_e type);
230 
231 INT32 EV_DoCrush(line_t *line, ceiling_e type);
232 void T_CrushCeiling(ceiling_t *ceiling);
233 
234 void T_MoveCeiling(ceiling_t *ceiling);
235 
236 //
237 // P_FLOOR
238 //
239 typedef enum
240 {
241 	// lower floor to lowest surrounding floor
242 	lowerFloorToLowest,
243 
244 	// raise floor to next highest surrounding floor
245 	raiseFloorToNearestFast,
246 
247 	// move the floor down instantly
248 	instantLower,
249 
250 	moveFloorByFrontSector,
251 	instantMoveFloorByFrontSector,
252 
253 	moveFloorByFrontTexture,
254 
255 	bounceFloor,
256 	bounceFloorCrush,
257 
258 	crushFloorOnce,
259 } floor_e;
260 
261 typedef enum
262 {
263 	elevateUp,
264 	elevateDown,
265 	elevateCurrent,
266 	elevateContinuous,
267 	elevateBounce,
268 	elevateHighest,
269 	bridgeFall,
270 } elevator_e;
271 
272 typedef struct
273 {
274 	thinker_t thinker;
275 	floor_e type;
276 	UINT8 crush;
277 	sector_t *sector;
278 	INT32 direction;
279 	INT32 texture;
280 	fixed_t floordestheight;
281 	fixed_t speed;
282 	fixed_t origspeed;
283 	fixed_t delay;
284 	fixed_t delaytimer;
285 } floormove_t;
286 
287 typedef struct
288 {
289 	thinker_t thinker;
290 	elevator_e type;
291 	sector_t *sector;
292 	sector_t *actionsector; // The sector the rover action is taking place in.
293 	INT32 direction;
294 	fixed_t floordestheight;
295 	fixed_t ceilingdestheight;
296 	fixed_t speed;
297 	fixed_t origspeed;
298 	fixed_t low;
299 	fixed_t high;
300 	fixed_t distance;
301 	fixed_t delay;
302 	fixed_t delaytimer;
303 	fixed_t floorwasheight; // Height the floor WAS at
304 	fixed_t ceilingwasheight; // Height the ceiling WAS at
305 	line_t *sourceline;
306 } elevator_t;
307 
308 typedef enum
309 {
310 	CF_RETURN   = 1,    // Return after crumbling
311 	CF_FLOATBOB = 1<<1, // Float on water
312 	CF_REVERSE  = 1<<2, // Reverse gravity
313 } crumbleflag_t;
314 
315 typedef struct
316 {
317 	thinker_t thinker;
318 	line_t *sourceline;
319 	sector_t *sector;
320 	sector_t *actionsector; // The sector the rover action is taking place in.
321 	player_t *player; // Player who initiated the thinker (used for airbob)
322 	INT32 direction;
323 	INT32 origalpha;
324 	INT32 timer;
325 	fixed_t speed;
326 	fixed_t floorwasheight; // Height the floor WAS at
327 	fixed_t ceilingwasheight; // Height the ceiling WAS at
328 	UINT8 flags;
329 } crumble_t;
330 
331 typedef struct
332 {
333 	thinker_t thinker;
334 	line_t *sourceline; // Source line of the thinker
335 } noenemies_t;
336 
337 typedef struct
338 {
339 	thinker_t thinker;
340 	sector_t *sector;
341 	fixed_t speed;
342 	INT32 direction;
343 	fixed_t floorstartheight;
344 	fixed_t ceilingstartheight;
345 	fixed_t destheight;
346 } continuousfall_t;
347 
348 typedef struct
349 {
350 	thinker_t thinker;
351 	line_t *sourceline;
352 	sector_t *sector;
353 	fixed_t speed;
354 	fixed_t distance;
355 	fixed_t floorwasheight;
356 	fixed_t ceilingwasheight;
357 	boolean low;
358 } bouncecheese_t;
359 
360 typedef struct
361 {
362 	thinker_t thinker;
363 	sector_t *sector;
364 	fixed_t speed;
365 	INT32 direction;
366 	fixed_t floorstartheight;
367 	fixed_t ceilingstartheight;
368 	INT16 tag;
369 } mariothink_t;
370 
371 typedef struct
372 {
373 	thinker_t thinker;
374 	line_t *sourceline;
375 	sector_t *sector;
376 } mariocheck_t;
377 
378 typedef struct
379 {
380 	thinker_t thinker;
381 	line_t *sourceline;
382 	sector_t *sector;
383 	fixed_t crushspeed;
384 	fixed_t retractspeed;
385 	INT32 direction;
386 	fixed_t floorstartheight;
387 	fixed_t ceilingstartheight;
388 	INT32 delay;
389 	INT16 tag;
390 	UINT16 sound;
391 } thwomp_t;
392 
393 typedef struct
394 {
395 	thinker_t thinker;
396 	line_t *sourceline;
397 	sector_t *sector;
398 	INT16 tag;
399 } floatthink_t;
400 
401 typedef struct
402 {
403 	thinker_t thinker;
404 	line_t *sourceline; // Source line of the thinker
405 	boolean playersInArea[MAXPLAYERS];
406 	boolean playersOnArea[MAXPLAYERS];
407 	boolean triggerOnExit;
408 } eachtime_t;
409 
410 typedef enum
411 {
412 	RF_REVERSE  = 1,    //Lower when stood on
413 	RF_SPINDASH = 1<<1, //Require spindash to move
414 	RF_DYNAMIC  = 1<<2, //Dynamically sinking platform
415 } raiseflag_t;
416 
417 typedef struct
418 {
419 	thinker_t thinker;
420 	INT16 tag;
421 	sector_t *sector;
422 	fixed_t ceilingbottom;
423 	fixed_t ceilingtop;
424 	fixed_t basespeed;
425 	fixed_t extraspeed; //For dynamically sinking platform
426 	UINT8 shaketimer; //For dynamically sinking platform
427 	UINT8 flags;
428 } raise_t;
429 
430 #define ELEVATORSPEED (FRACUNIT*4)
431 #define FLOORSPEED (FRACUNIT)
432 
433 typedef enum
434 {
435 	ok,
436 	crushed,
437 	pastdest
438 } result_e;
439 
440 result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush,
441 	boolean ceiling, INT32 direction);
442 void EV_DoFloor(line_t *line, floor_e floortype);
443 void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed);
444 void EV_CrumbleChain(sector_t *sec, ffloor_t *rover);
445 void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);
446 
447 // Some other special 3dfloor types
448 INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,
449 	boolean floating, player_t *player, fixed_t origalpha, boolean crumblereturn);
450 
451 void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards);
452 
453 void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
454 
455 void T_MoveFloor(floormove_t *movefloor);
456 
457 void T_MoveElevator(elevator_t *elevator);
458 void T_ContinuousFalling(continuousfall_t *faller);
459 void T_BounceCheese(bouncecheese_t *bouncer);
460 void T_StartCrumble(crumble_t *crumble);
461 void T_MarioBlock(mariothink_t *block);
462 void T_FloatSector(floatthink_t *floater);
463 void T_MarioBlockChecker(mariocheck_t *block);
464 void T_ThwompSector(thwomp_t *thwomp);
465 void T_NoEnemiesSector(noenemies_t *nobaddies);
466 void T_EachTimeThinker(eachtime_t *eachtime);
467 void T_CameraScanner(elevator_t *elevator);
468 void T_RaiseSector(raise_t *raise);
469 
470 typedef struct
471 {
472 	thinker_t thinker; // Thinker for linedef executor delay
473 	line_t *line;      // Pointer to line that is waiting.
474 	mobj_t *caller;    // Pointer to calling mobj
475 	sector_t *sector;  // Pointer to triggering sector
476 	INT32 timer;       // Delay timer
477 } executor_t;
478 
479 void T_ExecutorDelay(executor_t *e);
480 
481 /** Generalized scroller.
482   */
483 typedef struct
484 {
485 	thinker_t thinker;   ///< Thinker structure for scrolling.
486 	fixed_t dx, dy;      ///< (dx,dy) scroll speeds.
487 	INT32 affectee;      ///< Number of affected sidedef or sector.
488 	INT32 control;       ///< Control sector (-1 if none) used to control scrolling.
489 	fixed_t last_height; ///< Last known height of control sector.
490 	fixed_t vdx, vdy;    ///< Accumulated velocity if accelerative.
491 	INT32 accel;         ///< Whether it's accelerative.
492 	INT32 exclusive;     ///< If a conveyor, same property as in pusher_t
493 	/** Types of generalized scrollers.
494 	*/
495 	enum
496 	{
497 		sc_side,         ///< Scroll wall texture on a sidedef.
498 		sc_floor,        ///< Scroll floor.
499 		sc_ceiling,      ///< Scroll ceiling.
500 		sc_carry,        ///< Carry objects on floor.
501 		sc_carry_ceiling,///< Carry objects on ceiling (for 3Dfloor conveyors).
502 	} type;
503 } scroll_t;
504 
505 void T_Scroll(scroll_t *s);
506 void T_LaserFlash(laserthink_t *flash);
507 
508 /** Friction for ice/sludge effects.
509   */
510 typedef struct
511 {
512 	thinker_t thinker;   ///< Thinker structure for friction.
513 	INT32 friction;      ///< Friction value, 0xe800 = normal.
514 	INT32 movefactor;    ///< Inertia factor when adding to momentum, FRACUNIT = normal.
515 	INT32 affectee;      ///< Number of affected sector.
516 	INT32 referrer;      ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied.
517 	UINT8 roverfriction;  ///< flag for whether friction originated from a FOF or not
518 } friction_t;
519 
520 // Friction defines.
521 #define ORIG_FRICTION          (0xE8 << (FRACBITS-8)) ///< Original value.
522 #define ORIG_FRICTION_FACTOR   (8 << (FRACBITS-8))    ///< Original value.
523 
524 void T_Friction(friction_t *f);
525 
526 typedef enum
527 {
528 	p_push,        ///< Point pusher or puller.
529 	p_wind,        ///< Wind.
530 	p_current,     ///< Current.
531 	p_upcurrent,   ///< Upwards current.
532 	p_downcurrent, ///< Downwards current.
533 	p_upwind,      ///< Upwards wind.
534 	p_downwind     ///< Downwards wind.
535 } pushertype_e;
536 
537 // Model for pushers for push/pull effects
538 typedef struct
539 {
540 	thinker_t thinker; ///< Thinker structure for push/pull effect.
541 	/** Types of push/pull effects.
542 	*/
543 	pushertype_e type;  ///< Type of push/pull effect.
544 	mobj_t *source;     ///< Point source if point pusher/puller.
545 	INT32 x_mag;        ///< X strength.
546 	INT32 y_mag;        ///< Y strength.
547 	INT32 magnitude;    ///< Vector strength for point pusher/puller.
548 	INT32 radius;       ///< Effective radius for point pusher/puller.
549 	INT32 x, y, z;      ///< Point source if point pusher/puller.
550 	INT32 affectee;     ///< Number of affected sector.
551 	UINT8 roverpusher;   ///< flag for whether pusher originated from a FOF or not
552 	INT32 referrer;     ///< If roverpusher == true, then this will contain the sector # of the control sector where the effect was applied.
553 	INT32 exclusive;    /// < Once this affect has been applied to a mobj, no other pushers may affect it.
554 	INT32 slider;       /// < Should the player go into an uncontrollable slide?
555 } pusher_t;
556 
557 // Model for disappearing/reappearing FOFs
558 typedef struct
559 {
560 	thinker_t thinker;  ///< Thinker structure for effect.
561 	tic_t appeartime;   ///< Tics to be appeared for
562 	tic_t disappeartime;///< Tics to be disappeared for
563 	tic_t offset;       ///< Time to wait until thinker starts
564 	tic_t timer;        ///< Timer between states
565 	INT32 affectee;     ///< Number of affected line
566 	INT32 sourceline;   ///< Number of source line
567 	INT32 exists;       ///< Exists toggle
568 } disappear_t;
569 
570 void T_Disappear(disappear_t *d);
571 
572 // Model for fading FOFs
573 typedef struct
574 {
575 	thinker_t thinker;  ///< Thinker structure for effect.
576 	ffloor_t *rover;    ///< Target ffloor
577 	extracolormap_t *dest_exc; ///< Colormap to fade to
578 	UINT32 sectornum;    ///< Number of ffloor target sector
579 	UINT32 ffloornum;    ///< Number of ffloor of target sector
580 	INT32 alpha;        ///< Internal alpha counter
581 	INT16 sourcevalue;  ///< Transparency value to fade from
582 	INT16 destvalue;    ///< Transparency value to fade to
583 	INT16 destlightlevel; ///< Light level to fade to
584 	INT16 speed;        ///< Speed to fade by
585 	boolean ticbased;    ///< Tic-based logic toggle
586 	INT32 timer;        ///< Timer for tic-based logic
587 	boolean doexists;   ///< Handle FF_EXISTS
588 	boolean dotranslucent; ///< Handle FF_TRANSLUCENT
589 	boolean dolighting; ///< Handle shadows and light blocks
590 	boolean docolormap; ///< Handle colormaps
591 	boolean docollision; ///< Handle interactive flags
592 	boolean doghostfade; ///< No interactive flags during fading
593 	boolean exactalpha; ///< Use exact alpha values (opengl)
594 } fade_t;
595 
596 void T_Fade(fade_t *d);
597 
598 // Model for fading colormaps
599 
600 typedef struct
601 {
602 	thinker_t thinker;          ///< Thinker structure for effect.
603 	sector_t *sector;           ///< Sector where action is taking place.
604 	extracolormap_t *source_exc;
605 	extracolormap_t *dest_exc;
606 	boolean ticbased;           ///< Tic-based timing
607 	INT32 duration;             ///< Total duration for tic-based logic (OR: speed increment)
608 	INT32 timer;                ///< Timer for tic-based logic (OR: internal speed counter)
609 } fadecolormap_t;
610 
611 void T_FadeColormap(fadecolormap_t *d);
612 
613 // Prototype functions for pushers
614 void T_Pusher(pusher_t *p);
615 mobj_t *P_GetPushThing(UINT32 s);
616 
617 // Plane displacement
618 typedef struct
619 {
620 	thinker_t thinker;   ///< Thinker structure for plane displacement effect.
621 	INT32 affectee;      ///< Number of affected sector.
622 	INT32 control;       ///< Control sector used to control plane positions.
623 	fixed_t last_height; ///< Last known height of control sector.
624 	fixed_t speed;       ///< Plane movement speed.
625 	UINT8 reverse;       ///< Move in reverse direction to control sector?
626 	/** Types of plane displacement effects.
627 	*/
628 	enum
629 	{
630 		pd_floor,        ///< Displace floor.
631 		pd_ceiling,      ///< Displace ceiling.
632 		pd_both,         ///< Displace both floor AND ceiling.
633 	} type;
634 } planedisplace_t;
635 
636 void T_PlaneDisplace(planedisplace_t *pd);
637 
638 void P_CalcHeight(player_t *player);
639 
640 sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);
641 
642 #endif
643