1 //----------------------------------------------------------------------------
2 //  EDGE Data Definition File Code (Linedefs)
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 1999-2011  The EDGE Team.
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //----------------------------------------------------------------------------
18 //
19 // Line Definitions Setup and Parser Code
20 //
21 // -KM- 1998/09/01 Written.
22 // -ACB- 1998/09/06 Beautification: cleaned up so I can read it :).
23 // -KM- 1998/10/29 New types of linedefs added: colourmap, sound, friction, gravity
24 //                  auto, singlesided, music, lumpcheck
25 //                  Removed sector movement to ddf_main.c, so can be accesed by
26 //                  ddf_sect.c
27 //
28 // -ACB- 2001/02/04 DDF_GetSecHeightReference moved to p_plane.c
29 //
30 
31 #include "local.h"
32 
33 #include <limits.h>
34 
35 #include "line.h"
36 
37 #undef  DF
38 #define DF  DDF_FIELD
39 
40 #define DDF_LineHashFunc(x)  (((x) + LOOKUP_CACHESIZE) % LOOKUP_CACHESIZE)
41 
42 // -KM- 1999/01/29 Improved scrolling.
43 // Scrolling
44 typedef enum
45 {
46 	dir_none  = 0,
47 	dir_vert  = 1,
48 	dir_up    = 2,
49 	dir_horiz = 4,
50 	dir_left  = 8
51 }
52 scrolldirs_e;
53 
54 linetype_container_c linetypes;		// <-- User-defined
55 
56 static linetype_c *default_linetype;
57 
58 static void DDF_LineGetTrigType(const char *info, void *storage);
59 static void DDF_LineGetActivators(const char *info, void *storage);
60 static void DDF_LineGetSecurity(const char *info, void *storage);
61 static void DDF_LineGetScroller(const char *info, void *storage);
62 static void DDF_LineGetScrollPart(const char *info, void *storage);
63 static void DDF_LineGetExtraFloor(const char *info, void *storage);
64 static void DDF_LineGetEFControl(const char *info, void *storage);
65 static void DDF_LineGetTeleportSpecial(const char *info, void *storage);
66 static void DDF_LineGetRadTrig(const char *info, void *storage);
67 static void DDF_LineGetSpecialFlags(const char *info, void *storage);
68 static void DDF_LineGetSlideType(const char *info, void *storage);
69 static void DDF_LineGetLineEffect(const char *info, void *storage);
70 static void DDF_LineGetSectorEffect(const char *info, void *storage);
71 static void DDF_LineGetPortalEffect(const char *info, void *storage);
72 static void DDF_LineGetSlopeType(const char *info, void *storage);
73 
74 static void DDF_LineMakeCrush(const char *info);
75 
76 
77 #undef  DDF_CMD_BASE
78 #define DDF_CMD_BASE  dummy_floor
79 static movplanedef_c dummy_floor;
80 
81 const commandlist_t floor_commands[] =
82 {
83 	DF("TYPE", type, DDF_SectGetMType),
84 	DF("SPEED_UP",   speed_up,   DDF_MainGetFloat),
85 	DF("SPEED_DOWN", speed_down, DDF_MainGetFloat),
86 	DF("DEST_REF",   destref,    DDF_SectGetDestRef),
87 	DF("DEST_OFFSET", dest, DDF_MainGetFloat),
88 	DF("OTHER_REF",   otherref,  DDF_SectGetDestRef),
89 	DF("OTHER_OFFSET", other, DDF_MainGetFloat),
90 	DF("CRUSH_DAMAGE", crush_damage, DDF_MainGetNumeric),
91 	DF("TEXTURE", tex, DDF_MainGetLumpName),
92 	DF("PAUSE_TIME", wait,  DDF_MainGetTime),
93 	DF("WAIT_TIME", prewait,  DDF_MainGetTime),
94 	DF("SFX_START", sfxstart, DDF_MainLookupSound),
95 	DF("SFX_UP",    sfxup,    DDF_MainLookupSound),
96 	DF("SFX_DOWN",  sfxdown,  DDF_MainLookupSound),
97 	DF("SFX_STOP",  sfxstop,  DDF_MainLookupSound),
98 	DF("SCROLL_ANGLE", scroll_angle,DDF_MainGetAngle),
99 	DF("SCROLL_SPEED", scroll_speed,DDF_MainGetFloat),
100 	DF("IGNORE_TEXTURE", ignore_texture, DDF_MainGetBoolean),
101 
102 	DDF_CMD_END
103 };
104 
105 #undef  DDF_CMD_BASE
106 #define DDF_CMD_BASE  dummy_ladder
107 static ladderdef_c dummy_ladder;
108 
109 const commandlist_t ladder_commands[] =
110 {
111 	DF("HEIGHT", height, DDF_MainGetFloat),
112 	DDF_CMD_END
113 };
114 
115 #undef  DDF_CMD_BASE
116 #define DDF_CMD_BASE  dummy_slider
117 static sliding_door_c dummy_slider;
118 
119 const commandlist_t slider_commands[] =
120 {
121 	DF("TYPE",  type, DDF_LineGetSlideType),
122 	DF("SPEED", speed, DDF_MainGetFloat),
123 	DF("PAUSE_TIME", wait, DDF_MainGetTime),
124 	DF("SEE_THROUGH", see_through, DDF_MainGetBoolean),
125 	DF("DISTANCE",  distance,  DDF_MainGetPercent),
126 	DF("SFX_START", sfx_start, DDF_MainLookupSound),
127 	DF("SFX_OPEN",  sfx_open,  DDF_MainLookupSound),
128 	DF("SFX_CLOSE", sfx_close, DDF_MainLookupSound),
129 	DF("SFX_STOP",  sfx_stop,  DDF_MainLookupSound),
130 
131 	DDF_CMD_END
132 };
133 
134 
135 static linetype_c *dynamic_line;
136 
137 // these bits logically belong with buffer_line:
138 static float scrolling_speed;
139 static scrolldirs_e scrolling_dir;
140 
141 #undef  DDF_CMD_BASE
142 #define DDF_CMD_BASE  dummy_line
143 static linetype_c dummy_line;
144 
145 static const commandlist_t linedef_commands[] =
146 {
147 	// sub-commands
148 	DDF_SUB_LIST("FLOOR",    f,  floor_commands),
149 	DDF_SUB_LIST("CEILING",  c,  floor_commands),
150 	DDF_SUB_LIST("SLIDER",   s,  slider_commands),
151 	DDF_SUB_LIST("LADDER",   ladder, ladder_commands),
152 
153 	DF("NEWTRIGGER", newtrignum, DDF_MainGetNumeric),
154 	DF("ACTIVATORS", obj, DDF_LineGetActivators),
155 	DF("TYPE", type, DDF_LineGetTrigType),
156 	DF("KEYS", keys, DDF_LineGetSecurity),
157 	DF("FAILED_MESSAGE", failedmessage, DDF_MainGetString),
158 	DF("FAILED_SFX", failed_sfx, DDF_MainLookupSound),
159 	DF("COUNT", count, DDF_MainGetNumeric),
160 
161 	DF("DONUT", d.dodonut, DDF_MainGetBoolean),
162 	DF("DONUT_IN_SFX", d.d_sfxin, DDF_MainLookupSound),
163 	DF("DONUT_IN_SFXSTOP", d.d_sfxinstop, DDF_MainLookupSound),
164 	DF("DONUT_OUT_SFX", d.d_sfxout, DDF_MainLookupSound),
165 	DF("DONUT_OUT_SFXSTOP", d.d_sfxoutstop, DDF_MainLookupSound),
166 
167 	DF("TELEPORT", t.teleport, DDF_MainGetBoolean),
168 	DF("TELEPORT_DELAY", t.delay, DDF_MainGetTime),
169 	DF("TELEIN_EFFECTOBJ", t.inspawnobj_ref, DDF_MainGetString),
170 	DF("TELEOUT_EFFECTOBJ", t.outspawnobj_ref, DDF_MainGetString),
171 	DF("TELEPORT_SPECIAL", t.special, DDF_LineGetTeleportSpecial),
172 
173 	DF("LIGHT_TYPE", l.type, DDF_SectGetLighttype),
174 	DF("LIGHT_LEVEL", l.level, DDF_MainGetNumeric),
175 	DF("LIGHT_DARK_TIME", l.darktime, DDF_MainGetTime),
176 	DF("LIGHT_BRIGHT_TIME", l.brighttime, DDF_MainGetTime),
177 	DF("LIGHT_CHANCE", l.chance, DDF_MainGetPercent),
178 	DF("LIGHT_SYNC", l.sync, DDF_MainGetTime),
179 	DF("LIGHT_STEP", l.step, DDF_MainGetNumeric),
180 	DF("EXIT", e_exit, DDF_SectGetExit),
181 	DF("HUB_EXIT", hub_exit, DDF_MainGetNumeric),
182 
183 	DF("SCROLL_XSPEED", s_xspeed, DDF_MainGetFloat),
184 	DF("SCROLL_YSPEED", s_yspeed, DDF_MainGetFloat),
185 	DF("SCROLL_PARTS", scroll_parts, DDF_LineGetScrollPart),
186 	DF("USE_COLOURMAP", use_colourmap, DDF_MainGetColourmap),
187 	DF("GRAVITY", gravity, DDF_MainGetFloat),
188 	DF("FRICTION", friction, DDF_MainGetFloat),
189 	DF("VISCOSITY", viscosity, DDF_MainGetFloat),
190 	DF("DRAG", drag, DDF_MainGetFloat),
191 	DF("AMBIENT_SOUND", ambient_sfx, DDF_MainLookupSound),
192 	DF("ACTIVATE_SOUND", activate_sfx, DDF_MainLookupSound),
193 	DF("MUSIC", music, DDF_MainGetNumeric),
194 	DF("AUTO", autoline, DDF_MainGetBoolean),
195 	DF("SINGLESIDED", singlesided, DDF_MainGetBoolean),
196 	DF("EXTRAFLOOR_TYPE", ef.type, DDF_LineGetExtraFloor),
197 	DF("EXTRAFLOOR_CONTROL", ef.control, DDF_LineGetEFControl),
198 	DF("TRANSLUCENCY", translucency, DDF_MainGetPercent),
199 	DF("WHEN_APPEAR", appear, DDF_MainGetWhenAppear),
200 	DF("SPECIAL", special_flags, DDF_LineGetSpecialFlags),
201 	DF("RADIUS_TRIGGER", trigger_effect, DDF_LineGetRadTrig),
202 	DF("LINE_EFFECT", line_effect, DDF_LineGetLineEffect),
203 	DF("LINE_PARTS",  line_parts,  DDF_LineGetScrollPart),
204 	DF("SECTOR_EFFECT", sector_effect, DDF_LineGetSectorEffect),
205 	DF("PORTAL_TYPE",   portal_effect, DDF_LineGetPortalEffect),
206 	DF("SLOPE_TYPE", slope_type, DDF_LineGetSlopeType),
207 	DF("COLOUR", fx_color, DDF_MainGetRGB),
208 
209 	// -AJA- backwards compatibility cruft...
210 	DF("EXTRAFLOOR_TRANSLUCENCY", translucency, DDF_MainGetPercent),
211 
212 	DDF_CMD_END
213 };
214 
215 
216 typedef struct
217 {
218 	const char *s;
219 	scrolldirs_e dir;
220 }
221 scroll_kludge_t;
222 
223 static scroll_kludge_t s_scroll[] =
224 {
225 	{ "NONE",  dir_none  },
226 	{ "UP",    (scrolldirs_e)(dir_vert | dir_up) },
227 	{ "DOWN",  dir_vert  },
228 	{ "LEFT",  (scrolldirs_e)(dir_horiz | dir_left) },
229 	{ "RIGHT", dir_horiz },
230 	{ NULL,    dir_none  }
231 };
232 
233 
234 static struct  // FIXME: APPLIES TO NEXT 3 TABLES !
235 {
236 	const char *s;
237 	int n;
238 }
239 
240 // FIXME: use keytype_names (in ddf_mobj.c)
241 s_keys[] =
242 {
243 	{ "NONE",           KF_NONE },
244 
245 	{ "BLUE_CARD",      KF_BlueCard },
246 	{ "YELLOW_CARD",    KF_YellowCard },
247 	{ "RED_CARD",       KF_RedCard },
248 	{ "BLUE_SKULL",     KF_BlueSkull },
249 	{ "YELLOW_SKULL",   KF_YellowSkull },
250 	{ "RED_SKULL",      KF_RedSkull },
251 	{ "GREEN_CARD",     KF_GreenCard },
252 	{ "GREEN_SKULL",    KF_GreenSkull },
253 
254 	{ "GOLD_KEY",       KF_GoldKey },
255 	{ "SILVER_KEY",     KF_SilverKey },
256 	{ "BRASS_KEY",      KF_BrassKey },
257 	{ "COPPER_KEY",     KF_CopperKey },
258 	{ "STEEL_KEY",      KF_SteelKey },
259 	{ "WOODEN_KEY",     KF_WoodenKey },
260 	{ "FIRE_KEY",       KF_FireKey },
261 	{ "WATER_KEY",      KF_WaterKey },
262 
263 	// backwards compatibility
264 	{ "REQUIRES_ALL", KF_STRICTLY_ALL |
265 	                  KF_BlueCard | KF_YellowCard | KF_RedCard |
266 	                  KF_BlueSkull | KF_YellowSkull | KF_RedSkull }
267 }
268 ,
269 
270 s_trigger[] =
271 {
272 	{ "WALK",  line_walkable },
273 	{ "PUSH",  line_pushable },
274 	{ "SHOOT", line_shootable },
275 	{ "MANUAL", line_manual }
276 }
277 ,
278 
279 s_activators[] =
280 {
281 	{ "PLAYER",  trig_player } ,
282 	{ "MONSTER", trig_monster },
283 	{ "OTHER",   trig_other },
284 	{ "NOBOT",   trig_nobot } ,
285 
286 	// obsolete stuff
287 	{ "MISSILE", 0 }
288 };
289 
290 //
291 //  DDF PARSE ROUTINES
292 //
293 
LinedefStartEntry(const char * name,bool extend)294 static void LinedefStartEntry(const char *name, bool extend)
295 {
296 	int number = MAX(0, atoi(name));
297 
298 	if (number == 0)
299 		DDF_Error("Bad linetype number in lines.ddf: %s\n", name);
300 
301 	scrolling_dir   = dir_none;
302 	scrolling_speed = 1.0f;
303 
304 	dynamic_line = linetypes.Lookup(number);
305 
306 	if (extend)
307 	{
308 		if (! dynamic_line)
309 			DDF_Error("Unknown linetype to extend: %s\n", name);
310 		return;
311 	}
312 
313 	// replaces an existing entry?
314 	if (dynamic_line)
315 	{
316 		dynamic_line->Default();
317 		return;
318 	}
319 
320 	// not found, create a new one
321 	dynamic_line = new linetype_c;
322 	dynamic_line->number = number;
323 
324 	linetypes.Insert(dynamic_line);
325 }
326 
327 
LinedefDoTemplate(const char * contents)328 static void LinedefDoTemplate(const char *contents)
329 {
330 	int number = MAX(0, atoi(contents));
331 	if (number == 0)
332 		DDF_Error("Bad linetype number for template: %s\n", contents);
333 
334 	linetype_c *other = linetypes.Lookup(number);
335 
336 	if (!other || other == dynamic_line)
337 		DDF_Error("Unknown linetype template: '%s'\n", contents);
338 
339 	dynamic_line->CopyDetail(*other);
340 }
341 
342 
LinedefParseField(const char * field,const char * contents,int index,bool is_last)343 static void LinedefParseField(const char *field, const char *contents,
344 							  int index, bool is_last)
345 {
346 #if (DEBUG_DDF)
347 	I_Debugf("LINEDEF_PARSE: %s = %s;\n", field, contents);
348 #endif
349 
350 	if (DDF_CompareName(field, "TEMPLATE") == 0)
351 	{
352 		LinedefDoTemplate(contents);
353 		return;
354 	}
355 
356 	// ignored for backwards compatibility
357 	if (DDF_CompareName(field, "SECSPECIAL") == 0)
358 		return;
359 
360 	// -AJA- backwards compatibility cruft...
361 	if (DDF_CompareName(field, "CRUSH") == 0)
362 	{
363 		DDF_LineMakeCrush(contents);
364 		return;
365 	}
366 	else if (DDF_CompareName(field, "SCROLL") == 0)
367 	{
368 		DDF_LineGetScroller(contents, &scrolling_dir);
369 		return;
370 	}
371 	else if (DDF_CompareName(field, "SCROLLING_SPEED") == 0)
372 	{
373 		scrolling_speed = atof(contents);
374 		return;
375 	}
376 
377 	if (DDF_MainParseField(linedef_commands, field, contents, (byte *)dynamic_line))
378 		return;  // OK
379 
380 	DDF_WarnError("Unknown lines.ddf command: %s\n", field);
381 }
382 
383 
LinedefFinishEntry(void)384 static void LinedefFinishEntry(void)
385 {
386 	// -KM- 1999/01/29 Convert old style scroller to new.
387 	if (scrolling_dir & dir_vert)
388 	{
389 		if (scrolling_dir & dir_up)
390 			dynamic_line->s_yspeed = scrolling_speed;
391 		else
392 			dynamic_line->s_yspeed = -scrolling_speed;
393 	}
394 
395 	if (scrolling_dir & dir_horiz)
396 	{
397 		if (scrolling_dir & dir_left)
398 			dynamic_line->s_xspeed = scrolling_speed;
399 		else
400 			dynamic_line->s_xspeed = -scrolling_speed;
401 	}
402 
403 	// backwards compat: COUNT=0 means no limit on triggering
404 	if (dynamic_line->count == 0)
405 		dynamic_line->count = -1;
406 
407 	if (dynamic_line->hub_exit > 0)
408 		dynamic_line->e_exit = EXIT_Hub;
409 
410 	// check stuff...
411 
412 	if (dynamic_line->ef.type != EXFL_None)
413 	{
414 		// AUTO is no longer needed for extrafloors
415 		dynamic_line->autoline = false;
416 
417 		if ((dynamic_line->ef.type & EXFL_Flooder) && (dynamic_line->ef.type & EXFL_NoShade))
418 		{
419 			DDF_WarnError("FLOODER and NOSHADE tags cannot be used together.\n");
420 			dynamic_line->ef.type = (extrafloor_type_e)(dynamic_line->ef.type & ~EXFL_Flooder);
421 		}
422 
423 		if (! (dynamic_line->ef.type & EXFL_Present))
424 		{
425 			DDF_WarnError("Extrafloor type missing THIN, THICK or LIQUID.\n");
426 			dynamic_line->ef.type = EXFL_None;
427 		}
428 	}
429 
430 	if (dynamic_line->friction != FLO_UNUSED && dynamic_line->friction < 0.05f)
431 	{
432 		DDF_WarnError("Friction value too low (%1.2f), it would prevent "
433 			"all movement.\n", dynamic_line->friction);
434 		dynamic_line->friction = 0.05f;
435 	}
436 
437 	if (dynamic_line->viscosity != FLO_UNUSED && dynamic_line->viscosity > 0.95f)
438 	{
439 		DDF_WarnError("Viscosity value too high (%1.2f), it would prevent "
440 			"all movement.\n", dynamic_line->viscosity);
441 		dynamic_line->viscosity = 0.95f;
442 	}
443 
444 	// TODO: check more stuff...
445 }
446 
447 
LinedefClearAll(void)448 static void LinedefClearAll(void)
449 {
450 	// 100% safe to delete all the linetypes
451 	linetypes.Reset();
452 }
453 
454 //
455 // DDF_ReadLines
456 //
DDF_ReadLines(void * data,int size)457 bool DDF_ReadLines(void *data, int size)
458 {
459 	readinfo_t lines;
460 
461 	lines.memfile = (char*)data;
462 	lines.memsize = size;
463 	lines.tag = "LINES";
464 	lines.entries_per_dot = 6;
465 
466 	if (lines.memfile)
467 	{
468 		lines.message = NULL;
469 		lines.filename = NULL;
470 		lines.lumpname = "DDFLINE";
471 	}
472 	else
473 	{
474 		lines.message = "DDF_InitLinedefs";
475 		lines.filename = "lines.ddf";
476 		lines.lumpname = NULL;
477 	}
478 
479 	lines.start_entry  = LinedefStartEntry;
480 	lines.parse_field  = LinedefParseField;
481 	lines.finish_entry = LinedefFinishEntry;
482 	lines.clear_all    = LinedefClearAll;
483 
484 	return DDF_MainReadFile(&lines);
485 }
486 
487 //
488 // DDF_LinedefInit
489 //
DDF_LinedefInit(void)490 void DDF_LinedefInit(void)
491 {
492 	linetypes.Reset();
493 
494 	default_linetype = new linetype_c();
495 	default_linetype->number = 0;
496 }
497 
498 //
499 // DDF_LinedefCleanUp
500 //
DDF_LinedefCleanUp(void)501 void DDF_LinedefCleanUp(void)
502 {
503 	epi::array_iterator_c it;
504 	linetype_c *l;
505 
506 	for (it=linetypes.GetBaseIterator(); it.IsValid(); it++)
507 	{
508 		l = ITERATOR_TO_TYPE(it, linetype_c*);
509 
510 		cur_ddf_entryname = epi::STR_Format("[%d]  (lines.ddf)", l->number);
511 
512 		l->t.inspawnobj = l->t.inspawnobj_ref ?
513 			mobjtypes.Lookup(l->t.inspawnobj_ref) : NULL;
514 
515 		l->t.outspawnobj = l->t.outspawnobj_ref ?
516 			mobjtypes.Lookup(l->t.outspawnobj_ref) : NULL;
517 
518 		cur_ddf_entryname.clear();
519 	}
520 
521 	linetypes.Trim();
522 }
523 
524 //
525 // DDF_LineGetScroller
526 //
527 // Check for scroll types
528 //
DDF_LineGetScroller(const char * info,void * storage)529 void DDF_LineGetScroller(const char *info, void *storage)
530 {
531 	for (int i = 0; s_scroll[i].s; i++)
532 	{
533 		if (DDF_CompareName(info, s_scroll[i].s) == 0)
534 		{
535 			scrolling_dir = (scrolldirs_e)(scrolling_dir | s_scroll[i].dir);
536 			return;
537 		}
538 	}
539 	DDF_WarnError("Unknown scroll direction %s\n", info);
540 }
541 
542 //
543 // DDF_LineGetSecurity
544 //
545 // Get Red/Blue/Yellow
546 //
DDF_LineGetSecurity(const char * info,void * storage)547 void DDF_LineGetSecurity(const char *info, void *storage)
548 {
549 	keys_e *var = (keys_e *)storage;
550 
551 	bool required = false;
552 
553 	if (info[0] == '+')
554 	{
555 		required = true;
556 		info++;
557 	}
558 	else if (*var & KF_STRICTLY_ALL)
559 	{
560 		// -AJA- when there is at least one required key, then the
561 		// non-required keys don't have any effect.
562 		return;
563 	}
564 
565 	for (int i = sizeof(s_keys) / sizeof(s_keys[0]); i--; )
566 	{
567 		if (DDF_CompareName(info, s_keys[i].s) == 0)
568 		{
569 			*var = (keys_e)(*var | s_keys[i].n);
570 
571 			if (required)
572 				*var = (keys_e)(*var | KF_STRICTLY_ALL);
573 
574 			return;
575 		}
576 	}
577 
578 	DDF_WarnError("Unknown key type %s\n", info);
579 }
580 
581 //
582 // DDF_LineGetTrigType
583 //
584 // Check for walk/push/shoot
585 //
DDF_LineGetTrigType(const char * info,void * storage)586 void DDF_LineGetTrigType(const char *info, void *storage)
587 {
588 	trigger_e *var = (trigger_e *)storage;
589 
590 	for (int i = sizeof(s_trigger) / sizeof(s_trigger[0]); i--; )
591 	{
592 		if (DDF_CompareName(info, s_trigger[i].s) == 0)
593 		{
594 #if 0  // DISABLED FOR NOW
595 			if (global_flags.edge_compat && (trigger_e)s_trigger[i].n == line_manual)
596 			{
597 				*var = line_pushable;
598 				return;
599 			}
600 #endif
601 			*var = (trigger_e)s_trigger[i].n;
602 			return;
603 		}
604 	}
605 
606 	DDF_WarnError("Unknown Trigger type %s\n", info);
607 }
608 
609 //
610 // DDF_LineGetActivators
611 //
612 // Get player/monsters/missiles
613 //
DDF_LineGetActivators(const char * info,void * storage)614 void DDF_LineGetActivators(const char *info, void *storage)
615 {
616 	trigacttype_e *var = (trigacttype_e *)storage;
617 
618 	for (int i = sizeof(s_activators) / sizeof(s_activators[0]); i--; )
619 	{
620 		if (DDF_CompareName(info, s_activators[i].s) == 0)
621 		{
622 			*var = (trigacttype_e)(*var | s_activators[i].n);
623 			return;
624 		}
625 	}
626 
627 	DDF_WarnError("Unknown Activator type %s\n", info);
628 }
629 
630 static specflags_t extrafloor_types[] =
631 {
632 	// definers:
633 	{"THIN",          EF_DEF_THIN,       0},
634 	{"THICK",         EF_DEF_THICK,      0},
635 	{"LIQUID",        EF_DEF_LIQUID,     0},
636 
637 	// modifiers:
638 	{"SEE_THROUGH",   EXFL_SeeThrough,   0},
639 	{"WATER",         EXFL_Water,        0},
640 	{"SHADE",         EXFL_NoShade,      1},
641 	{"FLOODER",       EXFL_Flooder,      0},
642 	{"SIDE_UPPER",    EXFL_SideUpper,    0},
643 	{"SIDE_LOWER",    EXFL_SideLower,    0},
644 	{"SIDE_MIDY",     EXFL_SideMidY,     0},
645 	{"BOOMTEX",       EXFL_BoomTex,      0},
646 
647 	// backwards compatibility...
648 	{"FALL_THROUGH",  EXFL_Liquid, 0},
649 	{"SHOOT_THROUGH", 0, 0},
650 	{NULL, 0, 0}
651 };
652 
653 //
654 // DDF_LineGetExtraFloor
655 //
656 // Gets the extra floor type(s).
657 //
658 // -AJA- 1999/06/21: written.
659 // -AJA- 2000/03/27: updated for simpler system.
660 //
DDF_LineGetExtraFloor(const char * info,void * storage)661 void DDF_LineGetExtraFloor(const char *info, void *storage)
662 {
663 	extrafloor_type_e *var = (extrafloor_type_e *)storage;
664 
665 	if (DDF_CompareName(info, "NONE") == 0)
666 	{
667 		*var = EXFL_None;
668 		return;
669 	}
670 
671 	int flag_value;
672 
673 	switch (DDF_MainCheckSpecialFlag(info, extrafloor_types,
674 		                             &flag_value, true, false))
675 	{
676 		case CHKF_Positive:
677 			*var = (extrafloor_type_e)(*var | flag_value);
678 			break;
679 
680 		case CHKF_Negative:
681 			*var = (extrafloor_type_e)(*var & ~flag_value);
682 			break;
683 
684 		case CHKF_User:
685 		case CHKF_Unknown:
686 			DDF_WarnError("Unknown Extrafloor Type: %s\n", info);
687 			break;
688 	}
689 }
690 
691 static specflags_t ef_control_types[] =
692 {
693 	{"NONE",   EFCTL_None,   0},
694 	{"REMOVE", EFCTL_Remove, 0},
695 	{NULL, 0, 0}
696 };
697 
698 //
699 // DDF_LineGetEFControl
700 //
DDF_LineGetEFControl(const char * info,void * storage)701 void DDF_LineGetEFControl(const char *info, void *storage)
702 {
703 	extrafloor_control_e *var = (extrafloor_control_e *)storage;
704 
705 	int flag_value;
706 
707 	switch (DDF_MainCheckSpecialFlag(info, ef_control_types, &flag_value,
708 	                                 false, false))
709 	{
710 		case CHKF_Positive:
711 		case CHKF_Negative:
712 			*var = (extrafloor_control_e) flag_value;
713 			break;
714 
715 		case CHKF_User:
716 		case CHKF_Unknown:
717 			DDF_WarnError("Unknown CONTROL_EXTRAFLOOR tag: %s", info);
718 			break;
719 	}
720 }
721 
722 #define TELSP_AllSame  \
723     ((teleportspecial_e)(TELSP_Relative | TELSP_SameHeight | \
724 	  TELSP_SameSpeed | TELSP_SameOffset))
725 
726 #define TELSP_Preserve  \
727     ((teleportspecial_e)(TELSP_SameAbsDir | TELSP_SameHeight | TELSP_SameSpeed))
728 
729 static specflags_t teleport_specials[] =
730 {
731 	{"RELATIVE",   TELSP_Relative, 0},
732 	{"SAME_HEIGHT",TELSP_SameHeight, 0},
733 	{"SAME_SPEED", TELSP_SameSpeed, 0},
734 	{"SAME_OFFSET",TELSP_SameOffset, 0},
735 	{"ALL_SAME",   TELSP_AllSame, 0},
736 
737 	{"LINE",       TELSP_Line, 0},
738 	{"FLIPPED",    TELSP_Flipped, 0},
739 	{"SILENT",     TELSP_Silent, 0},
740 
741 	// these modes are deprecated (kept for B.C.)
742 	{"SAME_DIR",   TELSP_SameAbsDir, 0},
743 	{"ROTATE",     TELSP_Rotate, 0},
744 	{"PRESERVE",   TELSP_Preserve, 0},
745 
746 	{NULL, 0, 0}
747 };
748 
749 //
750 // DDF_LineGetTeleportSpecial
751 //
752 // Gets the teleporter special flags.
753 //
754 // -AJA- 1999/07/12: written.
755 //
DDF_LineGetTeleportSpecial(const char * info,void * storage)756 void DDF_LineGetTeleportSpecial(const char *info, void *storage)
757 {
758 	teleportspecial_e *var = (teleportspecial_e *)storage;
759 
760 	int flag_value;
761 
762 	switch (DDF_MainCheckSpecialFlag(info, teleport_specials,
763 									 &flag_value, true, false))
764 	{
765 		case CHKF_Positive:
766 			*var = (teleportspecial_e)(*var | flag_value);
767 			break;
768 
769 		case CHKF_Negative:
770 			*var = (teleportspecial_e)(*var & ~flag_value);
771 			break;
772 
773 		case CHKF_User:
774 		case CHKF_Unknown:
775 			DDF_WarnError("DDF_LineGetTeleportSpecial: Unknown Special: %s\n", info);
776 			break;
777 	}
778 }
779 
780 static specflags_t scrollpart_specials[] =
781 {
782 	{"RIGHT_UPPER", SCPT_RightUpper, 0},
783 	{"RIGHT_MIDDLE", SCPT_RightMiddle, 0},
784 	{"RIGHT_LOWER", SCPT_RightLower, 0},
785 	{"RIGHT", SCPT_RIGHT, 0},
786 	{"LEFT_UPPER", SCPT_LeftUpper, 0},
787 	{"LEFT_MIDDLE", SCPT_LeftMiddle, 0},
788 	{"LEFT_LOWER", SCPT_LeftLower, 0},
789 	{"LEFT", SCPT_LEFT, 0},
790 	{"LEFT_REVERSE_X", SCPT_LeftRevX, 0},
791 	{"LEFT_REVERSE_Y", SCPT_LeftRevY, 0},
792 	{NULL, 0, 0}
793 };
794 
795 //
796 // DDF_LineGetScrollPart
797 //
798 // Gets the scroll part flags.
799 //
800 // -AJA- 1999/07/12: written.
801 //
DDF_LineGetScrollPart(const char * info,void * storage)802 void DDF_LineGetScrollPart(const char *info, void *storage)
803 {
804 	int flag_value;
805 	scroll_part_e *dest = (scroll_part_e *)storage;
806 
807 	if (DDF_CompareName(info, "NONE") == 0)
808 	{
809 		(*dest) = SCPT_None;
810 		return;
811 	}
812 
813 	switch (DDF_MainCheckSpecialFlag(info, scrollpart_specials,
814 		&flag_value, true, false))
815 	{
816 		case CHKF_Positive:
817 			(*dest) = (scroll_part_e)((*dest) | flag_value);
818 			break;
819 
820 		case CHKF_Negative:
821 			(*dest) = (scroll_part_e)((*dest) & ~flag_value);
822 			break;
823 
824 		case CHKF_User:
825 		case CHKF_Unknown:
826 			DDF_WarnError("DDF_LineGetScrollPart: Unknown Part: %s", info);
827 			break;
828 	}
829 }
830 
831 //----------------------------------------------------------------------------
832 
833 static specflags_t line_specials[] =
834 {
835 	{"MUST_REACH",      LINSP_MustReach, 0},
836 	{"SWITCH_SEPARATE", LINSP_SwitchSeparate, 0},
837 	{"BACK_SECTOR",     LINSP_BackSector, 0},
838 	{NULL, 0, 0}
839 };
840 
841 //
842 // DDF_LineGetSpecialFlags
843 //
844 // Gets the line special flags.
845 //
DDF_LineGetSpecialFlags(const char * info,void * storage)846 void DDF_LineGetSpecialFlags(const char *info, void *storage)
847 {
848 	line_special_e *var = (line_special_e *)storage;
849 
850 	int flag_value;
851 
852 	switch (DDF_MainCheckSpecialFlag(info, line_specials, &flag_value,
853 									 true, false))
854 	{
855 	case CHKF_Positive:
856 		*var = (line_special_e)(*var | flag_value);
857 		break;
858 
859 	case CHKF_Negative:
860 		*var = (line_special_e)(*var & ~flag_value);
861 		break;
862 
863 	case CHKF_User:
864 	case CHKF_Unknown:
865 		DDF_WarnError("Unknown line special: %s", info);
866 		break;
867 	}
868 }
869 
870 //
871 // DDF_LineGetRadTrig
872 //
873 // Gets the line's radius trigger effect.
874 //
DDF_LineGetRadTrig(const char * info,void * storage)875 static void DDF_LineGetRadTrig(const char *info, void *storage)
876 {
877 	int *trigger_effect = (int *)storage;
878 
879 	if (DDF_CompareName(info, "ENABLE_TAGGED") == 0)
880 	{
881 		*trigger_effect = +1;
882 		return;
883 	}
884 	if (DDF_CompareName(info, "DISABLE_TAGGED") == 0)
885 	{
886 		*trigger_effect = -1;
887 		return;
888 	}
889 
890 	DDF_WarnError("DDF_LineGetRadTrig: Unknown effect: %s\n", info);
891 }
892 
893 static const specflags_t slidingdoor_names[] =
894 {
895 	{"NONE",   SLIDE_None,   0},
896 	{"LEFT",   SLIDE_Left,   0},
897 	{"RIGHT",  SLIDE_Right,  0},
898 	{"CENTER", SLIDE_Center, 0},
899 	{"CENTRE", SLIDE_Center, 0},   // synonym
900 	{NULL, 0, 0}
901 };
902 
903 //
904 // DDF_LineGetSlideType
905 //
DDF_LineGetSlideType(const char * info,void * storage)906 static void DDF_LineGetSlideType(const char *info, void *storage)
907 {
908 	if (CHKF_Positive != DDF_MainCheckSpecialFlag(info,
909 		slidingdoor_names, (int *) storage, false, false))
910 	{
911 		DDF_WarnError("DDF_LineGetSlideType: Unknown slider: %s\n", info);
912 	}
913 }
914 
915 static specflags_t line_effect_names[] =
916 {
917 	{"TRANSLUCENT",    LINEFX_Translucency, 0},
918 	{"VECTOR_SCROLL",  LINEFX_VectorScroll, 0},
919 	{"OFFSET_SCROLL",  LINEFX_OffsetScroll, 0},
920 
921 	{"SCALE_TEX",      LINEFX_Scale,         0},
922 	{"SKEW_TEX",       LINEFX_Skew,          0},
923 	{"LIGHT_WALL",     LINEFX_LightWall,     0},
924 
925 	{"UNBLOCK_THINGS", LINEFX_UnblockThings, 0},
926 	{"BLOCK_SHOTS",    LINEFX_BlockShots,    0},
927 	{"BLOCK_SIGHT",    LINEFX_BlockSight,    0},
928 	{NULL, 0, 0}
929 };
930 
931 //
932 // Gets the line effect flags.
933 //
DDF_LineGetLineEffect(const char * info,void * storage)934 static void DDF_LineGetLineEffect(const char *info, void *storage)
935 {
936 	line_effect_type_e *var = (line_effect_type_e *)storage;
937 
938 	int flag_value;
939 
940 	if (DDF_CompareName(info, "NONE") == 0)
941 	{
942 		*var = LINEFX_NONE;
943 		return;
944 	}
945 
946 	switch (DDF_MainCheckSpecialFlag(info, line_effect_names,
947 	                                 &flag_value, true, false))
948 	{
949 		case CHKF_Positive:
950 			*var = (line_effect_type_e)(*var | flag_value);
951 			break;
952 
953 		case CHKF_Negative:
954 			*var = (line_effect_type_e)(*var & ~flag_value);
955 			break;
956 
957 		case CHKF_User:
958 		case CHKF_Unknown:
959 			DDF_WarnError("Unknown line effect type: %s", info);
960 			break;
961 	}
962 }
963 
964 static specflags_t sector_effect_names[] =
965 {
966 	{"LIGHT_FLOOR",     SECTFX_LightFloor,     0},
967 	{"LIGHT_CEILING",   SECTFX_LightCeiling,   0},
968 	{"SCROLL_FLOOR",    SECTFX_ScrollFloor,    0},
969 	{"SCROLL_CEILING",  SECTFX_ScrollCeiling,  0},
970 	{"PUSH_THINGS",     SECTFX_PushThings,     0},
971 
972 	{"SET_FRICTION",    SECTFX_SetFriction,    0},
973 	{"WIND_FORCE",      SECTFX_WindForce,      0},
974 	{"CURRENT_FORCE",   SECTFX_CurrentForce,   0},
975 	{"POINT_FORCE",     SECTFX_PointForce,     0},
976 
977 	{"RESET_FLOOR",     SECTFX_ResetFloor,     0},
978 	{"RESET_CEILING",   SECTFX_ResetCeiling,   0},
979 	{"ALIGN_FLOOR",     SECTFX_AlignFloor,     0},
980 	{"ALIGN_CEILING",   SECTFX_AlignCeiling,   0},
981 	{"SCALE_FLOOR",     SECTFX_ScaleFloor,     0},
982 	{"SCALE_CEILING",   SECTFX_ScaleCeiling,   0},
983 	{NULL, 0, 0}
984 };
985 
986 //
987 // Gets the sector effect flags.
988 //
DDF_LineGetSectorEffect(const char * info,void * storage)989 static void DDF_LineGetSectorEffect(const char *info, void *storage)
990 {
991 	sector_effect_type_e *var = (sector_effect_type_e *)storage;
992 
993 	int flag_value;
994 
995 	if (DDF_CompareName(info, "NONE") == 0)
996 	{
997 		*var = SECTFX_None;
998 		return;
999 	}
1000 
1001 	switch (DDF_MainCheckSpecialFlag(info, sector_effect_names, &flag_value,
1002 	                                 true, false))
1003 	{
1004 		case CHKF_Positive:
1005 			*var = (sector_effect_type_e)(*var | flag_value);
1006 			break;
1007 
1008 		case CHKF_Negative:
1009 			*var = (sector_effect_type_e)(*var & ~flag_value);
1010 			break;
1011 
1012 		case CHKF_User:
1013 		case CHKF_Unknown:
1014 			DDF_WarnError("Unknown sector effect type: %s", info);
1015 			break;
1016 	}
1017 }
1018 
1019 static specflags_t portal_effect_names[] =
1020 {
1021 	{"STANDARD",   PORTFX_Standard,  0},
1022 	{"MIRROR",     PORTFX_Mirror,    0},
1023 	{"CAMERA",     PORTFX_Camera,    0},
1024 
1025 	{NULL, 0, 0}
1026 };
1027 
1028 //
1029 // Gets the portal effect flags.
1030 //
DDF_LineGetPortalEffect(const char * info,void * storage)1031 static void DDF_LineGetPortalEffect(const char *info, void *storage)
1032 {
1033 	portal_effect_type_e *var = (portal_effect_type_e *)storage;
1034 
1035 	int flag_value;
1036 
1037 	if (DDF_CompareName(info, "NONE") == 0)
1038 	{
1039 		*var = PORTFX_None;
1040 		return;
1041 	}
1042 
1043 	switch (DDF_MainCheckSpecialFlag(info, portal_effect_names, &flag_value,
1044 	                                 true, false))
1045 	{
1046 		case CHKF_Positive:
1047 			*var = (portal_effect_type_e)(*var | flag_value);
1048 			break;
1049 
1050 		case CHKF_Negative:
1051 			*var = (portal_effect_type_e)(*var & ~flag_value);
1052 			break;
1053 
1054 		case CHKF_User:
1055 		case CHKF_Unknown:
1056 			DDF_WarnError("Unknown portal type: %s", info);
1057 			break;
1058 	}
1059 }
1060 
1061 static specflags_t slope_type_names[] =
1062 {
1063 	{"FAKE_FLOOR",   SLP_DetailFloor,   0},
1064 	{"FAKE_CEILING", SLP_DetailCeiling, 0},
1065 
1066 	{NULL, 0, 0}
1067 };
1068 
DDF_LineGetSlopeType(const char * info,void * storage)1069 static void DDF_LineGetSlopeType(const char *info, void *storage)
1070 {
1071 	slope_type_e *var = (slope_type_e *)storage;
1072 
1073 	int flag_value;
1074 
1075 	if (DDF_CompareName(info, "NONE") == 0)
1076 	{
1077 		*var = SLP_NONE;
1078 		return;
1079 	}
1080 
1081 	switch (DDF_MainCheckSpecialFlag(info, slope_type_names, &flag_value,
1082 	                                 true, false))
1083 	{
1084 		case CHKF_Positive:
1085 			*var = (slope_type_e)(*var | flag_value);
1086 			break;
1087 
1088 		case CHKF_Negative:
1089 			*var = (slope_type_e)(*var & ~flag_value);
1090 			break;
1091 
1092 		case CHKF_User:
1093 		case CHKF_Unknown:
1094 			DDF_WarnError("Unknown slope type: %s", info);
1095 			break;
1096 	}
1097 }
1098 
DDF_LineMakeCrush(const char * info)1099 static void DDF_LineMakeCrush(const char *info)
1100 {
1101 	dynamic_line->f.crush_damage = 10;
1102 	dynamic_line->c.crush_damage = 10;
1103 }
1104 
1105 
1106 //----------------------------------------------------------------------------
1107 
1108 
1109 // --> Donut definition class
1110 
1111 //
1112 // donutdef_c Constructor
1113 //
donutdef_c()1114 donutdef_c::donutdef_c()
1115 {
1116 }
1117 
1118 //
1119 // donutdef_c Copy constructor
1120 //
donutdef_c(donutdef_c & rhs)1121 donutdef_c::donutdef_c(donutdef_c &rhs)
1122 {
1123 	Copy(rhs);
1124 }
1125 
1126 //
1127 // donutdef_c Destructor
1128 //
~donutdef_c()1129 donutdef_c::~donutdef_c()
1130 {
1131 }
1132 
1133 //
1134 // donutdef_c::Copy()
1135 //
Copy(donutdef_c & src)1136 void donutdef_c::Copy(donutdef_c &src)
1137 {
1138 	dodonut = src.dodonut;
1139 
1140 	// FIXME! Strip out the d_ since we're not trying to
1141 	// to differentiate them now?
1142 	d_sfxin = src.d_sfxin;
1143 	d_sfxinstop = src.d_sfxinstop;
1144 	d_sfxout = src.d_sfxout;
1145 	d_sfxoutstop = src.d_sfxoutstop;
1146 }
1147 
1148 //
1149 // donutdef_c::Default()
1150 //
Default()1151 void donutdef_c::Default()
1152 {
1153 	dodonut = false;
1154 	d_sfxin = NULL;
1155 	d_sfxinstop = NULL;
1156 	d_sfxout = NULL;
1157 	d_sfxoutstop = NULL;
1158 }
1159 
1160 //
1161 // donutdef_c assignment operator
1162 //
operator =(donutdef_c & rhs)1163 donutdef_c& donutdef_c::operator=(donutdef_c &rhs)
1164 {
1165 	if(&rhs != this)
1166 		Copy(rhs);
1167 
1168 	return *this;
1169 }
1170 
1171 
1172 // --> Extrafloor definition class
1173 
1174 //
1175 // extrafloordef_c Constructor
1176 //
extrafloordef_c()1177 extrafloordef_c::extrafloordef_c()
1178 {
1179 }
1180 
1181 //
1182 // extrafloordef_c Copy constructor
1183 //
extrafloordef_c(extrafloordef_c & rhs)1184 extrafloordef_c::extrafloordef_c(extrafloordef_c &rhs)
1185 {
1186 	Copy(rhs);
1187 }
1188 
1189 //
1190 // extrafloordef_c Destructor
1191 //
~extrafloordef_c()1192 extrafloordef_c::~extrafloordef_c()
1193 {
1194 }
1195 
1196 //
1197 // extrafloordef_c::Copy()
1198 //
Copy(extrafloordef_c & src)1199 void extrafloordef_c::Copy(extrafloordef_c &src)
1200 {
1201 	control = src.control;
1202 	type = src.type;
1203 }
1204 
1205 //
1206 // extrafloordef_c::Default()
1207 //
Default()1208 void extrafloordef_c::Default()
1209 {
1210 	control = EFCTL_None;
1211 	type = EXFL_None;
1212 }
1213 
1214 //
1215 // extrafloordef_c assignment operator
1216 //
operator =(extrafloordef_c & rhs)1217 extrafloordef_c& extrafloordef_c::operator=(extrafloordef_c &rhs)
1218 {
1219 	if(&rhs != this)
1220 		Copy(rhs);
1221 
1222 	return *this;
1223 }
1224 
1225 
1226 // --> Ladder definition class
1227 
1228 //
1229 // ladderdef_c Constructor
1230 //
ladderdef_c()1231 ladderdef_c::ladderdef_c()
1232 {
1233 }
1234 
1235 //
1236 // ladderdef_c Copy constructor
1237 //
ladderdef_c(ladderdef_c & rhs)1238 ladderdef_c::ladderdef_c(ladderdef_c &rhs)
1239 {
1240 	Copy(rhs);
1241 }
1242 
1243 //
1244 // ladderdef_c Destructor
1245 //
~ladderdef_c()1246 ladderdef_c::~ladderdef_c()
1247 {
1248 }
1249 
1250 //
1251 // ladderdef_c::Copy()
1252 //
Copy(ladderdef_c & src)1253 void ladderdef_c::Copy(ladderdef_c &src)
1254 {
1255 	height = src.height;
1256 }
1257 
1258 //
1259 // ladderdef_c::Default()
1260 //
Default()1261 void ladderdef_c::Default()
1262 {
1263 	height = 0.0f;
1264 }
1265 
1266 //
1267 // ladderdef_c assignment operator
1268 //
operator =(ladderdef_c & rhs)1269 ladderdef_c& ladderdef_c::operator=(ladderdef_c &rhs)
1270 {
1271 	if(&rhs != this)
1272 		Copy(rhs);
1273 
1274 	return *this;
1275 }
1276 
1277 // --> Light effect definition class
1278 
1279 //
1280 // lightdef_c Constructor
1281 //
lightdef_c()1282 lightdef_c::lightdef_c()
1283 {
1284 }
1285 
1286 //
1287 // lightdef_c Copy constructor
1288 //
lightdef_c(lightdef_c & rhs)1289 lightdef_c::lightdef_c(lightdef_c &rhs)
1290 {
1291 	Copy(rhs);
1292 }
1293 
1294 //
1295 // lightdef_c Destructor
1296 //
~lightdef_c()1297 lightdef_c::~lightdef_c()
1298 {
1299 }
1300 
1301 //
1302 // lightdef_c::Copy()
1303 //
Copy(lightdef_c & src)1304 void lightdef_c::Copy(lightdef_c &src)
1305 {
1306 	type = src.type;
1307 	level = src.level;
1308 	chance = src.chance;
1309 	darktime = src.darktime;
1310 	brighttime = src.brighttime;
1311 	sync = src.sync;
1312 	step = src.step;
1313 }
1314 
1315 //
1316 // lightdef_c::Default()
1317 //
Default()1318 void lightdef_c::Default()
1319 {
1320 	type = LITE_None;
1321 	level = 64;
1322 	chance = PERCENT_MAKE(50);
1323 	darktime = 0;
1324 	brighttime = 0;
1325 	sync = 0;
1326 	step = 8;
1327 }
1328 
1329 //
1330 // lightdef_c assignment operator
1331 //
operator =(lightdef_c & rhs)1332 lightdef_c& lightdef_c::operator=(lightdef_c &rhs)
1333 {
1334 	if(&rhs != this)
1335 		Copy(rhs);
1336 
1337 	return *this;
1338 }
1339 
1340 // --> Moving plane definition class
1341 
1342 //
1343 // movplanedef_c Constructor
1344 //
movplanedef_c()1345 movplanedef_c::movplanedef_c()
1346 {
1347 }
1348 
1349 //
1350 // movplanedef_c Copy constructor
1351 //
movplanedef_c(movplanedef_c & rhs)1352 movplanedef_c::movplanedef_c(movplanedef_c &rhs)
1353 {
1354 	Copy(rhs);
1355 }
1356 
1357 //
1358 // movplanedef_c Destructor
1359 //
~movplanedef_c()1360 movplanedef_c::~movplanedef_c()
1361 {
1362 }
1363 
1364 //
1365 // movplanedef_c::Copy()
1366 //
Copy(movplanedef_c & src)1367 void movplanedef_c::Copy(movplanedef_c &src)
1368 {
1369 	type = src.type;
1370 	is_ceiling = src.is_ceiling;
1371 	speed_up = src.speed_up;
1372 	speed_down = src.speed_down;
1373 	destref = src.destref;
1374 	dest = src.dest;
1375 	otherref = src.otherref;
1376 	other = src.other;
1377 	crush_damage = src.crush_damage;
1378 	tex = src.tex;
1379 	wait = src.wait;
1380     prewait = src.prewait;
1381 	sfxstart = src.sfxstart;
1382 	sfxup = src.sfxup;
1383 	sfxdown = src.sfxdown;
1384 	sfxstop = src.sfxstop;
1385 	scroll_angle = src.scroll_angle;
1386 	scroll_speed = src.scroll_speed;
1387 	ignore_texture = src.ignore_texture;
1388 }
1389 
1390 //
1391 // movplanedef_c::Default()
1392 //
Default(movplanedef_c::default_e def)1393 void movplanedef_c::Default(movplanedef_c::default_e def)
1394 {
1395 	type = mov_undefined;
1396 
1397 	if (def == DEFAULT_CeilingLine || def == DEFAULT_CeilingSect)
1398 		is_ceiling = true;
1399 	else
1400 		is_ceiling = false;
1401 
1402 	switch (def)
1403 	{
1404 		case DEFAULT_CeilingLine:
1405 		case DEFAULT_FloorLine:
1406 		{
1407 			speed_up = -1;
1408 			speed_down = -1;
1409 			break;
1410 		}
1411 
1412 		case DEFAULT_DonutFloor:
1413 		{
1414 			speed_up = FLOORSPEED/2;
1415 			speed_down = FLOORSPEED/2;
1416 			break;
1417 		}
1418 
1419 		default:
1420 		{
1421 			speed_up = 0;
1422 			speed_down = 0;
1423 			break;
1424 		}
1425 	}
1426 
1427 	destref = REF_Absolute;
1428 
1429 	// FIXME!!! Why are we using INT_MAX with a fp number?
1430 	dest = (def != DEFAULT_DonutFloor) ? 0.0f : (float)INT_MAX;
1431 
1432 	switch (def)
1433 	{
1434 		case DEFAULT_CeilingLine:
1435 		{
1436 			otherref = (heightref_e)(REF_Current|REF_CEILING);
1437 			break;
1438 		}
1439 
1440 		case DEFAULT_FloorLine:
1441 		{
1442 			otherref = (heightref_e)(REF_Surrounding|REF_HIGHEST|REF_INCLUDE);
1443 			break;
1444 		}
1445 
1446 		default:
1447 		{
1448 			otherref = REF_Absolute;
1449 			break;
1450 		}
1451 	}
1452 
1453 	// FIXME!!! Why are we using INT_MAX with a fp number?
1454 	other = (def != DEFAULT_DonutFloor) ? 0.0f : (float)INT_MAX;
1455 
1456 	crush_damage = 0;
1457 
1458 	tex.clear();
1459 
1460 	wait = 0;
1461 	prewait = 0;
1462 
1463 	sfxstart = NULL;
1464 	sfxup = NULL;
1465 	sfxdown = NULL;
1466 	sfxstop = NULL;
1467 
1468 	scroll_angle = 0;
1469 	scroll_speed = 0.0f;
1470 
1471 	ignore_texture = false;
1472 }
1473 
1474 //
1475 // movplanedef_c assignment operator
1476 //
operator =(movplanedef_c & rhs)1477 movplanedef_c& movplanedef_c::operator=(movplanedef_c &rhs)
1478 {
1479 	if(&rhs != this)
1480 		Copy(rhs);
1481 
1482 	return *this;
1483 }
1484 
1485 // --> Sliding door definition class
1486 
1487 //
1488 // sliding_door_c Constructor
1489 //
sliding_door_c()1490 sliding_door_c::sliding_door_c()
1491 {
1492 }
1493 
1494 //
1495 // sliding_door_c Copy constructor
1496 //
sliding_door_c(sliding_door_c & rhs)1497 sliding_door_c::sliding_door_c(sliding_door_c &rhs)
1498 {
1499 	Copy(rhs);
1500 }
1501 
1502 //
1503 // sliding_door_c Destructor
1504 //
~sliding_door_c()1505 sliding_door_c::~sliding_door_c()
1506 {
1507 }
1508 
1509 //
1510 // sliding_door_c::Copy()
1511 //
Copy(sliding_door_c & src)1512 void sliding_door_c::Copy(sliding_door_c &src)
1513 {
1514 	type = src.type;
1515 	speed = src.speed;
1516 	wait = src.wait;
1517 	see_through = src.see_through;
1518 	distance = src.distance;
1519 	sfx_start = src.sfx_start;
1520 	sfx_open = src.sfx_open;
1521 	sfx_close = src.sfx_close;
1522 	sfx_stop = src.sfx_stop;
1523 }
1524 
1525 //
1526 // sliding_door_c::Default()
1527 //
Default()1528 void sliding_door_c::Default()
1529 {
1530 	type = SLIDE_None;
1531 	speed =4.0f;
1532 	wait = 150;
1533 	see_through = false;
1534 	distance = PERCENT_MAKE(90);
1535 	sfx_start =	sfx_None;
1536 	sfx_open = sfx_None;
1537 	sfx_close = sfx_None;
1538 	sfx_stop = sfx_None;
1539 }
1540 
1541 //
1542 // sliding_door_c assignment operator
1543 //
operator =(sliding_door_c & rhs)1544 sliding_door_c& sliding_door_c::operator=(sliding_door_c &rhs)
1545 {
1546 	if(&rhs != this)
1547 		Copy(rhs);
1548 
1549 	return *this;
1550 }
1551 
1552 // --> Teleport point definition class
1553 
1554 //
1555 // teleportdef_c Constructor
1556 //
teleportdef_c()1557 teleportdef_c::teleportdef_c()
1558 {
1559 }
1560 
1561 //
1562 // teleportdef_c Copy constructor
1563 //
teleportdef_c(teleportdef_c & rhs)1564 teleportdef_c::teleportdef_c(teleportdef_c &rhs)
1565 {
1566 	Copy(rhs);
1567 }
1568 
1569 //
1570 // teleportdef_c Destructor
1571 //
~teleportdef_c()1572 teleportdef_c::~teleportdef_c()
1573 {
1574 }
1575 
1576 //
1577 // teleportdef_c::Copy()
1578 //
Copy(teleportdef_c & src)1579 void teleportdef_c::Copy(teleportdef_c &src)
1580 {
1581 	teleport = src.teleport;
1582 
1583 	inspawnobj = src.inspawnobj;
1584 	inspawnobj_ref = src.inspawnobj_ref;
1585 
1586 	outspawnobj = src.outspawnobj;
1587 	outspawnobj_ref = src.outspawnobj_ref;
1588 
1589 	special = src.special;
1590 	delay = src.delay;
1591 }
1592 
1593 //
1594 // teleportdef_c::Default()
1595 //
Default()1596 void teleportdef_c::Default()
1597 {
1598 	teleport = false;
1599 
1600 	inspawnobj = NULL;
1601 	inspawnobj_ref.clear();
1602 
1603 	outspawnobj = NULL;
1604 	outspawnobj_ref.clear();
1605 
1606 	delay = 0;
1607 	special = TELSP_None;
1608 }
1609 
1610 //
1611 // teleportdef_c assignment operator
1612 //
operator =(teleportdef_c & rhs)1613 teleportdef_c& teleportdef_c::operator=(teleportdef_c &rhs)
1614 {
1615 	if(&rhs != this)
1616 		Copy(rhs);
1617 
1618 	return *this;
1619 }
1620 
1621 // --> Line definition type class
1622 
1623 //
1624 // linetype_c Constructor
1625 //
linetype_c()1626 linetype_c::linetype_c() : number(0)
1627 {
1628 	Default();
1629 }
1630 
1631 //
1632 // linetype_c Destructor
1633 //
~linetype_c()1634 linetype_c::~linetype_c()
1635 {
1636 }
1637 
1638 
CopyDetail(linetype_c & src)1639 void linetype_c::CopyDetail(linetype_c &src)
1640 {
1641 	newtrignum = src.newtrignum;
1642 	type = src.type;
1643 	obj = src.obj;
1644 	keys = src.keys;
1645 	count = src.count;
1646 
1647 	f = src.f;
1648 	c = src.c;
1649 	d = src.d;
1650 	s = src.s;
1651 	t = src.t;
1652 	l = src.l;
1653 
1654 	ladder = src.ladder;
1655 	e_exit = src.e_exit;
1656 	hub_exit = src.hub_exit;
1657 	s_xspeed = src.s_xspeed;
1658 	s_yspeed = src.s_yspeed;
1659 	scroll_parts = src.scroll_parts;
1660 
1661 	failedmessage = src.failedmessage;
1662 	failed_sfx = src.failed_sfx;
1663 
1664 	use_colourmap = src.use_colourmap;
1665 	gravity = src.gravity;
1666 	friction = src.friction;
1667 	viscosity = src.viscosity;
1668 	drag = src.drag;
1669 	ambient_sfx = src.ambient_sfx;
1670 	activate_sfx = src.activate_sfx;
1671 	music = src.music;
1672 	autoline = src.autoline;
1673 	singlesided = src.singlesided;
1674 	ef = src.ef;
1675 	translucency = src.translucency;
1676 	appear = src.appear;
1677 
1678 	special_flags = src.special_flags;
1679 	trigger_effect = src.trigger_effect;
1680 	line_effect = src.line_effect;
1681 	line_parts = src.line_parts;
1682 	sector_effect = src.sector_effect;
1683 	portal_effect = src.portal_effect;
1684 	slope_type = src.slope_type;
1685 	fx_color = src.fx_color;
1686 }
1687 
1688 
Default(void)1689 void linetype_c::Default(void)
1690 {
1691 	newtrignum = 0;
1692 	type = line_none;
1693 	obj = trig_none;
1694 	keys = KF_NONE;
1695 	count = -1;
1696 
1697 	f.Default(movplanedef_c::DEFAULT_FloorLine);
1698 	c.Default(movplanedef_c::DEFAULT_CeilingLine);
1699 
1700 	d.Default();		// Donut
1701 	s.Default();		// Sliding Door
1702 
1703 	t.Default();		// Teleport
1704 	l.Default();		// Light definition
1705 
1706 	ladder.Default();	// Ladder
1707 
1708 	e_exit = EXIT_None;
1709 	hub_exit = 0;
1710 	s_xspeed = 0.0f;
1711 	s_yspeed = 0.0f;
1712 	scroll_parts = SCPT_None;
1713 
1714 	failedmessage.clear();
1715 	failed_sfx = NULL;
1716 
1717 	use_colourmap = NULL;
1718 	gravity = FLO_UNUSED;
1719 	friction = FLO_UNUSED;
1720 	viscosity = FLO_UNUSED;
1721 	drag = FLO_UNUSED;
1722 	ambient_sfx = sfx_None;
1723 	activate_sfx = sfx_None;
1724 	music = 0;
1725 	autoline = false;
1726 	singlesided = false;
1727 
1728 	ef.Default();
1729 
1730 	translucency = PERCENT_MAKE(100);
1731 	appear = DEFAULT_APPEAR;
1732 	special_flags = LINSP_None;
1733 	trigger_effect = 0;
1734 	line_effect = LINEFX_NONE;
1735 	line_parts = SCPT_None;
1736 	sector_effect = SECTFX_None;
1737 	portal_effect = PORTFX_None;
1738 	slope_type = SLP_NONE;
1739 	fx_color = RGB_MAKE(0,0,0);
1740 }
1741 
1742 
1743 // --> Line definition type container class
1744 
1745 //
1746 // linetype_container_c Constructor
1747 //
linetype_container_c()1748 linetype_container_c::linetype_container_c() :
1749 	epi::array_c(sizeof(linetype_c*))
1750 {
1751 	Reset();
1752 }
1753 
1754 //
1755 // linetype_container_c Destructor
1756 //
~linetype_container_c()1757 linetype_container_c::~linetype_container_c()
1758 {
1759 	Clear();
1760 }
1761 
1762 //
1763 // linetype_container_c::CleanupObject
1764 //
CleanupObject(void * obj)1765 void linetype_container_c::CleanupObject(void *obj)
1766 {
1767 	linetype_c *l = *(linetype_c**)obj;
1768 
1769 	if (l)
1770 		delete l;
1771 
1772 	return;
1773 }
1774 
1775 //
1776 // linetype_c* linetype_container_c::Lookup()
1777 //
1778 // Looks an linetype by id, returns NULL if line can't be found.
1779 //
Lookup(const int id)1780 linetype_c* linetype_container_c::Lookup(const int id)
1781 {
1782 	if (id == 0)
1783 		return default_linetype;
1784 
1785 	int slot = DDF_LineHashFunc(id);
1786 
1787 	// check the cache
1788 	if (lookup_cache[slot] &&
1789 		lookup_cache[slot]->number == id)
1790 	{
1791 		return lookup_cache[slot];
1792 	}
1793 
1794 	epi::array_iterator_c it;
1795 
1796 	for (it = GetTailIterator(); it.IsValid(); it--)
1797 	{
1798 		linetype_c *l = ITERATOR_TO_TYPE(it, linetype_c*);
1799 
1800 		if (l->number == id)
1801 		{
1802 			// update the cache
1803 			lookup_cache[slot] = l;
1804 			return l;
1805 		}
1806 	}
1807 
1808 	return NULL;
1809 }
1810 
1811 //
1812 // linetype_container_c::Reset()
1813 //
1814 // Clears down both the data and the cache
1815 //
Reset()1816 void linetype_container_c::Reset()
1817 {
1818 	Clear();
1819 	memset(lookup_cache, 0, sizeof(linetype_c*) * LOOKUP_CACHESIZE);
1820 }
1821 
1822 //--- editor settings ---
1823 // vi:ts=4:sw=4:noexpandtab
1824