1 /*
2  * Portions of this file are copyright Rebirth contributors and licensed as
3  * described in COPYING.txt.
4  * Portions of this file are copyright Parallax Software and licensed
5  * according to the Parallax license below.
6  * See COPYING.txt for license details.
7 
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18 */
19 
20 /*
21  *
22  * Header for wall.c
23  *
24  */
25 
26 #pragma once
27 
28 #include "dsx-ns.h"
29 #include "fwd-segment.h"
30 #include "fwd-wall.h"
31 #include "fwd-object.h"
32 #include "pack.h"
33 #include "switch.h"
34 #include "d_underlying_value.h"
35 
36 namespace dcx {
37 
38 enum class wall_key : uint8_t
39 {
40 	none = 1,
41 	blue = 2,
42 	red = 4,
43 	gold = 8,
44 };
45 
46 constexpr uint8_t operator&(const wall_key a, const wall_key b)
47 {
48 	return underlying_value(a) & underlying_value(b);
49 }
50 
51 #if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
52 struct WALL_IS_DOORWAY_mask_t
53 {
54 	uint8_t value;
WALL_IS_DOORWAY_mask_tWALL_IS_DOORWAY_mask_t55 	constexpr WALL_IS_DOORWAY_mask_t(WALL_IS_DOORWAY_FLAG F) :
56 		value(static_cast<uint8_t>(F))
57 	{
58 	}
59 };
60 
61 struct WALL_IS_DOORWAY_result_t
62 {
63 	uint8_t value;
WALL_IS_DOORWAY_result_tWALL_IS_DOORWAY_result_t64 	constexpr WALL_IS_DOORWAY_result_t(const WALL_IS_DOORWAY_sresult_t f) :
65 		value(static_cast<unsigned>(f))
66 	{
67 	}
68 	unsigned operator&(WALL_IS_DOORWAY_FLAG f) const
69 	{
70 		return value & static_cast<uint8_t>(f);
71 	}
72 	WALL_IS_DOORWAY_result_t &operator|=(WALL_IS_DOORWAY_FLAG f)
73 	{
74 		value |= static_cast<uint8_t>(f);
75 		return *this;
76 	}
77 	bool operator==(WALL_IS_DOORWAY_sresult_t F) const
78 	{
79 		return value == static_cast<unsigned>(F);
80 	}
81 	bool operator&(WALL_IS_DOORWAY_mask_t m) const
82 	{
83 		return value & m.value;
84 	}
85 	bool operator==(WALL_IS_DOORWAY_result_t) const = delete;
86 	template <typename T>
87 		bool operator!=(const T &t) const
88 		{
89 			return !(*this == t);
90 		}
91 };
92 
93 struct stuckobj : public prohibit_void_ptr<stuckobj>
94 {
95 	objnum_t objnum = object_none;
96 	wallnum_t wallnum = wall_none;
97 };
98 #endif
99 
100 //Start old wall structures
101 
102 struct v16_wall : public prohibit_void_ptr<v16_wall>
103 {
104 	sbyte   type;               // What kind of special wall.
105 	sbyte   flags;              // Flags for the wall.
106 	uint8_t   trigger;            // Which trigger is associated with the wall.
107 	fix     hps;                // "Hit points" of the wall.
108 	sbyte   clip_num;           // Which animation associated with the wall.
109 	sbyte   keys;
110 };
111 
112 struct v19_wall : public prohibit_void_ptr<v19_wall>
113 {
114 	segnum_t     segnum;
115 	sbyte   type;               // What kind of special wall.
116 	sbyte   flags;              // Flags for the wall.
117 	int	sidenum;     // Seg & side for this wall
118 	fix     hps;                // "Hit points" of the wall.
119 	uint8_t   trigger;            // Which trigger is associated with the wall.
120 	sbyte   clip_num;           // Which animation associated with the wall.
121 	sbyte   keys;
122 	wallnum_t linked_wall;            // number of linked wall
123 };
124 
125 #ifdef dsx
126 class d_level_unique_stuck_object_state
127 {
128 protected:
129 	unsigned Num_stuck_objects = 0;
130 	std::array<stuckobj, 32> Stuck_objects;
131 public:
132 	void init_stuck_objects();
133 };
134 #endif
135 
136 enum class wall_flag : uint8_t
137 {
138 	blasted = 1,	// Blasted out wall.
139 	door_opened = 1u << 1,	// Open door.
140 	door_locked = 1u << 3,	// Door is locked.
141 	door_auto = 1u << 4,	// Door automatically closes after time.
142 	illusion_off = 1u << 5,	// Illusionary wall is shut off.
143 	exploding = 1u << 6,
144 #if defined(DXX_BUILD_DESCENT_II)
145 	buddy_proof = 1u << 7,	// Buddy assumes he cannot get through this wall.
146 #endif
147 };
148 
149 enum class wall_flags : uint8_t;
150 
151 enum class wall_state : uint8_t
152 {
153 	closed,		// Door is closed
154 	opening,	// Door is opening.
155 	waiting,	// Waiting to close
156 	closing,	// Door is closing
157 	/* if DXX_BUILD_DESCENT_II */
158 	open,		// Door is open, and staying open
159 	cloaking,	// Wall is going from closed -> open
160 	decloaking,	// Wall is going from open -> closed
161 	/* endif */
162 };
163 
164 static constexpr auto &operator|=(wall_flags &wall, const wall_flag f)
165 {
166 	return wall = static_cast<wall_flags>(underlying_value(wall) | underlying_value(f));
167 }
168 
169 static constexpr auto &operator&=(wall_flags &wall, const wall_flag f)
170 {
171 	return wall = static_cast<wall_flags>(underlying_value(wall) & underlying_value(f));
172 }
173 
174 static constexpr auto operator~(const wall_flag f)
175 {
176 	return static_cast<wall_flag>(~underlying_value(f));
177 }
178 
179 static constexpr auto operator&(const wall_flags wall, const wall_flag f)
180 {
181 	return underlying_value(wall) & underlying_value(f);
182 }
183 
184 static constexpr auto operator|(const wall_flag f1, const wall_flag f2)
185 {
186 	return static_cast<wall_flag>(underlying_value(f1) | underlying_value(f2));
187 }
188 
189 }
190 
191 //End old wall structures
192 
193 #ifdef dsx
194 namespace dsx {
195 
196 /* No shared state is possible for this structure, but include the
197  * `unique` qualifier to document its status.
198  */
199 class d_level_unique_stuck_object_state : public ::dcx::d_level_unique_stuck_object_state
200 {
201 public:
202 	void add_stuck_object(fvcwallptr &, vmobjptridx_t objp, const shared_segment &segp, unsigned sidenum);
203 	void remove_stuck_object(vcobjidx_t);
204 	void kill_stuck_objects(fvmobjptr &, vcwallidx_t wallnum);
205 };
206 
207 extern d_level_unique_stuck_object_state LevelUniqueStuckObjectState;
208 
209 struct wall : public prohibit_void_ptr<wall>
210 {
211 	segnum_t segnum;
212 	uint8_t  sidenum;     // Seg & side for this wall
213 	uint8_t type;               // What kind of special wall.
214 	fix     hps;                // "Hit points" of the wall.
215 	uint16_t explode_time_elapsed;
216 	wallnum_t linked_wall;        // number of linked wall
217 	wall_flags flags;              // Flags for the wall.
218 	wall_state state;              // Opening, closing, etc.
219 	trgnum_t trigger;            // Which trigger is associated with the wall.
220 	sbyte   clip_num;           // Which animation associated with the wall.
221 	wall_key keys;               // which keys are required
222 #if defined(DXX_BUILD_DESCENT_II)
223 	trgnum_t controlling_trigger;// which trigger causes something to happen here.  Not like "trigger" above, which is the trigger on this wall.
224                                 //  Note: This gets stuffed at load time in gamemine.c.  Don't try to use it in the editor.  You will be sorry!
225 	sbyte   cloak_value;        // if this wall is cloaked, the fade value
226 #endif
227 };
228 
229 }
230 
231 namespace dcx {
232 
233 struct active_door : public prohibit_void_ptr<active_door>
234 {
235 	unsigned n_parts;            // for linked walls
236 	std::array<wallnum_t, 2>   front_wallnum;   // front wall numbers for this door
237 	std::array<wallnum_t, 2>   back_wallnum;    // back wall numbers for this door
238 	fix     time;               // how long been opening, closing, waiting
239 };
240 
241 struct d_level_unique_active_door_state
242 {
243 	active_door_array ActiveDoors;
244 };
245 
246 }
247 
248 namespace dsx {
249 #if defined(DXX_BUILD_DESCENT_II)
250 struct cloaking_wall : public prohibit_void_ptr<cloaking_wall>
251 {
252 	wallnum_t       front_wallnum;  // front wall numbers for this door
253 	wallnum_t       back_wallnum;   // back wall numbers for this door
254 	std::array<fix, 4> front_ls;     // front wall saved light values
255 	std::array<fix, 4> back_ls;      // back wall saved light values
256 	fix     time;               // how long been cloaking or decloaking
257 };
258 
259 struct d_level_unique_cloaking_wall_state
260 {
261 	cloaking_wall_array CloakingWalls;
262 };
263 #endif
264 
265 struct d_level_unique_wall_state
266 {
267 	wall_array Walls;
268 };
269 
270 struct d_level_unique_wall_subsystem_state :
271 	d_level_unique_active_door_state,
272 	d_level_unique_trigger_state,
273 	d_level_unique_wall_state
274 #if defined(DXX_BUILD_DESCENT_II)
275 	, d_level_unique_cloaking_wall_state
276 #endif
277 {
278 };
279 
280 extern d_level_unique_wall_subsystem_state LevelUniqueWallSubsystemState;
281 
282 struct wclip : public prohibit_void_ptr<wclip>
283 {
284 	fix     play_time;
285 	uint16_t num_frames;
286 	union {
287 		std::array<uint16_t, MAX_CLIP_FRAMES> frames;
288 		std::array<uint16_t, MAX_CLIP_FRAMES_D1> d1_frames;
289 	};
290 	short   open_sound;
291 	short   close_sound;
292 	short   flags;
293 	std::array<char, 13> filename;
294 };
295 
296 constexpr std::integral_constant<uint16_t, 0xffff> wclip_frames_none{};
297 
298 }
299 #endif
300