1 // Emacs style mode select	 -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // DESCRIPTION:
18 //		Refresh/rendering module, shared data struct definitions.
19 //
20 //-----------------------------------------------------------------------------
21 
22 
23 #ifndef __R_DEFS_H__
24 #define __R_DEFS_H__
25 
26 #include "doomdef.h"
27 #include "templates.h"
28 #include "memarena.h"
29 
30 // Some more or less basic data types
31 // we depend on.
32 #include "m_fixed.h"
33 
34 // We rely on the thinker data struct
35 // to handle sound origins in sectors.
36 // SECTORS do store MObjs anyway.
37 #include "actor.h"
38 
39 #include "dthinker.h"
40 
41 #define MAXWIDTH 5760
42 #define MAXHEIGHT 3600
43 
44 const WORD NO_INDEX = 0xffffu;
45 const DWORD NO_SIDE = 0xffffffffu;
46 
47 // Silhouette, needed for clipping Segs (mainly)
48 // and sprites representing things.
49 enum
50 {
51 	SIL_NONE,
52 	SIL_BOTTOM,
53 	SIL_TOP,
54 	SIL_BOTH
55 };
56 
57 extern size_t MaxDrawSegs;
58 
59 
60 //
61 // INTERNAL MAP TYPES
62 //	used by play and refresh
63 //
64 
65 //
66 // Your plain vanilla vertex.
67 // Note: transformed values not buffered locally,
68 //	like some DOOM-alikes ("wt", "WebView") did.
69 //
70 enum
71 {
72 	VERTEXFLAG_ZCeilingEnabled = 0x01,
73 	VERTEXFLAG_ZFloorEnabled   = 0x02
74 };
75 struct vertexdata_t
76 {
77 	fixed_t zCeiling, zFloor;
78 	DWORD flags;
79 };
80 struct vertex_t
81 {
82 	fixed_t x, y;
83 
84 	bool operator== (const vertex_t &other)
85 	{
86 		return x == other.x && y == other.y;
87 	}
88 
clearvertex_t89 	void clear()
90 	{
91 		x = y = 0;
92 	}
93 };
94 
95 // Forward of LineDefs, for Sectors.
96 struct line_t;
97 
98 class player_t;
99 class FScanner;
100 class FBitmap;
101 struct FCopyInfo;
102 class DInterpolation;
103 class FArchive;
104 
105 enum
106 {
107 	UDMF_Line,
108 	UDMF_Side,
109 	UDMF_Sector,
110 	UDMF_Thing
111 };
112 
113 
114 struct FUDMFKey
115 {
116 	enum
117 	{
118 		UDMF_Int,
119 		UDMF_Float,
120 		UDMF_String
121 	};
122 
123 	FName Key;
124 	int Type;
125 	int IntVal;
126 	double FloatVal;
127 	FString StringVal;
128 
FUDMFKeyFUDMFKey129 	FUDMFKey()
130 	{
131 	}
132 
133 	FUDMFKey& operator =(int val)
134 	{
135 		Type = UDMF_Int;
136 		IntVal = val;
137 		FloatVal = val;
138 		StringVal = "";
139 		return *this;
140 	}
141 
142 	FUDMFKey& operator =(double val)
143 	{
144 		Type = UDMF_Float;
145 		IntVal = int(val);
146 		FloatVal = val;
147 		StringVal = "";
148 		return *this;
149 	}
150 
151 	FUDMFKey& operator =(const FString &val)
152 	{
153 		Type = UDMF_String;
154 		IntVal = strtol(val, NULL, 0);
155 		FloatVal = strtod(val, NULL);
156 		StringVal = val;
157 		return *this;
158 	}
159 
160 };
161 
162 class FUDMFKeys : public TArray<FUDMFKey>
163 {
164 public:
165 	void Sort();
166 	FUDMFKey *Find(FName key);
167 };
168 
169 //
170 // The SECTORS record, at runtime.
171 // Stores things/mobjs.
172 //
173 class DSectorEffect;
174 struct sector_t;
175 struct line_t;
176 struct FRemapTable;
177 
178 enum
179 {
180 	SECSPAC_Enter		= 1,	// Trigger when player enters
181 	SECSPAC_Exit		= 2,	// Trigger when player exits
182 	SECSPAC_HitFloor	= 4,	// Trigger when player hits floor
183 	SECSPAC_HitCeiling	= 8,	// Trigger when player hits ceiling
184 	SECSPAC_Use			= 16,	// Trigger when player uses
185 	SECSPAC_UseWall		= 32,	// Trigger when player uses a wall
186 	SECSPAC_EyesDive	= 64,	// Trigger when player eyes go below fake floor
187 	SECSPAC_EyesSurface = 128,	// Trigger when player eyes go above fake floor
188 	SECSPAC_EyesBelowC	= 256,	// Trigger when player eyes go below fake ceiling
189 	SECSPAC_EyesAboveC	= 512,	// Trigger when player eyes go above fake ceiling
190 	SECSPAC_HitFakeFloor= 1024,	// Trigger when player hits fake floor
191 };
192 
193 class ASectorAction : public AActor
194 {
195 	DECLARE_CLASS (ASectorAction, AActor)
196 public:
197 	ASectorAction (bool activatedByUse = false);
198 	void Destroy ();
199 	void BeginPlay ();
200 	void Activate (AActor *source);
201 	void Deactivate (AActor *source);
202 	bool TriggerAction(AActor *triggerer, int activationType);
203 	bool CanTrigger (AActor *triggerer) const;
204 	bool IsActivatedByUse() const;
205 protected:
206 	virtual bool DoTriggerAction(AActor *triggerer, int activationType);
207 	bool CheckTrigger(AActor *triggerer) const;
208 private:
209 	bool ActivatedByUse;
210 };
211 
212 class ASkyViewpoint;
213 
214 struct secplane_t
215 {
216 	// the plane is defined as a*x + b*y + c*z + d = 0
217 	// ic is 1/c, for faster Z calculations
218 
219 	fixed_t a, b, c, d, ic;
220 
221 	// Returns < 0 : behind; == 0 : on; > 0 : in front
PointOnSidesecplane_t222 	int PointOnSide (fixed_t x, fixed_t y, fixed_t z) const
223 	{
224 		return TMulScale16(a,x, b,y, c,z) + d;
225 	}
226 
227 	// Returns the value of z at (0,0) This is used by the 3D floor code which does not handle slopes
Zat0secplane_t228 	fixed_t Zat0 () const
229 	{
230 		return ic < 0 ? d : -d;
231 	}
232 
233 	// Returns the value of z at (x,y)
ZatPointsecplane_t234 	fixed_t ZatPoint (fixed_t x, fixed_t y) const
235 	{
236 		return FixedMul (ic, -d - DMulScale16 (a, x, b, y));
237 	}
238 
239 	// Returns the value of z at (x,y) as a double
ZatPointsecplane_t240 	double ZatPoint (double x, double y) const
241 	{
242 		return (d + a*x + b*y) * ic / (-65536.0 * 65536.0);
243 	}
244 
245 	// Returns the value of z at vertex v
ZatPointsecplane_t246 	fixed_t ZatPoint (const vertex_t *v) const
247 	{
248 		return FixedMul (ic, -d - DMulScale16 (a, v->x, b, v->y));
249 	}
250 
ZatPointsecplane_t251 	fixed_t ZatPoint (const AActor *ac) const
252 	{
253 		return FixedMul (ic, -d - DMulScale16 (a, ac->X(), b, ac->Y()));
254 	}
255 
256 	// Returns the value of z at (x,y) if d is equal to dist
ZatPointDistsecplane_t257 	fixed_t ZatPointDist (fixed_t x, fixed_t y, fixed_t dist) const
258 	{
259 		return FixedMul (ic, -dist - DMulScale16 (a, x, b, y));
260 	}
261 
262 	// Returns the value of z at vertex v if d is equal to dist
ZatPointDistsecplane_t263 	fixed_t ZatPointDist (const vertex_t *v, fixed_t dist)
264 	{
265 		return FixedMul (ic, -dist - DMulScale16 (a, v->x, b, v->y));
266 	}
267 
268 	// Flips the plane's vertical orientiation, so that if it pointed up,
269 	// it will point down, and vice versa.
FlipVertsecplane_t270 	void FlipVert ()
271 	{
272 		a = -a;
273 		b = -b;
274 		c = -c;
275 		d = -d;
276 		ic = -ic;
277 	}
278 
279 	// Returns true if 2 planes are the same
280 	bool operator== (const secplane_t &other) const
281 	{
282 		return a == other.a && b == other.b && c == other.c && d == other.d;
283 	}
284 
285 	// Returns true if 2 planes are different
286 	bool operator!= (const secplane_t &other) const
287 	{
288 		return a != other.a || b != other.b || c != other.c || d != other.d;
289 	}
290 
291 	// Moves a plane up/down by hdiff units
ChangeHeightsecplane_t292 	void ChangeHeight (fixed_t hdiff)
293 	{
294 		d = d - FixedMul (hdiff, c);
295 	}
296 
297 	// Moves a plane up/down by hdiff units
GetChangedHeightsecplane_t298 	fixed_t GetChangedHeight (fixed_t hdiff)
299 	{
300 		return d - FixedMul (hdiff, c);
301 	}
302 
303 	// Returns how much this plane's height would change if d were set to oldd
HeightDiffsecplane_t304 	fixed_t HeightDiff (fixed_t oldd) const
305 	{
306 		return FixedMul (oldd - d, ic);
307 	}
308 
309 	// Returns how much this plane's height would change if d were set to oldd
HeightDiffsecplane_t310 	fixed_t HeightDiff (fixed_t oldd, fixed_t newd) const
311 	{
312 		return FixedMul (oldd - newd, ic);
313 	}
314 
PointToDistsecplane_t315 	fixed_t PointToDist (fixed_t x, fixed_t y, fixed_t z) const
316 	{
317 		return -TMulScale16 (a, x, y, b, z, c);
318 	}
319 
PointToDistsecplane_t320 	fixed_t PointToDist (const vertex_t *v, fixed_t z) const
321 	{
322 		return -TMulScale16 (a, v->x, b, v->y, z, c);
323 	}
324 
325 	bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const;
326 
327 };
328 
329 FArchive &operator<< (FArchive &arc, secplane_t &plane);
330 
331 
332 #include "p_3dfloors.h"
333 // Ceiling/floor flags
334 enum
335 {
336 	PLANEF_ABSLIGHTING	= 1,	// floor/ceiling light is absolute, not relative
337 	PLANEF_BLOCKED		= 2,	// can not be moved anymore.
338 	PLANEF_ADDITIVE		= 4,	// rendered additive
339 };
340 
341 // Internal sector flags
342 enum
343 {
344 	SECF_FAKEFLOORONLY	= 2,	// when used as heightsec in R_FakeFlat, only copies floor
345 	SECF_CLIPFAKEPLANES = 4,	// as a heightsec, clip planes to target sector's planes
346 	SECF_NOFAKELIGHT	= 8,	// heightsec does not change lighting
347 	SECF_IGNOREHEIGHTSEC= 16,	// heightsec is only for triggering sector actions
348 	SECF_UNDERWATER		= 32,	// sector is underwater
349 	SECF_FORCEDUNDERWATER= 64,	// sector is forced to be underwater
350 	SECF_UNDERWATERMASK	= 32+64,
351 	SECF_DRAWN			= 128,	// sector has been drawn at least once
352 	SECF_HIDDEN			= 256,	// Do not draw on textured automap
353 	SECF_NOFLOORSKYBOX	= 512,	// force use of regular sky
354 	SECF_NOCEILINGSKYBOX	= 1024,	// force use of regular sky (do not separate from NOFLOORSKYBOX!!!)
355 };
356 
357 enum
358 {
359 	SECF_SILENT			= 1,	// actors in sector make no noise
360 	SECF_NOFALLINGDAMAGE= 2,	// No falling damage in this sector
361 	SECF_FLOORDROP		= 4,	// all actors standing on this floor will remain on it when it lowers very fast.
362 	SECF_NORESPAWN		= 8,	// players can not respawn in this sector
363 	SECF_FRICTION		= 16,	// sector has friction enabled
364 	SECF_PUSH			= 32,	// pushers enabled
365 	SECF_SILENTMOVE		= 64,	// Sector movement makes mo sound (Eternity got this so this may be useful for an extended cross-port standard.)
366 	SECF_DMGTERRAINFX	= 128,	// spawns terrain splash when inflicting damage
367 	SECF_ENDGODMODE		= 256,	// getting damaged by this sector ends god mode
368 	SECF_ENDLEVEL		= 512,	// ends level when health goes below 10
369 	SECF_HAZARD			= 1024,	// Change to Strife's delayed damage handling.
370 
371 	SECF_WASSECRET		= 1 << 30,	// a secret that was discovered
372 	SECF_SECRET			= 1 << 31,	// a secret sector
373 
374 	SECF_DAMAGEFLAGS = SECF_ENDGODMODE|SECF_ENDLEVEL|SECF_DMGTERRAINFX|SECF_HAZARD,
375 	SECF_NOMODIFY = SECF_SECRET|SECF_WASSECRET,	// not modifiable by Sector_ChangeFlags
376 	SECF_SPECIALFLAGS = SECF_DAMAGEFLAGS|SECF_FRICTION|SECF_PUSH,	// these flags originate from 'special and must be transferrable by floor thinkers
377 };
378 
379 enum
380 {
381 	PL_SKYFLAT = 0x40000000
382 };
383 
384 struct FDynamicColormap;
385 
386 
387 struct FLinkedSector
388 {
389 	sector_t *Sector;
390 	int Type;
391 };
392 
393 
394 // this substructure contains a few sector properties that are stored in dynamic arrays
395 // These must not be copied by R_FakeFlat etc. or bad things will happen.
396 struct extsector_t
397 {
398 	// Boom sector transfer information
399 	struct fakefloor
400 	{
401 		TArray<sector_t *> Sectors;
402 	} FakeFloor;
403 
404 	// 3DMIDTEX information
405 	struct midtex
406 	{
407 		struct plane
408 		{
409 			TArray<sector_t *> AttachedSectors;		// all sectors containing 3dMidtex lines attached to this sector
410 			TArray<line_t *> AttachedLines;			// all 3dMidtex lines attached to this sector
411 		} Floor, Ceiling;
412 	} Midtex;
413 
414 	// Linked sector information
415 	struct linked
416 	{
417 		struct plane
418 		{
419 			TArray<FLinkedSector> Sectors;
420 		} Floor, Ceiling;
421 	} Linked;
422 
423 	// 3D floors
424 	struct xfloor
425 	{
426 		TDeletingArray<F3DFloor *>		ffloors;		// 3D floors in this sector
427 		TArray<lightlist_t>				lightlist;		// 3D light list
428 		TArray<sector_t*>				attached;		// 3D floors attached to this sector
429 	} XFloor;
430 
431 	void Serialize(FArchive &arc);
432 };
433 
434 struct FTransform
435 {
436 	// killough 3/7/98: floor and ceiling texture offsets
437 	fixed_t xoffs, yoffs;
438 
439 	// [RH] floor and ceiling texture scales
440 	fixed_t xscale, yscale;
441 
442 	// [RH] floor and ceiling texture rotation
443 	angle_t angle;
444 
445 	// base values
446 	fixed_t base_angle, base_yoffs;
447 };
448 
449 struct secspecial_t
450 {
451 	FNameNoInit damagetype;		// [RH] Means-of-death for applied damage
452 	int damageamount;			// [RH] Damage to do while standing on floor
453 	short special;
454 	short damageinterval;	// Interval for damage application
455 	short leakydamage;		// chance of leaking through radiation suit
456 	int Flags;
457 
secspecial_tsecspecial_t458 	secspecial_t()
459 	{
460 		Clear();
461 	}
462 
Clearsecspecial_t463 	void Clear()
464 	{
465 		memset(this, 0, sizeof(*this));
466 	}
467 };
468 
469 FArchive &operator<< (FArchive &arc, secspecial_t &p);
470 
471 struct sector_t
472 {
473 	// Member functions
474 	bool IsLinked(sector_t *other, bool ceiling) const;
475 	fixed_t FindLowestFloorSurrounding (vertex_t **v) const;
476 	fixed_t FindHighestFloorSurrounding (vertex_t **v) const;
477 	fixed_t FindNextHighestFloor (vertex_t **v) const;
478 	fixed_t FindNextLowestFloor (vertex_t **v) const;
479 	fixed_t FindLowestCeilingSurrounding (vertex_t **v) const;			// jff 2/04/98
480 	fixed_t FindHighestCeilingSurrounding (vertex_t **v) const;			// jff 2/04/98
481 	fixed_t FindNextLowestCeiling (vertex_t **v) const;					// jff 2/04/98
482 	fixed_t FindNextHighestCeiling (vertex_t **v) const;				// jff 2/04/98
483 	fixed_t FindShortestTextureAround () const;							// jff 2/04/98
484 	fixed_t FindShortestUpperAround () const;							// jff 2/04/98
485 	sector_t *FindModelFloorSector (fixed_t floordestheight) const;		// jff 2/04/98
486 	sector_t *FindModelCeilingSector (fixed_t floordestheight) const;	// jff 2/04/98
487 	int FindMinSurroundingLight (int max) const;
488 	sector_t *NextSpecialSector (int type, sector_t *prev) const;		// [RH]
489 	fixed_t FindLowestCeilingPoint (vertex_t **v) const;
490 	fixed_t FindHighestFloorPoint (vertex_t **v) const;
491 	void AdjustFloorClip () const;
492 	void SetColor(int r, int g, int b, int desat);
493 	void SetFade(int r, int g, int b);
494 	void ClosestPoint(fixed_t x, fixed_t y, fixed_t &ox, fixed_t &oy) const;
495 	int GetFloorLight () const;
496 	int GetCeilingLight () const;
497 	sector_t *GetHeightSec() const;
498 
499 	DInterpolation *SetInterpolation(int position, bool attach);
500 
501 	ASkyViewpoint *GetSkyBox(int which);
502 
503 	enum
504 	{
505 		floor,
506 		ceiling
507 	};
508 
509 	struct splane
510 	{
511 		FTransform xform;
512 		int Flags;
513 		int Light;
514 		fixed_t alpha;
515 		FTextureID Texture;
516 		fixed_t TexZ;
517 	};
518 
519 
520 	splane planes[2];
521 
SetXOffsetsector_t522 	void SetXOffset(int pos, fixed_t o)
523 	{
524 		planes[pos].xform.xoffs = o;
525 	}
526 
AddXOffsetsector_t527 	void AddXOffset(int pos, fixed_t o)
528 	{
529 		planes[pos].xform.xoffs += o;
530 	}
531 
GetXOffsetsector_t532 	fixed_t GetXOffset(int pos) const
533 	{
534 		return planes[pos].xform.xoffs;
535 	}
536 
SetYOffsetsector_t537 	void SetYOffset(int pos, fixed_t o)
538 	{
539 		planes[pos].xform.yoffs = o;
540 	}
541 
AddYOffsetsector_t542 	void AddYOffset(int pos, fixed_t o)
543 	{
544 		planes[pos].xform.yoffs += o;
545 	}
546 
547 	fixed_t GetYOffset(int pos, bool addbase = true) const
548 	{
549 		if (!addbase)
550 		{
551 			return planes[pos].xform.yoffs;
552 		}
553 		else
554 		{
555 			return planes[pos].xform.yoffs + planes[pos].xform.base_yoffs;
556 		}
557 	}
558 
SetXScalesector_t559 	void SetXScale(int pos, fixed_t o)
560 	{
561 		planes[pos].xform.xscale = o;
562 	}
563 
GetXScalesector_t564 	fixed_t GetXScale(int pos) const
565 	{
566 		return planes[pos].xform.xscale;
567 	}
568 
SetYScalesector_t569 	void SetYScale(int pos, fixed_t o)
570 	{
571 		planes[pos].xform.yscale = o;
572 	}
573 
GetYScalesector_t574 	fixed_t GetYScale(int pos) const
575 	{
576 		return planes[pos].xform.yscale;
577 	}
578 
SetAnglesector_t579 	void SetAngle(int pos, angle_t o)
580 	{
581 		planes[pos].xform.angle = o;
582 	}
583 
584 	angle_t GetAngle(int pos, bool addbase = true) const
585 	{
586 		if (!addbase)
587 		{
588 			return planes[pos].xform.angle;
589 		}
590 		else
591 		{
592 			return planes[pos].xform.angle + planes[pos].xform.base_angle;
593 		}
594 	}
595 
SetBasesector_t596 	void SetBase(int pos, fixed_t y, angle_t o)
597 	{
598 		planes[pos].xform.base_yoffs = y;
599 		planes[pos].xform.base_angle = o;
600 	}
601 
SetAlphasector_t602 	void SetAlpha(int pos, fixed_t o)
603 	{
604 		planes[pos].alpha = o;
605 	}
606 
GetAlphasector_t607 	fixed_t GetAlpha(int pos) const
608 	{
609 		return planes[pos].alpha;
610 	}
611 
GetFlagssector_t612 	int GetFlags(int pos) const
613 	{
614 		return planes[pos].Flags;
615 	}
616 
ChangeFlagssector_t617 	void ChangeFlags(int pos, int And, int Or)
618 	{
619 		planes[pos].Flags &= ~And;
620 		planes[pos].Flags |= Or;
621 	}
622 
GetPlaneLightsector_t623 	int GetPlaneLight(int pos) const
624 	{
625 		return planes[pos].Light;
626 	}
627 
SetPlaneLightsector_t628 	void SetPlaneLight(int pos, int level)
629 	{
630 		planes[pos].Light = level;
631 	}
632 
GetTexturesector_t633 	FTextureID GetTexture(int pos) const
634 	{
635 		return planes[pos].Texture;
636 	}
637 
638 	void SetTexture(int pos, FTextureID tex, bool floorclip = true)
639 	{
640 		FTextureID old = planes[pos].Texture;
641 		planes[pos].Texture = tex;
642 		if (floorclip && pos == floor && tex != old) AdjustFloorClip();
643 	}
644 
GetPlaneTexZsector_t645 	fixed_t GetPlaneTexZ(int pos) const
646 	{
647 		return planes[pos].TexZ;
648 	}
649 
SetPlaneTexZsector_t650 	void SetPlaneTexZ(int pos, fixed_t val)
651 	{
652 		planes[pos].TexZ = val;
653 	}
654 
ChangePlaneTexZsector_t655 	void ChangePlaneTexZ(int pos, fixed_t val)
656 	{
657 		planes[pos].TexZ += val;
658 	}
659 
ClampLightsector_t660 	static inline short ClampLight(int level)
661 	{
662 		return (short)clamp(level, SHRT_MIN, SHRT_MAX);
663 	}
664 
ChangeLightLevelsector_t665 	void ChangeLightLevel(int newval)
666 	{
667 		lightlevel = ClampLight(lightlevel + newval);
668 	}
669 
SetLightLevelsector_t670 	void SetLightLevel(int newval)
671 	{
672 		lightlevel = ClampLight(newval);
673 	}
674 
GetLightLevelsector_t675 	int GetLightLevel() const
676 	{
677 		return lightlevel;
678 	}
679 
GetSecPlanesector_t680 	secplane_t &GetSecPlane(int pos)
681 	{
682 		return pos == floor? floorplane:ceilingplane;
683 	}
684 
HighestCeilingsector_t685 	fixed_t HighestCeiling(AActor *a) const
686 	{
687 		return ceilingplane.ZatPoint(a);
688 	}
689 
LowestFloorsector_t690 	fixed_t LowestFloor(AActor *a) const
691 	{
692 		return floorplane.ZatPoint(a);
693 	}
694 
695 
isSecretsector_t696 	bool isSecret() const
697 	{
698 		return !!(Flags & SECF_SECRET);
699 	}
700 
wasSecretsector_t701 	bool wasSecret() const
702 	{
703 		return !!(Flags & SECF_WASSECRET);
704 	}
705 
ClearSecretsector_t706 	void ClearSecret()
707 	{
708 		Flags &= ~SECF_SECRET;
709 	}
710 
ClearSpecialsector_t711 	void ClearSpecial()
712 	{
713 		// clears all variables that originate from 'special'. Used for sector type transferring thinkers
714 		special = 0;
715 		damageamount = 0;
716 		damageinterval = 0;
717 		damagetype = NAME_None;
718 		leakydamage = 0;
719 		Flags &= ~SECF_SPECIALFLAGS;
720 	}
721 
722 	int GetTerrain(int pos) const;
723 
724 	void TransferSpecial(sector_t *model);
725 	void GetSpecial(secspecial_t *spec);
726 	void SetSpecial(const secspecial_t *spec);
727 	bool PlaneMoving(int pos);
728 
729 
730 	// Member variables
CenterFloorsector_t731 	fixed_t		CenterFloor () const { return floorplane.ZatPoint (soundorg[0], soundorg[1]); }
CenterCeilingsector_t732 	fixed_t		CenterCeiling () const { return ceilingplane.ZatPoint (soundorg[0], soundorg[1]); }
733 
734 	// [RH] store floor and ceiling planes instead of heights
735 	secplane_t	floorplane, ceilingplane;
736 
737 	// [RH] give floor and ceiling even more properties
738 	FDynamicColormap *ColorMap;	// [RH] Per-sector colormap
739 
740 
741 	TObjPtr<AActor> SoundTarget;
742 
743 	short		special;
744 	short		lightlevel;
745 	short		seqType;		// this sector's sound sequence
746 
747 	int			sky;
748 	FNameNoInit	SeqName;		// Sound sequence name. Setting seqType non-negative will override this.
749 
750 	fixed_t		soundorg[2];	// origin for any sounds played by the sector
751 	int 		validcount;		// if == validcount, already checked
752 	AActor* 	thinglist;		// list of mobjs in sector
753 
754 	// killough 8/28/98: friction is a sector property, not an mobj property.
755 	// these fields used to be in AActor, but presented performance problems
756 	// when processed as mobj properties. Fix is to make them sector properties.
757 	fixed_t		friction, movefactor;
758 
759 	int			terrainnum[2];
760 
761 	// thinker_t for reversable actions
762 	TObjPtr<DSectorEffect> floordata;			// jff 2/22/98 make thinkers on
763 	TObjPtr<DSectorEffect> ceilingdata;			// floors, ceilings, lighting,
764 	TObjPtr<DSectorEffect> lightingdata;		// independent of one another
765 
766 	enum
767 	{
768 		CeilingMove,
769 		FloorMove,
770 		CeilingScroll,
771 		FloorScroll
772 	};
773 	TObjPtr<DInterpolation> interpolations[4];
774 
775 	BYTE 		soundtraversed;	// 0 = untraversed, 1,2 = sndlines -1
776 	// jff 2/26/98 lockout machinery for stairbuilding
777 	SBYTE stairlock;	// -2 on first locked -1 after thinker done 0 normally
778 	SWORD prevsec;		// -1 or number of sector for previous step
779 	SWORD nextsec;		// -1 or number of next step sector
780 
781 	short linecount;
782 	struct line_t **lines;		// [linecount] size
783 
784 	// killough 3/7/98: support flat heights drawn at another sector's heights
785 	sector_t *heightsec;		// other sector, or NULL if no other sector
786 
787 	DWORD bottommap, midmap, topmap;	// killough 4/4/98: dynamic colormaps
788 										// [RH] these can also be blend values if
789 										//		the alpha mask is non-zero
790 
791 	// list of mobjs that are at least partially in the sector
792 	// thinglist is a subset of touching_thinglist
793 	struct msecnode_t *touching_thinglist;				// phares 3/14/98
794 
795 	float gravity;			// [RH] Sector gravity (1.0 is normal)
796 	FNameNoInit damagetype;		// [RH] Means-of-death for applied damage
797 	int damageamount;			// [RH] Damage to do while standing on floor
798 	short damageinterval;	// Interval for damage application
799 	short leakydamage;		// chance of leaking through radiation suit
800 
801 	WORD ZoneNumber;	// [RH] Zone this sector belongs to
802 	WORD MoreFlags;		// [RH] Internal sector flags
803 	DWORD Flags;		// Sector flags
804 
805 	// [RH] Action specials for sectors. Like Skull Tag, but more
806 	// flexible in a Bloody way. SecActTarget forms a list of actors
807 	// joined by their tracer fields. When a potential sector action
808 	// occurs, SecActTarget's TriggerAction method is called.
809 	TObjPtr<ASectorAction> SecActTarget;
810 
811 	// [RH] The sky box to render for this sector. NULL means use a
812 	// regular sky.
813 	TObjPtr<ASkyViewpoint> SkyBoxes[2];
814 
815 	int							sectornum;			// for comparing sector copies
816 
817 	extsector_t	*				e;		// This stores data that requires construction/destruction. Such data must not be copied by R_FakeFlat.
818 };
819 
820 FArchive &operator<< (FArchive &arc, sector_t::splane &p);
821 
822 
823 struct ReverbContainer;
824 struct zone_t
825 {
826 	ReverbContainer *Environment;
827 };
828 
829 
830 //
831 // The SideDef.
832 //
833 
834 class DBaseDecal;
835 
836 enum
837 {
838 	WALLF_ABSLIGHTING	 = 1,	// Light is absolute instead of relative
839 	WALLF_NOAUTODECALS	 = 2,	// Do not attach impact decals to this wall
840 	WALLF_NOFAKECONTRAST = 4,	// Don't do fake contrast for this wall in side_t::GetLightLevel
841 	WALLF_SMOOTHLIGHTING = 8,   // Similar to autocontrast but applies to all angles.
842 	WALLF_CLIP_MIDTEX	 = 16,	// Like the line counterpart, but only for this side.
843 	WALLF_WRAP_MIDTEX	 = 32,	// Like the line counterpart, but only for this side.
844 	WALLF_POLYOBJ		 = 64,	// This wall belongs to a polyobject.
845 	WALLF_LIGHT_FOG      = 128,	// This wall's Light is used even in fog.
846 };
847 
848 struct side_t
849 {
850 	enum ETexpart
851 	{
852 		top=0,
853 		mid=1,
854 		bottom=2
855 	};
856 	struct part
857 	{
858 		fixed_t xoffset;
859 		fixed_t yoffset;
860 		fixed_t xscale;
861 		fixed_t yscale;
862 		FTextureID texture;
863 		TObjPtr<DInterpolation> interpolation;
864 		//int Light;
865 	};
866 
867 	sector_t*	sector;			// Sector the SideDef is facing.
868 	DBaseDecal*	AttachedDecals;	// [RH] Decals bound to the wall
869 	part		textures[3];
870 	line_t		*linedef;
871 	//DWORD		linenum;
872 	DWORD		LeftSide, RightSide;	// [RH] Group walls into loops
873 	WORD		TexelLength;
874 	SWORD		Light;
875 	BYTE		Flags;
876 	int			Index;		// needed to access custom UDMF fields which are stored in loading order.
877 
878 	int GetLightLevel (bool foggy, int baselight, bool noabsolute=false, int *pfakecontrast_usedbygzdoom=NULL) const;
879 
SetLightside_t880 	void SetLight(SWORD l)
881 	{
882 		Light = l;
883 	}
884 
GetTextureside_t885 	FTextureID GetTexture(int which) const
886 	{
887 		return textures[which].texture;
888 	}
SetTextureside_t889 	void SetTexture(int which, FTextureID tex)
890 	{
891 		textures[which].texture = tex;
892 	}
893 
SetTextureXOffsetside_t894 	void SetTextureXOffset(int which, fixed_t offset)
895 	{
896 		textures[which].xoffset = offset;
897 	}
SetTextureXOffsetside_t898 	void SetTextureXOffset(fixed_t offset)
899 	{
900 		textures[top].xoffset =
901 		textures[mid].xoffset =
902 		textures[bottom].xoffset = offset;
903 	}
GetTextureXOffsetside_t904 	fixed_t GetTextureXOffset(int which) const
905 	{
906 		return textures[which].xoffset;
907 	}
AddTextureXOffsetside_t908 	void AddTextureXOffset(int which, fixed_t delta)
909 	{
910 		textures[which].xoffset += delta;
911 	}
912 
SetTextureYOffsetside_t913 	void SetTextureYOffset(int which, fixed_t offset)
914 	{
915 		textures[which].yoffset = offset;
916 	}
SetTextureYOffsetside_t917 	void SetTextureYOffset(fixed_t offset)
918 	{
919 		textures[top].yoffset =
920 		textures[mid].yoffset =
921 		textures[bottom].yoffset = offset;
922 	}
GetTextureYOffsetside_t923 	fixed_t GetTextureYOffset(int which) const
924 	{
925 		return textures[which].yoffset;
926 	}
AddTextureYOffsetside_t927 	void AddTextureYOffset(int which, fixed_t delta)
928 	{
929 		textures[which].yoffset += delta;
930 	}
931 
SetTextureXScaleside_t932 	void SetTextureXScale(int which, fixed_t scale)
933 	{
934 		textures[which].xscale = scale == 0 ? FRACUNIT : scale;
935 	}
SetTextureXScaleside_t936 	void SetTextureXScale(fixed_t scale)
937 	{
938 		textures[top].xscale = textures[mid].xscale = textures[bottom].xscale = scale == 0 ? FRACUNIT : scale;
939 	}
GetTextureXScaleside_t940 	fixed_t GetTextureXScale(int which) const
941 	{
942 		return textures[which].xscale;
943 	}
MultiplyTextureXScaleside_t944 	void MultiplyTextureXScale(int which, fixed_t delta)
945 	{
946 		textures[which].xscale = FixedMul(textures[which].xscale, delta);
947 	}
948 
949 
SetTextureYScaleside_t950 	void SetTextureYScale(int which, fixed_t scale)
951 	{
952 		textures[which].yscale = scale == 0 ? FRACUNIT : scale;
953 	}
SetTextureYScaleside_t954 	void SetTextureYScale(fixed_t scale)
955 	{
956 		textures[top].yscale = textures[mid].yscale = textures[bottom].yscale = scale == 0 ? FRACUNIT : scale;
957 	}
GetTextureYScaleside_t958 	fixed_t GetTextureYScale(int which) const
959 	{
960 		return textures[which].yscale;
961 	}
MultiplyTextureYScaleside_t962 	void MultiplyTextureYScale(int which, fixed_t delta)
963 	{
964 		textures[which].yscale = FixedMul(textures[which].yscale, delta);
965 	}
966 
967 	DInterpolation *SetInterpolation(int position);
968 	void StopInterpolation(int position);
969 
970 	vertex_t *V1() const;
971 	vertex_t *V2() const;
972 };
973 
974 FArchive &operator<< (FArchive &arc, side_t::part &p);
975 
976 struct line_t
977 {
978 	vertex_t	*v1, *v2;	// vertices, from v1 to v2
979 	fixed_t 	dx, dy;		// precalculated v2 - v1 for side checking
980 	DWORD		flags;
981 	DWORD		activation;	// activation type
982 	int			special;
983 	fixed_t		Alpha;		// <--- translucency (0=invisibile, FRACUNIT=opaque)
984 	int			args[5];	// <--- hexen-style arguments (expanded to ZDoom's full width)
985 	side_t		*sidedef[2];
986 	fixed_t		bbox[4];	// bounding box, for the extent of the LineDef.
987 	sector_t	*frontsector, *backsector;
988 	int 		validcount;	// if == validcount, already checked
989 	int			locknumber;	// [Dusk] lock number for special
990 
isLinePortalline_t991 	bool isLinePortal() const
992 	{
993 		return false;
994 	}
995 };
996 
997 // phares 3/14/98
998 //
999 // Sector list node showing all sectors an object appears in.
1000 //
1001 // There are two threads that flow through these nodes. The first thread
1002 // starts at touching_thinglist in a sector_t and flows through the m_snext
1003 // links to find all mobjs that are entirely or partially in the sector.
1004 // The second thread starts at touching_sectorlist in a AActor and flows
1005 // through the m_tnext links to find all sectors a thing touches. This is
1006 // useful when applying friction or push effects to sectors. These effects
1007 // can be done as thinkers that act upon all objects touching their sectors.
1008 // As an mobj moves through the world, these nodes are created and
1009 // destroyed, with the links changed appropriately.
1010 //
1011 // For the links, NULL means top or end of list.
1012 
1013 struct msecnode_t
1014 {
1015 	sector_t			*m_sector;	// a sector containing this object
1016 	AActor				*m_thing;	// this object
1017 	struct msecnode_t	*m_tprev;	// prev msecnode_t for this thing
1018 	struct msecnode_t	*m_tnext;	// next msecnode_t for this thing
1019 	struct msecnode_t	*m_sprev;	// prev msecnode_t for this sector
1020 	struct msecnode_t	*m_snext;	// next msecnode_t for this sector
1021 	bool visited;	// killough 4/4/98, 4/7/98: used in search algorithms
1022 };
1023 
1024 struct FPolyNode;
1025 struct FMiniBSP;
1026 
1027 //
1028 // The LineSeg.
1029 //
1030 struct seg_t
1031 {
1032 	vertex_t*	v1;
1033 	vertex_t*	v2;
1034 
1035 	side_t* 	sidedef;
1036 	line_t* 	linedef;
1037 
1038 	// Sector references. Could be retrieved from linedef, too.
1039 	sector_t*		frontsector;
1040 	sector_t*		backsector;		// NULL for one-sided lines
1041 };
1042 
1043 struct glsegextra_t
1044 {
1045 	DWORD		 PartnerSeg;
1046 	subsector_t *Subsector;
1047 };
1048 
1049 //
1050 // A SubSector.
1051 // References a Sector.
1052 // Basically, this is a list of LineSegs indicating the visible walls that
1053 // define (all or some) sides of a convex BSP leaf.
1054 //
1055 
1056 enum
1057 {
1058 	SSECF_DEGENERATE = 1,
1059 	SSECF_DRAWN = 2,
1060 	SSECF_POLYORG = 4,
1061 };
1062 
1063 struct subsector_t
1064 {
1065 	sector_t	*sector;
1066 	FPolyNode	*polys;
1067 	FMiniBSP	*BSP;
1068 	seg_t		*firstline;
1069 	sector_t	*render_sector;
1070 	DWORD		numlines;
1071 	int			flags;
1072 
1073 	void BuildPolyBSP();
1074 };
1075 
1076 
1077 
1078 
1079 //
1080 // BSP node.
1081 //
1082 struct node_t
1083 {
1084 	// Partition line.
1085 	fixed_t		x;
1086 	fixed_t		y;
1087 	fixed_t		dx;
1088 	fixed_t		dy;
1089 	fixed_t		bbox[2][4];		// Bounding box for each child.
1090 	float		len;
1091 	union
1092 	{
1093 		void	*children[2];	// If bit 0 is set, it's a subsector.
1094 		int		intchildren[2];	// Used by nodebuilder.
1095 	};
1096 };
1097 
1098 
1099 // An entire BSP tree.
1100 
1101 struct FMiniBSP
1102 {
1103 	bool bDirty;
1104 
1105 	TArray<node_t> Nodes;
1106 	TArray<seg_t> Segs;
1107 	TArray<subsector_t> Subsectors;
1108 	TArray<vertex_t> Verts;
1109 };
1110 
1111 
1112 
1113 //
1114 // OTHER TYPES
1115 //
1116 
1117 typedef BYTE lighttable_t;	// This could be wider for >8 bit display.
1118 
1119 // This encapsulates the fields of vissprite_t that can be altered by AlterWeaponSprite
1120 struct visstyle_t
1121 {
1122 	lighttable_t	*colormap;
1123 	fixed_t			alpha;
1124 	FRenderStyle	RenderStyle;
1125 };
1126 
1127 
1128 #endif
1129