1 //----------------------------------------------------------------------------
2 //  EDGE New SaveGame Handling (Level Data)
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 1999-2008  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 // See the file "docs/save_sys.txt" for a complete description of the
20 // new savegame system.
21 //
22 // This file handles:
23 //    surface_t      [SURF]
24 //    side_t         [SIDE]
25 //    line_t         [LINE]
26 //
27 //    region_properties_t  [RPRP]
28 //    extrafloor_t         [EXFL]
29 //    sector_t             [SECT]
30 //
31 
32 #include "i_defs.h"
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 
37 #include "epi/str_format.h"
38 
39 #include "ddf/colormap.h"
40 
41 #include "r_image.h"
42 #include "sv_chunk.h"
43 #include "sv_main.h"
44 #include "z_zone.h"
45 
46 #undef SF
47 #define SF  SVFIELD
48 
49 
50 // forward decls.
51 int SV_SideCountElems(void);
52 int SV_SideFindElem(side_t *elem);
53 void * SV_SideGetElem(int index);
54 void SV_SideCreateElems(int num_elems);
55 void SV_SideFinaliseElems(void);
56 
57 int SV_LineCountElems(void);
58 int SV_LineFindElem(line_t *elem);
59 void * SV_LineGetElem(int index);
60 void SV_LineCreateElems(int num_elems);
61 void SV_LineFinaliseElems(void);
62 
63 int SV_ExfloorCountElems(void);
64 int SV_ExfloorFindElem(extrafloor_t *elem);
65 void * SV_ExfloorGetElem(int index);
66 void SV_ExfloorCreateElems(int num_elems);
67 void SV_ExfloorFinaliseElems(void);
68 
69 int SV_SectorCountElems(void);
70 int SV_SectorFindElem(sector_t *elem);
71 void * SV_SectorGetElem(int index);
72 void SV_SectorCreateElems(int num_elems);
73 void SV_SectorFinaliseElems(void);
74 
75 bool SR_LevelGetImage(void *storage, int index, void *extra);
76 bool SR_LevelGetColmap(void *storage, int index, void *extra);
77 bool SR_LevelGetSurface(void *storage, int index, void *extra);
78 bool SR_LevelGetSurfPtr(void *storage, int index, void *extra);
79 bool SR_LineGetSpecial(void *storage, int index, void *extra);
80 bool SR_SectorGetSpecial(void *storage, int index, void *extra);
81 bool SR_SectorGetProps(void *storage, int index, void *extra);
82 bool SR_SectorGetPropRef(void *storage, int index, void *extra);
83 bool SR_SectorGetGenMove(void *storage, int index, void *extra);
84 
85 void SR_LevelPutImage(void *storage, int index, void *extra);
86 void SR_LevelPutColmap(void *storage, int index, void *extra);
87 void SR_LevelPutSurface(void *storage, int index, void *extra);
88 void SR_LevelPutSurfPtr(void *storage, int index, void *extra);
89 void SR_LinePutSpecial(void *storage, int index, void *extra);
90 void SR_SectorPutSpecial(void *storage, int index, void *extra);
91 void SR_SectorPutProps(void *storage, int index, void *extra);
92 void SR_SectorPutPropRef(void *storage, int index, void *extra);
93 void SR_SectorPutGenMove(void *storage, int index, void *extra);
94 
95 
96 //----------------------------------------------------------------------------
97 //
98 //  SURFACE STRUCTURE
99 //
100 static surface_t sv_dummy_surface;
101 
102 #define SV_F_BASE  sv_dummy_surface
103 
104 static savefield_t sv_fields_surface[] =
105 {
106 	SF(image, "image", 1, SVT_STRING, SR_LevelGetImage, SR_LevelPutImage),
107 	SF(translucency, "translucency", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
108 
109 	SF(offset, "offset", 1, SVT_VEC2, SR_GetVec2, SR_PutVec2),
110 	SF(scroll, "scroll", 1, SVT_VEC2, SR_GetVec2, SR_PutVec2),
111 	SF(x_mat, "x_mat", 1, SVT_VEC2, SR_GetVec2, SR_PutVec2),
112 	SF(y_mat, "y_mat", 1, SVT_VEC2, SR_GetVec2, SR_PutVec2),
113 
114 	SF(override_p, "override_p", 1, SVT_STRING, SR_SectorGetPropRef, SR_SectorPutPropRef),
115 
116 	SVFIELD_END
117 };
118 
119 savestruct_t sv_struct_surface =
120 {
121 	NULL,                  // link in list
122 	"surface_t",           // structure name
123 	"surf",                // start marker
124 	sv_fields_surface,     // field descriptions
125 	SVDUMMY,               // dummy base
126 	true,                  // define_me
127 	NULL                   // pointer to known struct
128 };
129 
130 #undef SV_F_BASE
131 
132 
133 //----------------------------------------------------------------------------
134 //
135 //  SIDE STRUCTURE
136 //
137 static side_t sv_dummy_side;
138 
139 #define SV_F_BASE  sv_dummy_side
140 
141 static savefield_t sv_fields_side[] =
142 {
143 	SF(top, "top", 1, SVT_STRUCT("surface_t"), SR_LevelGetSurface, SR_LevelPutSurface),
144 	SF(middle, "middle", 1, SVT_STRUCT("surface_t"), SR_LevelGetSurface, SR_LevelPutSurface),
145 	SF(bottom, "bottom", 1, SVT_STRUCT("surface_t"), SR_LevelGetSurface, SR_LevelPutSurface),
146 
147 	// NOT HERE:
148 	//   sector: value is kept from level load.
149 
150 	SVFIELD_END
151 };
152 
153 savestruct_t sv_struct_side =
154 {
155 	NULL,          // link in list
156 	"side_t",      // structure name
157 	"side",        // start marker
158 	sv_fields_side,  // field descriptions
159 	SVDUMMY,       // dummy base
160 	true,          // define_me
161 	NULL           // pointer to known struct
162 };
163 
164 #undef SV_F_BASE
165 
166 savearray_t sv_array_side =
167 {
168 	NULL,               // link in list
169 	"sides",            // array name
170 	&sv_struct_side,    // array type
171 	true,               // define_me
172 	true,               // allow_hub
173 
174 	SV_SideCountElems,     // count routine
175 	SV_SideGetElem,        // index routine
176 	SV_SideCreateElems,    // creation routine
177 	SV_SideFinaliseElems,  // finalisation routine
178 
179 	NULL,     // pointer to known array
180 	0         // loaded size
181 };
182 
183 
184 //----------------------------------------------------------------------------
185 //
186 //  LINE STRUCTURE
187 //
188 static line_t sv_dummy_line;
189 
190 #define SV_F_BASE  sv_dummy_line
191 
192 static savefield_t sv_fields_line[] =
193 {
194 	SF(flags, "flags", 1, SVT_INT, SR_GetInt, SR_PutInt),
195 	SF(tag,   "tag",   1, SVT_INT, SR_GetInt, SR_PutInt),
196 	SF(count, "count", 1, SVT_INT, SR_GetInt, SR_PutInt),
197 	SF(special, "special", 1, SVT_STRING, SR_LineGetSpecial, SR_LinePutSpecial),
198 	SF(slide_door, "slide_door", 1, SVT_STRING, SR_LineGetSpecial, SR_LinePutSpecial),
199 
200 	// NOT HERE:
201 	//   (many): values are kept from level load.
202 	//   gap stuff: regenerated from sector heights.
203 	//   validcount: only a temporary value for some routines.
204 	//   slider_move: regenerated by a pass of the active part list.
205 
206 	SVFIELD_END
207 };
208 
209 savestruct_t sv_struct_line =
210 {
211 	NULL,          // link in list
212 	"line_t",      // structure name
213 	"line",        // start marker
214 	sv_fields_line,  // field descriptions
215 	SVDUMMY,       // dummy base
216 	true,          // define_me
217 	NULL           // pointer to known struct
218 };
219 
220 #undef SV_F_BASE
221 
222 savearray_t sv_array_line =
223 {
224 	NULL,               // link in list
225 	"lines",            // array name
226 	&sv_struct_line,    // array type
227 	true,               // define_me
228 	true,               // allow_hub
229 
230 	SV_LineCountElems,     // count routine
231 	SV_LineGetElem,        // index routine
232 	SV_LineCreateElems,    // creation routine
233 	SV_LineFinaliseElems,  // finalisation routine
234 
235 	NULL,     // pointer to known array
236 	0         // loaded size
237 };
238 
239 
240 //----------------------------------------------------------------------------
241 //
242 //  REGION_PROPERTIES STRUCTURE
243 //
244 static region_properties_t sv_dummy_regprops;
245 
246 #define SV_F_BASE  sv_dummy_regprops
247 
248 static savefield_t sv_fields_regprops[] =
249 {
250 	SF(lightlevel, "lightlevel_i", 1, SVT_INT, SR_GetInt, SR_PutInt),
251 	SF(colourmap,  "colourmap", 1, SVT_STRING, SR_LevelGetColmap, SR_LevelPutColmap),
252 
253 	SF(type, "type", 1, SVT_INT, SR_GetInt, SR_PutInt),
254 	SF(special, "special", 1, SVT_STRING, SR_SectorGetSpecial, SR_SectorPutSpecial),
255 
256 	SF(gravity, "gravity", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
257 	SF(friction, "friction", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
258 	SF(viscosity, "viscosity", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
259 	SF(drag, "drag", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
260 	SF(push, "push", 1, SVT_VEC3, SR_GetVec3, SR_PutVec3),
261 
262 	SVFIELD_END
263 };
264 
265 savestruct_t sv_struct_regprops =
266 {
267 	NULL,                   // link in list
268 	"region_properties_t",  // structure name
269 	"rprp",                 // start marker
270 	sv_fields_regprops,     // field descriptions
271 	SVDUMMY,                // dummy base
272 	true,                   // define_me
273 	NULL                    // pointer to known struct
274 };
275 
276 #undef SV_F_BASE
277 
278 
279 //----------------------------------------------------------------------------
280 //
281 //  EXTRAFLOOR STRUCTURE
282 //
283 static extrafloor_t sv_dummy_exfloor;
284 
285 #define SV_F_BASE  sv_dummy_exfloor
286 
287 static savefield_t sv_fields_exfloor[] =
288 {
289 	SF(higher, "higher", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
290 	SF(lower, "lower", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
291 	SF(sector, "sector", 1, SVT_INDEX("sectors"), SR_SectorGetSector, SR_SectorPutSector),
292 
293 	SF(top_h, "top_h", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
294 	SF(bottom_h, "bottom_h", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
295 	SF(top, "top", 1, SVT_STRING, SR_LevelGetSurfPtr, SR_LevelPutSurfPtr),
296 	SF(bottom, "bottom", 1, SVT_STRING, SR_LevelGetSurfPtr, SR_LevelPutSurfPtr),
297 
298 	SF(p, "p", 1, SVT_STRING, SR_SectorGetPropRef, SR_SectorPutPropRef),
299 	SF(ef_line, "ef_line", 1, SVT_INDEX("lines"), SR_LineGetLine, SR_LinePutLine),
300 	SF(ctrl_next, "ctrl_next", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
301 
302 	// NOT HERE:
303 	//   - sector: can be regenerated.
304 	//   - ef_info: cached value, regenerated from ef_line.
305 
306 	SVFIELD_END
307 };
308 
309 savestruct_t sv_struct_exfloor =
310 {
311 	NULL,              // link in list
312 	"extrafloor_t",    // structure name
313 	"exfl",            // start marker
314 	sv_fields_exfloor, // field descriptions
315   SVDUMMY,           // dummy base
316 	true,              // define_me
317 	NULL               // pointer to known struct
318 };
319 
320 #undef SV_F_BASE
321 
322 savearray_t sv_array_exfloor =
323 {
324 	NULL,               // link in list
325 	"extrafloors",      // array name
326 	&sv_struct_exfloor, // array type
327 	true,               // define_me
328 	true,               // allow_hub
329 
330 	SV_ExfloorCountElems,     // count routine
331 	SV_ExfloorGetElem,        // index routine
332 	SV_ExfloorCreateElems,    // creation routine
333 	SV_ExfloorFinaliseElems,  // finalisation routine
334 
335 	NULL,     // pointer to known array
336 	0         // loaded size
337 };
338 
339 
340 //----------------------------------------------------------------------------
341 //
342 //  SECTOR STRUCTURE
343 //
344 static sector_t sv_dummy_sector;
345 
346 #define SV_F_BASE  sv_dummy_sector
347 
348 static savefield_t sv_fields_sector[] =
349 {
350 	SF(floor, "floor", 1, SVT_STRUCT("surface_t"), SR_LevelGetSurface, SR_LevelPutSurface),
351 	SF(ceil, "ceil", 1, SVT_STRUCT("surface_t"), SR_LevelGetSurface, SR_LevelPutSurface),
352 	SF(f_h, "f_h", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
353 	SF(c_h, "c_h", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
354 
355 	SF(props, "props", 1, SVT_STRUCT("region_properties_t"), SR_SectorGetProps, SR_SectorPutProps),
356 	SF(p, "p", 1, SVT_STRING, SR_SectorGetPropRef, SR_SectorPutPropRef),
357 
358 	SF(exfloor_used, "exfloor_used", 1, SVT_INT, SR_GetInt, SR_PutInt),
359 	SF(control_floors, "control_floors", 1, SVT_INDEX("extrafloors"),
360 			SR_SectorGetEF, SR_SectorPutEF),
361 	SF(sound_player, "sound_player", 1, SVT_INT, SR_GetInt, SR_PutInt),
362 
363 	SF(bottom_ef, "bottom_ef", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
364 	SF(top_ef, "top_ef", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
365 	SF(bottom_liq, "bottom_liq", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
366 	SF(top_liq, "top_liq", 1, SVT_INDEX("extrafloors"), SR_SectorGetEF, SR_SectorPutEF),
367 
368 	// NOT HERE:
369 	//   - floor_move, ceil_move: can be regenerated
370 	//   - (many): values remaining from level load are OK
371 	//   - soundtraversed & validcount: temp values, don't need saving
372 
373 	SVFIELD_END
374 };
375 
376 savestruct_t sv_struct_sector =
377 {
378 	NULL,              // link in list
379 	"sector_t",        // structure name
380 	"sect",            // start marker
381 	sv_fields_sector,  // field descriptions
382 	SVDUMMY,           // dummy base
383 	true,              // define_me
384 	NULL               // pointer to known struct
385 };
386 
387 #undef SV_F_BASE
388 
389 savearray_t sv_array_sector =
390 {
391 	NULL,               // link in list
392 	"sectors",          // array name
393 	&sv_struct_sector,  // array type
394 	true,               // define_me
395 	true,               // allow_hub
396 
397 	SV_SectorCountElems,     // count routine
398 	SV_SectorGetElem,        // index routine
399 	SV_SectorCreateElems,    // creation routine
400 	SV_SectorFinaliseElems,  // finalisation routine
401 
402 	NULL,     // pointer to known array
403 	0         // loaded size
404 };
405 
406 
407 //----------------------------------------------------------------------------
408 
SV_SideCountElems(void)409 int SV_SideCountElems(void)
410 {
411 	return numsides;
412 }
413 
SV_SideGetElem(int index)414 void *SV_SideGetElem(int index)
415 {
416 	if (index < 0 || index >= numsides)
417 	{
418 		I_Warning("LOADGAME: Invalid Side: %d\n", index);
419 		index = 0;
420 	}
421 
422 	return sides + index;
423 }
424 
SV_SideFindElem(side_t * elem)425 int SV_SideFindElem(side_t *elem)
426 {
427 	SYS_ASSERT(sides <= elem && elem < (sides + numsides));
428 
429 	return elem - sides;
430 }
431 
SV_SideCreateElems(int num_elems)432 void SV_SideCreateElems(int num_elems)
433 {
434 	/* nothing much to do -- sides created from level load, and defaults
435 	* are initialised there.
436 	*/
437 
438 	if (num_elems != numsides)
439 		I_Error("LOADGAME: SIDE MISMATCH !  (%d != %d)\n",
440 		num_elems, numsides);
441 }
442 
SV_SideFinaliseElems(void)443 void SV_SideFinaliseElems(void)
444 {
445 	/* nothing to do */
446 }
447 
448 
449 //----------------------------------------------------------------------------
450 
451 extern std::list<line_t *> active_line_anims;
452 extern std::vector<slider_move_t *> active_sliders;
453 
SV_LineCountElems(void)454 int SV_LineCountElems(void)
455 {
456 	return numlines;
457 }
458 
SV_LineGetElem(int index)459 void *SV_LineGetElem(int index)
460 {
461 	if (index < 0 || index >= numlines)
462 	{
463 		I_Warning("LOADGAME: Invalid Line: %d\n", index);
464 		index = 0;
465 	}
466 
467 	return lines + index;
468 }
469 
SV_LineFindElem(line_t * elem)470 int SV_LineFindElem(line_t *elem)
471 {
472 	SYS_ASSERT(lines <= elem && elem < (lines + numlines));
473 
474 	return elem - lines;
475 }
476 
SV_LineCreateElems(int num_elems)477 void SV_LineCreateElems(int num_elems)
478 {
479 	// nothing much to do -- lines are created from level load,
480 	// and defaults are initialised there.
481 
482 	if (num_elems != numlines)
483 		I_Error("LOADGAME: LINE MISMATCH !  (%d != %d)\n",
484 			num_elems, numlines);
485 
486 	// clear animate list
487 	active_line_anims.clear();
488 }
489 
490 //
491 // NOTE: line gaps done in Sector finaliser.
492 //
SV_LineFinaliseElems(void)493 void SV_LineFinaliseElems(void)
494 {
495 	for (int i = 0; i < numlines; i++)
496 	{
497 		line_t *ld = lines + i;
498 		side_t *s1, *s2;
499 
500 		s1 = ld->side[0];
501 		s2 = ld->side[1];
502 
503 		// check for animation
504 		if (s1 && (s1->top.scroll.x || s1->top.scroll.y ||
505 			s1->middle.scroll.x || s1->middle.scroll.y ||
506 			s1->bottom.scroll.x || s1->bottom.scroll.y))
507 		{
508 			P_AddSpecialLine(ld);
509 		}
510 
511 		if (s2 && (s2->top.scroll.x || s2->top.scroll.y ||
512 			s2->middle.scroll.x || s2->middle.scroll.y ||
513 			s2->bottom.scroll.x || s2->bottom.scroll.y))
514 		{
515 			P_AddSpecialLine(ld);
516 		}
517 	}
518 
519 	// scan active parts, regenerate slider_move field
520 	std::vector<slider_move_t *>::iterator SMI;
521 
522 	for (SMI  = active_sliders.begin();
523 		 SMI != active_sliders.end();
524 		 SMI++)
525 	{
526 		SYS_ASSERT((*SMI)->line);
527 
528 		(*SMI)->line->slider_move = (*SMI);
529 	}
530 }
531 
532 
533 //----------------------------------------------------------------------------
534 
SV_ExfloorCountElems(void)535 int SV_ExfloorCountElems(void)
536 {
537 	return numextrafloors;
538 }
539 
SV_ExfloorGetElem(int index)540 void *SV_ExfloorGetElem(int index)
541 {
542 	if (index < 0 || index >= numextrafloors)
543 	{
544 		I_Warning("LOADGAME: Invalid Extrafloor: %d\n", index);
545 		index = 0;
546 	}
547 
548 	return extrafloors + index;
549 }
550 
SV_ExfloorFindElem(extrafloor_t * elem)551 int SV_ExfloorFindElem(extrafloor_t *elem)
552 {
553 	SYS_ASSERT(extrafloors <= elem && elem < (extrafloors + numextrafloors));
554 
555 	return elem - extrafloors;
556 }
557 
SV_ExfloorCreateElems(int num_elems)558 void SV_ExfloorCreateElems(int num_elems)
559 {
560 	/* nothing much to do -- extrafloors are created from level load, and
561 	* defaults are initialised there.
562 	*/
563 
564 	if (num_elems != numextrafloors)
565 		I_Error("LOADGAME: Extrafloor MISMATCH !  (%d != %d)\n",
566 		num_elems, numextrafloors);
567 }
568 
SV_ExfloorFinaliseElems(void)569 void SV_ExfloorFinaliseElems(void)
570 {
571 	int i;
572 
573 	// need to regenerate the ef_info fields
574 	for (i=0; i < numextrafloors; i++)
575 	{
576 		extrafloor_t *ef = extrafloors + i;
577 
578 		// skip unused extrafloors
579 		if (ef->ef_line == NULL)
580 			continue;
581 
582 		if (!ef->ef_line->special ||
583 			!(ef->ef_line->special->ef.type & EXFL_Present))
584 		{
585 			I_Warning("LOADGAME: Missing Extrafloor Special !\n");
586 			ef->ef_info = &linetypes.Lookup(0)->ef;
587 			continue;
588 		}
589 
590 		ef->ef_info = &ef->ef_line->special->ef;
591 	}
592 }
593 
594 
595 //----------------------------------------------------------------------------
596 
597 extern std::list<sector_t *> active_sector_anims;
598 extern std::vector<plane_move_t *>  active_planes;
599 
SV_SectorCountElems(void)600 int SV_SectorCountElems(void)
601 {
602 	return numsectors;
603 }
604 
SV_SectorGetElem(int index)605 void *SV_SectorGetElem(int index)
606 {
607 	if (index < 0 || index >= numsectors)
608 	{
609 		I_Warning("LOADGAME: Invalid Sector: %d\n", index);
610 		index = 0;
611 	}
612 
613 	return sectors + index;
614 }
615 
SV_SectorFindElem(sector_t * elem)616 int SV_SectorFindElem(sector_t *elem)
617 {
618 	SYS_ASSERT(sectors <= elem && elem < (sectors + numsectors));
619 
620 	return elem - sectors;
621 }
622 
SV_SectorCreateElems(int num_elems)623 void SV_SectorCreateElems(int num_elems)
624 {
625 	// nothing much to do -- sectors are created from level load,
626 	// and defaults are initialised there.
627 
628 	if (num_elems != numsectors)
629 		I_Error("LOADGAME: SECTOR MISMATCH !  (%d != %d)\n",
630 			num_elems, numsectors);
631 
632 	// clear animate list
633 	active_sector_anims.clear();
634 }
635 
SV_SectorFinaliseElems(void)636 void SV_SectorFinaliseElems(void)
637 {
638 	for (int i = 0; i < numsectors; i++)
639 	{
640 		sector_t *sec = sectors + i;
641 
642 		P_RecomputeGapsAroundSector(sec);
643 ///---	P_RecomputeTilesInSector(sec);
644 		P_FloodExtraFloors(sec);
645 
646 		// check for animation
647 		if (sec->floor.scroll.x || sec->floor.scroll.y ||
648 			sec->ceil.scroll.x  || sec->ceil.scroll.y)
649 		{
650 			P_AddSpecialSector(sec);
651 		}
652 	}
653 
654 	// scan active parts, regenerate floor_move and ceil_move
655 	std::vector<plane_move_t *>::iterator PMI;
656 
657 	for (PMI  = active_planes.begin();
658 		 PMI != active_planes.end();
659 		 PMI++)
660 	{
661 		plane_move_t * pmov = *PMI;
662 
663 		SYS_ASSERT(pmov->sector);
664 
665 		if (pmov->is_ceiling)
666 			pmov->sector->ceil_move = pmov;
667 		else
668 			pmov->sector->floor_move = pmov;
669 	}
670 }
671 
672 
673 //----------------------------------------------------------------------------
674 
SR_LevelGetSurface(void * storage,int index,void * extra)675 bool SR_LevelGetSurface(void *storage, int index, void *extra)
676 {
677 	surface_t *dest = (surface_t *)storage + index;
678 
679 	if (! sv_struct_surface.counterpart)
680 		return true;
681 
682 	return SV_LoadStruct(dest, sv_struct_surface.counterpart);
683 }
684 
SR_LevelPutSurface(void * storage,int index,void * extra)685 void SR_LevelPutSurface(void *storage, int index, void *extra)
686 {
687 	surface_t *src = (surface_t *)storage + index;
688 
689 	SV_SaveStruct(src, &sv_struct_surface);
690 }
691 
692 
SR_LevelGetSurfPtr(void * storage,int index,void * extra)693 bool SR_LevelGetSurfPtr(void *storage, int index, void *extra)
694 {
695 	surface_t ** dest = (surface_t **)storage + index;
696 
697 	const char *str;
698 	int num;
699 
700 	str = SV_GetString();
701 
702 	if (! str)
703 	{
704 		(*dest) = NULL;
705 		return true;
706 	}
707 
708 	if (str[1] != ':')
709 		I_Error("SR_LevelGetSurfPtr: invalid surface string `%s'\n", str);
710 
711 	num = strtol(str+2, NULL, 0);
712 
713 	if (num < 0 || num >= numsectors)
714 	{
715 		I_Warning("SR_LevelGetSurfPtr: bad sector ref %d\n", num);
716 		num = 0;
717 	}
718 
719 	if (str[0] == 'F')
720 		(*dest) = &sectors[num].floor;
721 	else if (str[0] == 'C')
722 		(*dest) = &sectors[num].ceil;
723 	else
724 		I_Error("SR_LevelGetSurfPtr: invalid surface plane `%s'\n", str);
725 
726 	SV_FreeString(str);
727 	return true;
728 }
729 
730 //
731 // Format of the string:
732 //
733 //    <floor/ceil>  `:'  <sector num>
734 //
735 // The first character is `F' for the floor surface of the sector,
736 // otherwise `C' for its ceiling.
737 //
SR_LevelPutSurfPtr(void * storage,int index,void * extra)738 void SR_LevelPutSurfPtr(void *storage, int index, void *extra)
739 {
740 	surface_t *src = ((surface_t **)storage)[index];
741 
742 	char buffer[64];
743 	int i;
744 
745 	if (! src)
746 	{
747 		SV_PutString(NULL);
748 		return;
749 	}
750 
751 	// not optimal, but safe
752 	for (i=0; i < numsectors; i++)
753 	{
754 		if (src == &sectors[i].floor)
755 		{
756 			sprintf(buffer, "F:%d", i);
757 			SV_PutString(buffer);
758 			return;
759 		}
760 		else if (src == &sectors[i].ceil)
761 		{
762 			sprintf(buffer, "C:%d", i);
763 			SV_PutString(buffer);
764 			return;
765 		}
766 	}
767 
768 	I_Warning("SR_LevelPutSurfPtr: surface %p not found !\n", src);
769 	SV_PutString("F:0");
770 }
771 
772 
SR_LevelGetImage(void * storage,int index,void * extra)773 bool SR_LevelGetImage(void *storage, int index, void *extra)
774 {
775 	const image_c ** dest = (const image_c **)storage + index;
776 	const char *str;
777 
778 	str = SV_GetString();
779 
780 	if (! str)
781 	{
782 		(*dest) = NULL;
783 		return true;
784 	}
785 
786 	if (str[1] != ':')
787 		I_Warning("SR_LevelGetImage: invalid image string `%s'\n", str);
788 
789 	(*dest) = W_ImageParseSaveString(str[0], str + 2);
790 
791 	SV_FreeString(str);
792 	return true;
793 }
794 
795 //
796 // Format of the string is:
797 //
798 //   <type char>  `:'  <name>
799 //
800 // The type character is `F' for flat, `T' for texture, etc etc..
801 // Also `*' is valid and means that type is not important.  Some
802 // examples: "F:FLAT10" and "T:STARTAN3".
803 //
SR_LevelPutImage(void * storage,int index,void * extra)804 void SR_LevelPutImage(void *storage, int index, void *extra)
805 {
806 	const image_c *src = ((const image_c **)storage)[index];
807 
808 	char buffer[64];
809 
810 	if (! src)
811 	{
812 		SV_PutString(NULL);
813 		return;
814 	}
815 
816 	W_ImageMakeSaveString(src, buffer, buffer + 2);
817 	buffer[1] = ':';
818 
819 	SV_PutString(buffer);
820 }
821 
822 
SR_LevelGetColmap(void * storage,int index,void * extra)823 bool SR_LevelGetColmap(void *storage, int index, void *extra)
824 {
825 	const colourmap_c ** dest = (const colourmap_c **)storage + index;
826 	const char *str;
827 
828 	str = SV_GetString();
829 
830 	if (str)
831 		(*dest) = colourmaps.Lookup(str);
832 	else
833 		(*dest) = NULL;
834 
835 	// -AJA- 2008/03/15: backwards compatibility
836 	if (*dest && stricmp((*dest)->name.c_str(), "NORMAL") == 0)
837 		*dest = NULL;
838 
839 	SV_FreeString(str);
840 	return true;
841 }
842 
843 //
844 // The string is the name of the colourmap.
845 //
SR_LevelPutColmap(void * storage,int index,void * extra)846 void SR_LevelPutColmap(void *storage, int index, void *extra)
847 {
848 	const colourmap_c *src = ((const colourmap_c **)storage)[index];
849 
850 	if (src)
851 		SV_PutString(src->name.c_str());
852 	else
853 		SV_PutString(NULL);
854 }
855 
856 
SR_LineGetSpecial(void * storage,int index,void * extra)857 bool SR_LineGetSpecial(void *storage, int index, void *extra)
858 {
859 	const linetype_c ** dest = (const linetype_c **)storage + index;
860 	const char *str;
861 
862 	str = SV_GetString();
863 
864 	if (! str)
865 	{
866 		(*dest) = NULL;
867 		return true;
868 	}
869 
870 	if (str[0] != ':')
871 		I_Error("SR_LineGetSpecial: invalid special `%s'\n", str);
872 
873 	(*dest) = P_LookupLineType(strtol(str+1, NULL, 0));
874 
875 	SV_FreeString(str);
876 	return true;
877 }
878 
879 //
880 // Format of the string will usually be a colon followed by the
881 // linedef number (e.g. ":123").  Alternatively it can be the ddf
882 // name, but this shouldn't be needed currently (reserved for future
883 // use).
884 //
SR_LinePutSpecial(void * storage,int index,void * extra)885 void SR_LinePutSpecial(void *storage, int index, void *extra)
886 {
887 	const linetype_c *src = ((const linetype_c **)storage)[index];
888 
889 	if (! src)
890 	{
891 		SV_PutString(NULL);
892 		return;
893 	}
894 
895 	std::string s = epi::STR_Format(":%d", src->number);
896 
897 	SV_PutString(s.c_str());
898 }
899 
900 
SR_SectorGetSpecial(void * storage,int index,void * extra)901 bool SR_SectorGetSpecial(void *storage, int index, void *extra)
902 {
903 	const sectortype_c ** dest = (const sectortype_c **)storage + index;
904 	const char *str;
905 
906 	str = SV_GetString();
907 
908 	if (! str)
909 	{
910 		(*dest) = NULL;
911 		return true;
912 	}
913 
914 	if (str[0] != ':')
915 		I_Error("SR_SectorGetSpecial: invalid special `%s'\n", str);
916 
917 	(*dest) = P_LookupSectorType(strtol(str+1, NULL, 0));
918 
919 	SV_FreeString(str);
920 	return true;
921 }
922 
923 //
924 // Format of the string will usually be a colon followed by the
925 // sector number (e.g. ":123").  Alternatively it can be the ddf
926 // name, but this shouldn't be needed currently (reserved for future
927 // use).
928 //
SR_SectorPutSpecial(void * storage,int index,void * extra)929 void SR_SectorPutSpecial(void *storage, int index, void *extra)
930 {
931 	const sectortype_c *src = ((const sectortype_c **)storage)[index];
932 
933 	if (! src)
934 	{
935 		SV_PutString(NULL);
936 		return;
937 	}
938 
939 	std::string s = epi::STR_Format(":%d", src->number);
940 
941 	SV_PutString(s.c_str());
942 }
943 
944 
945 //----------------------------------------------------------------------------
946 
SR_SectorGetProps(void * storage,int index,void * extra)947 bool SR_SectorGetProps(void *storage, int index, void *extra)
948 {
949 	region_properties_t *dest = (region_properties_t *)storage + index;
950 
951 	if (! sv_struct_regprops.counterpart)
952 		return true;
953 
954 	return SV_LoadStruct(dest, sv_struct_regprops.counterpart);
955 }
956 
SR_SectorPutProps(void * storage,int index,void * extra)957 void SR_SectorPutProps(void *storage, int index, void *extra)
958 {
959 	region_properties_t *src = (region_properties_t *)storage + index;
960 
961 	SV_SaveStruct(src, &sv_struct_regprops);
962 }
963 
964 
SR_SectorGetPropRef(void * storage,int index,void * extra)965 bool SR_SectorGetPropRef(void *storage, int index, void *extra)
966 {
967 	region_properties_t ** dest = (region_properties_t **)storage + index;
968 
969 	const char *str;
970 	int num;
971 
972 	str = SV_GetString();
973 
974 	if (! str)
975 	{
976 		(*dest) = NULL;
977 		return true;
978 	}
979 
980 	num = strtol(str, NULL, 0);
981 
982 	if (num < 0 || num >= numsectors)
983 	{
984 		I_Warning("SR_SectorGetPropRef: bad sector ref %d\n", num);
985 		num = 0;
986 	}
987 
988 	(*dest) = &sectors[num].props;
989 
990 	SV_FreeString(str);
991 	return true;
992 }
993 
994 //
995 // Format of the string is just the sector number containing the
996 // properties.
997 //
SR_SectorPutPropRef(void * storage,int index,void * extra)998 void SR_SectorPutPropRef(void *storage, int index, void *extra)
999 {
1000 	region_properties_t *src = ((region_properties_t **)storage)[index];
1001 
1002 	char buffer[64];
1003 	int i;
1004 
1005 	if (! src)
1006 	{
1007 		SV_PutString(NULL);
1008 		return;
1009 	}
1010 
1011 	// not optimal, but safe
1012 	for (i=0; i < numsectors; i++)
1013 	{
1014 		if (&sectors[i].props == src)
1015 			break;
1016 	}
1017 
1018 	if (i >= numsectors)
1019 	{
1020 		I_Warning("SR_SectorPutPropRef: properties %p not found !\n", src);
1021 		i = 0;
1022 	}
1023 
1024 	sprintf(buffer, "%d", i);
1025 	SV_PutString(buffer);
1026 }
1027 
1028 
SR_LineGetLine(void * storage,int index,void * extra)1029 bool SR_LineGetLine(void *storage, int index, void *extra)
1030 {
1031 	line_t ** dest = (line_t **)storage + index;
1032 
1033 	int swizzle = SV_GetInt();
1034 
1035 	*dest = (line_t*)((swizzle == 0) ? NULL : SV_LineGetElem(swizzle - 1));
1036 	return true;
1037 }
1038 
SR_LinePutLine(void * storage,int index,void * extra)1039 void SR_LinePutLine(void *storage, int index, void *extra)
1040 {
1041 	line_t *elem = ((line_t **)storage)[index];
1042 
1043 	int swizzle = (elem == NULL) ? 0 : SV_LineFindElem(elem) + 1;
1044 
1045 	SV_PutInt(swizzle);
1046 }
1047 
1048 
SR_SectorGetSector(void * storage,int index,void * extra)1049 bool SR_SectorGetSector(void *storage, int index, void *extra)
1050 {
1051 	sector_t ** dest = (sector_t **)storage + index;
1052 
1053 	int swizzle = SV_GetInt();
1054 
1055 	*dest = (sector_t*)((swizzle == 0) ? NULL : SV_SectorGetElem(swizzle - 1));
1056 	return true;
1057 }
1058 
SR_SectorPutSector(void * storage,int index,void * extra)1059 void SR_SectorPutSector(void *storage, int index, void *extra)
1060 {
1061 	sector_t *elem = ((sector_t **)storage)[index];
1062 
1063 	int swizzle = (elem == NULL) ? 0 : SV_SectorFindElem(elem) + 1;
1064 
1065 	SV_PutInt(swizzle);
1066 }
1067 
SR_SectorGetEF(void * storage,int index,void * extra)1068 bool SR_SectorGetEF(void *storage, int index, void *extra)
1069 {
1070 	extrafloor_t ** dest = (extrafloor_t **)storage + index;
1071 
1072 	int swizzle = SV_GetInt();
1073 
1074 	*dest = (extrafloor_t*)((swizzle == 0) ? NULL : SV_ExfloorGetElem(swizzle - 1));
1075 	return true;
1076 }
1077 
SR_SectorPutEF(void * storage,int index,void * extra)1078 void SR_SectorPutEF(void *storage, int index, void *extra)
1079 {
1080 	extrafloor_t *elem = ((extrafloor_t **)storage)[index];
1081 
1082 	int swizzle = (elem == NULL) ? 0 : SV_ExfloorFindElem(elem) + 1;
1083 
1084 	SV_PutInt(swizzle);
1085 }
1086 
1087 
1088 //--- editor settings ---
1089 // vi:ts=4:sw=4:noexpandtab
1090