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) = §ors[num].floor;
721 else if (str[0] == 'C')
722 (*dest) = §ors[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 == §ors[i].floor)
755 {
756 sprintf(buffer, "F:%d", i);
757 SV_PutString(buffer);
758 return;
759 }
760 else if (src == §ors[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) = §ors[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 (§ors[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