1 //----------------------------------------------------------------------------
2 // EDGE New SaveGame Handling (Miscellaneous)
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 // light_t [LITE]
24 // button_t [BUTN]
25 // rad_trigger_t [TRIG]
26 // drawtip_t [DTIP]
27 //
28 // plane_move_t [PMOV]
29 // slider_move_t [SMOV]
30 //
31 // TODO HERE:
32 // + Fix donuts.
33 // - Button off_sound field.
34 //
35
36 #include "i_defs.h"
37
38 #include "epi/str_format.h"
39
40 #include "rad_trig.h"
41 #include "sv_chunk.h"
42 #include "sv_main.h"
43 #include "z_zone.h"
44
45
46 #undef SF
47 #define SF SVFIELD
48
49
50 // forward decls.
51 int SV_ButtonCountElems(void);
52 int SV_ButtonFindElem(button_t *elem);
53 void * SV_ButtonGetElem(int index);
54 void SV_ButtonCreateElems(int num_elems);
55 void SV_ButtonFinaliseElems(void);
56
57 int SV_LightCountElems(void);
58 int SV_LightFindElem(light_t *elem);
59 void * SV_LightGetElem(int index);
60 void SV_LightCreateElems(int num_elems);
61 void SV_LightFinaliseElems(void);
62
63 int SV_TriggerCountElems(void);
64 int SV_TriggerFindElem(rad_trigger_t *elem);
65 void * SV_TriggerGetElem(int index);
66 void SV_TriggerCreateElems(int num_elems);
67 void SV_TriggerFinaliseElems(void);
68
69 int SV_TipCountElems(void);
70 int SV_TipFindElem(drawtip_t *elem);
71 void * SV_TipGetElem(int index);
72 void SV_TipCreateElems(int num_elems);
73 void SV_TipFinaliseElems(void);
74
75 int SV_PlaneMoveCountElems(void);
76 int SV_PlaneMoveFindElem(plane_move_t *elem);
77 void * SV_PlaneMoveGetElem(int index);
78 void SV_PlaneMoveCreateElems(int num_elems);
79 void SV_PlaneMoveFinaliseElems(void);
80
81 int SV_SliderMoveCountElems(void);
82 int SV_SliderMoveFindElem(plane_move_t *elem);
83 void * SV_SliderMoveGetElem(int index);
84 void SV_SliderMoveCreateElems(int num_elems);
85 void SV_SliderMoveFinaliseElems(void);
86
87
88 bool SR_LightGetType(void *storage, int index, void *extra);
89 void SR_LightPutType(void *storage, int index, void *extra);
90
91 bool SR_TriggerGetScript(void *storage, int index, void *extra);
92 void SR_TriggerPutScript(void *storage, int index, void *extra);
93
94 bool SR_TriggerGetState(void *storage, int index, void *extra);
95 void SR_TriggerPutState(void *storage, int index, void *extra);
96
97 bool SR_TipGetString(void *storage, int index, void *extra);
98 void SR_TipPutString(void *storage, int index, void *extra);
99
100 bool SR_PlaneMoveGetType(void *storage, int index, void *extra);
101 void SR_PlaneMovePutType(void *storage, int index, void *extra);
102
103 bool SR_SliderGetInfo(void *storage, int index, void *extra);
104 void SR_SliderPutInfo(void *storage, int index, void *extra);
105
106
107 //----------------------------------------------------------------------------
108 //
109 // BUTTON STRUCTURE
110 //
111 static button_t sv_dummy_button;
112
113 #define SV_F_BASE sv_dummy_button
114
115 static savefield_t sv_fields_button[] =
116 {
117 SF(line, "line", 1, SVT_INDEX("lines"),
118 SR_LineGetLine, SR_LinePutLine),
119 SF(where, "where", 1, SVT_ENUM, SR_GetEnum, SR_PutEnum),
120 SF(bimage, "bimage", 1, SVT_STRING, SR_LevelGetImage, SR_LevelPutImage),
121 SF(btimer, "btimer", 1, SVT_INT, SR_GetInt, SR_PutInt),
122
123 // FIXME: off_sound
124
125 SVFIELD_END
126 };
127
128 savestruct_t sv_struct_button =
129 {
130 NULL, // link in list
131 "button_t", // structure name
132 "butn", // start marker
133 sv_fields_button, // field descriptions
134 SVDUMMY, // dummy base
135 true, // define_me
136 NULL // pointer to known struct
137 };
138
139 #undef SV_F_BASE
140
141 savearray_t sv_array_button =
142 {
143 NULL, // link in list
144 "buttonlist", // array name
145 &sv_struct_button, // array type
146 true, // define_me
147 true, // allow_hub
148
149 SV_ButtonCountElems, // count routine
150 SV_ButtonGetElem, // index routine
151 SV_ButtonCreateElems, // creation routine
152 SV_ButtonFinaliseElems, // finalisation routine
153
154 NULL, // pointer to known array
155 0 // loaded size
156 };
157
158
159 //----------------------------------------------------------------------------
160 //
161 // LIGHT STRUCTURE
162 //
163 static light_t sv_dummy_light;
164
165 #define SV_F_BASE sv_dummy_light
166
167 static savefield_t sv_fields_light[] =
168 {
169 SF(type, "type", 1, SVT_STRING, SR_LightGetType, SR_LightPutType),
170 SF(sector, "sector", 1, SVT_INDEX("sectors"),
171 SR_SectorGetSector, SR_SectorPutSector),
172 SF(count, "count", 1, SVT_INT, SR_GetInt, SR_PutInt),
173 SF(minlight, "minlight", 1, SVT_INT, SR_GetInt, SR_PutInt),
174 SF(maxlight, "maxlight", 1, SVT_INT, SR_GetInt, SR_PutInt),
175 SF(direction, "direction", 1, SVT_INT, SR_GetInt, SR_PutInt),
176 SF(fade_count, "fade_count", 1, SVT_INT, SR_GetInt, SR_PutInt),
177
178 // NOT HERE:
179 // - prev & next: automatically regenerated
180
181 SVFIELD_END
182 };
183
184 savestruct_t sv_struct_light =
185 {
186 NULL, // link in list
187 "light_t", // structure name
188 "lite", // start marker
189 sv_fields_light, // field descriptions
190 SVDUMMY, // dummy base
191 true, // define_me
192 NULL // pointer to known struct
193 };
194
195 #undef SV_F_BASE
196
197 savearray_t sv_array_light =
198 {
199 NULL, // link in list
200 "lights", // array name
201 &sv_struct_light, // array type
202 true, // define_me
203 true, // allow_hub
204
205 SV_LightCountElems, // count routine
206 SV_LightGetElem, // index routine
207 SV_LightCreateElems, // creation routine
208 SV_LightFinaliseElems, // finalisation routine
209
210 NULL, // pointer to known array
211 0 // loaded size
212 };
213
214
215 //----------------------------------------------------------------------------
216 //
217 // TRIGGER STRUCTURE
218 //
219 static rad_trigger_t sv_dummy_trigger;
220
221 #define SV_F_BASE sv_dummy_trigger
222
223 static savefield_t sv_fields_trigger[] =
224 {
225 SF(info, "info", 1, SVT_STRING,
226 SR_TriggerGetScript, SR_TriggerPutScript),
227
228 SF(disabled, "disabled", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
229 SF(activated, "activated", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
230 SF(acti_players, "acti_players", 1, SVT_INT, SR_GetInt, SR_PutInt),
231 SF(repeats_left, "repeats_left", 1, SVT_INT, SR_GetInt, SR_PutInt),
232 SF(repeat_delay, "repeat_delay", 1, SVT_INT, SR_GetInt, SR_PutInt),
233
234 SF(state, "state", 1, SVT_INT, SR_TriggerGetState, SR_TriggerPutState),
235 SF(wait_tics, "wait_tics", 1, SVT_INT, SR_GetInt, SR_PutInt),
236 SF(tip_slot, "tip_slot", 1, SVT_INT, SR_GetInt, SR_PutInt),
237 SF(menu_style_name, "menu_style_name", 1, SVT_STRING,
238 SR_TipGetString, SR_TipPutString),
239 SF(menu_result, "menu_result", 1, SVT_INT, SR_GetInt, SR_PutInt),
240 SF(wud_tag, "wud_tag", 1, SVT_INT, SR_GetInt, SR_PutInt),
241 SF(wud_count, "wud_count", 1, SVT_INT, SR_GetInt, SR_PutInt),
242
243 // NOT HERE
244 // - next & prev: can be regenerated.
245 // - tag_next & tag_prev: ditto
246 // - sound: can be recomputed.
247 // - last_con_message: doesn't matter.
248
249 SVFIELD_END
250 };
251
252 savestruct_t sv_struct_trigger =
253 {
254 NULL, // link in list
255 "rad_trigger_t", // structure name
256 "trig", // start marker
257 sv_fields_trigger, // field descriptions
258 SVDUMMY, // dummy base
259 true, // define_me
260 NULL // pointer to known struct
261 };
262
263 #undef SV_F_BASE
264
265 savearray_t sv_array_trigger =
266 {
267 NULL, // link in list
268 "r_triggers", // array name
269 &sv_struct_trigger, // array type
270 true, // define_me
271 true, // allow_hub
272
273 SV_TriggerCountElems, // count routine
274 SV_TriggerGetElem, // index routine
275 SV_TriggerCreateElems, // creation routine
276 SV_TriggerFinaliseElems, // finalisation routine
277
278 NULL, // pointer to known array
279 0 // loaded size
280 };
281
282
283 //----------------------------------------------------------------------------
284 //
285 // DRAWTIP STRUCTURE
286 //
287 static drawtip_t sv_dummy_drawtip;
288
289 #define SV_F_BASE sv_dummy_drawtip
290
291 static savefield_t sv_fields_drawtip[] =
292 {
293 // treating the `p' sub-struct here as if the fields were directly
294 // in drawtip_t.
295
296 SF(p.x_pos, "x_pos", 1, SVT_PERCENT, SR_GetPercent, SR_PutPercent),
297 SF(p.y_pos, "y_pos", 1, SVT_PERCENT, SR_GetPercent, SR_PutPercent),
298 SF(p.left_just, "left_just", 1, SVT_INT, SR_GetInt, SR_PutInt),
299 SF(p.translucency, "translucency", 1, SVT_PERCENT, SR_GetPercent, SR_PutPercent),
300
301 SF(delay, "delay", 1, SVT_INT, SR_GetInt, SR_PutInt),
302 SF(tip_text, "tip_text", 1, SVT_STRING, SR_TipGetString, SR_TipPutString),
303 SF(tip_graphic, "tip_graphic", 1, SVT_STRING, SR_LevelGetImage, SR_LevelPutImage),
304 SF(playsound, "playsound", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
305 SF(fade_time, "fade_time", 1, SVT_INT, SR_GetInt, SR_PutInt),
306 SF(fade_target, "fade_target", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
307 SF(color, "color", 1, SVT_INT, SR_GetInt, SR_PutInt),
308
309 // NOT HERE:
310 // p.slot_num, p.time: not used withing drawtip_t
311 // dirty: this is set in the finalizer
312 // hu_*: these are regenerated on next display
313 // p.color_name: only serves to generate 'color' field
314
315 SVFIELD_END
316 };
317
318 savestruct_t sv_struct_drawtip =
319 {
320 NULL, // link in list
321 "drawtip_t", // structure name
322 "dtip", // start marker
323 sv_fields_drawtip, // field descriptions
324 SVDUMMY, // dummy base
325 true, // define_me
326 NULL // pointer to known struct
327 };
328
329 #undef SV_F_BASE
330
331 savearray_t sv_array_drawtip =
332 {
333 NULL, // link in list
334 "tip_slots", // array name
335 &sv_struct_drawtip, // array type
336 true, // define_me
337 true, // allow_hub
338
339 SV_TipCountElems, // count routine
340 SV_TipGetElem, // index routine
341 SV_TipCreateElems, // creation routine
342 SV_TipFinaliseElems, // finalisation routine
343
344 NULL, // pointer to known array
345 0 // loaded size
346 };
347
348
349 //----------------------------------------------------------------------------
350 //
351 // PLANEMOVE STRUCTURE
352 //
353 static plane_move_t sv_dummy_plane_move;
354
355 #define SV_F_BASE sv_dummy_plane_move
356
357 static savefield_t sv_fields_plane_move[] =
358 {
359 SF(type, "type", 1, SVT_STRING, SR_PlaneMoveGetType, SR_PlaneMovePutType),
360 SF(sector, "sector", 1, SVT_INDEX("sectors"),
361 SR_SectorGetSector, SR_SectorPutSector),
362
363 SF(is_ceiling, "is_ceiling", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
364 SF(is_elevator, "is_elevator", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
365 SF(startheight, "startheight", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
366 SF(destheight, "destheight", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
367 SF(elev_height, "elevheight", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
368 SF(speed, "speed", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
369 SF(crush, "crush", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
370
371 SF(direction, "direction", 1, SVT_INT, SR_GetInt, SR_PutInt),
372 SF(olddirection, "olddirection", 1, SVT_INT, SR_GetInt, SR_PutInt),
373 SF(tag, "tag", 1, SVT_INT, SR_GetInt, SR_PutInt),
374 SF(waited, "waited", 1, SVT_INT, SR_GetInt, SR_PutInt),
375 SF(sfxstarted, "sfxstarted", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
376
377 SF(newspecial, "newspecial", 1, SVT_INT, SR_GetInt, SR_PutInt),
378 SF(new_image, "new_image", 1, SVT_STRING, SR_LevelGetImage, SR_LevelPutImage),
379
380 SVFIELD_END
381 };
382
383 savestruct_t sv_struct_plane_move =
384 {
385 NULL, // link in list
386 "plane_move_t", // structure name
387 "pmov", // start marker
388 sv_fields_plane_move, // field descriptions
389 SVDUMMY, // dummy base
390 true, // define_me
391 NULL // pointer to known struct
392 };
393
394 #undef SV_F_BASE
395
396 savearray_t sv_array_plane_move =
397 {
398 NULL, // link in list
399 "plane_movers", // array name (virtual list)
400 &sv_struct_plane_move, // array type
401 true, // define_me
402 true, // allow_hub
403
404 SV_PlaneMoveCountElems, // count routine
405 SV_PlaneMoveGetElem, // index routine
406 SV_PlaneMoveCreateElems, // creation routine
407 SV_PlaneMoveFinaliseElems, // finalisation routine
408
409 NULL, // pointer to known array
410 0 // loaded size
411 };
412
413
414 //----------------------------------------------------------------------------
415 //
416 // SLIDERMOVE STRUCTURE
417 //
418 static slider_move_t sv_dummy_slider_move;
419
420 #define SV_F_BASE sv_dummy_slider_move
421
422 static savefield_t sv_fields_slider_move[] =
423 {
424 SF(info, "info", 1, SVT_STRING, SR_SliderGetInfo, SR_SliderPutInfo),
425 SF(line, "line", 1, SVT_INDEX("lines"), SR_LineGetLine, SR_LinePutLine),
426
427 SF(opening, "opening", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
428 SF(target, "target", 1, SVT_FLOAT, SR_GetFloat, SR_PutFloat),
429
430 SF(direction, "direction", 1, SVT_INT, SR_GetInt, SR_PutInt),
431 SF(waited, "waited", 1, SVT_INT, SR_GetInt, SR_PutInt),
432
433 SF(sfxstarted, "sfxstarted", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
434 SF(final_open, "final_open", 1, SVT_BOOLEAN, SR_GetBoolean, SR_PutBoolean),
435
436 // NOT HERE:
437 // - line_len (can recreate)
438
439 SVFIELD_END
440 };
441
442 savestruct_t sv_struct_slider_move =
443 {
444 NULL, // link in list
445 "slider_move_t", // structure name
446 "pmov", // start marker
447 sv_fields_slider_move, // field descriptions
448 SVDUMMY, // dummy base
449 true, // define_me
450 NULL // pointer to known struct
451 };
452
453 #undef SV_F_BASE
454
455 savearray_t sv_array_slider_move =
456 {
457 NULL, // link in list
458 "active_sliders", // array name (virtual list)
459 &sv_struct_slider_move, // array type
460 true, // define_me
461 true, // allow_hub
462
463 SV_SliderMoveCountElems, // count routine
464 SV_SliderMoveGetElem, // index routine
465 SV_SliderMoveCreateElems, // creation routine
466 SV_SliderMoveFinaliseElems, // finalisation routine
467
468 NULL, // pointer to known array
469 0 // loaded size
470 };
471
472
473 //----------------------------------------------------------------------------
474
475 extern std::vector<button_t *> active_buttons;
476
SV_ButtonCountElems(void)477 int SV_ButtonCountElems(void)
478 {
479 // Note: also saves the unused button_ts (btimer == 0)
480 return (int)active_buttons.size();
481 }
482
SV_ButtonGetElem(int index)483 void *SV_ButtonGetElem(int index)
484 {
485 if (index < 0 || index >= (int)active_buttons.size())
486 {
487 I_Warning("LOADGAME: Invalid Button: %d\n", index);
488 index = 0;
489 }
490
491 return active_buttons[index];
492 }
493
SV_ButtonFindElem(button_t * elem)494 int SV_ButtonFindElem(button_t *elem)
495 {
496 int index = 0;
497
498 std::vector<button_t *>::iterator LI;
499
500 for (LI=active_buttons.begin(); LI != active_buttons.end() && (*LI) != elem; LI++)
501 index++;
502
503 if (LI == active_buttons.end())
504 I_Error("LOADGAME: No such LightPtr: %p\n", elem);
505
506 return index;
507 }
508
SV_ButtonCreateElems(int num_elems)509 void SV_ButtonCreateElems(int num_elems)
510 {
511 P_ClearButtons();
512
513 for (; num_elems > 0; num_elems--)
514 {
515 button_t *b = new button_t;
516
517 Z_Clear(b, button_t, 1);
518
519 active_buttons.push_back(b);
520 }
521 }
522
SV_ButtonFinaliseElems(void)523 void SV_ButtonFinaliseElems(void)
524 {
525 // nothing to do
526 }
527
528
529 //----------------------------------------------------------------------------
530
531 extern std::vector<light_t *> active_lights;
532
SV_LightCountElems(void)533 int SV_LightCountElems(void)
534 {
535 return (int)active_lights.size();
536 }
537
SV_LightGetElem(int index)538 void *SV_LightGetElem(int index)
539 {
540 if (index < 0 || index >= (int)active_lights.size())
541 I_Error("LOADGAME: Invalid Light: %d\n", index);
542
543 return active_lights[index];
544 }
545
SV_LightFindElem(light_t * elem)546 int SV_LightFindElem(light_t *elem)
547 {
548 int index = 0;
549
550 std::vector<light_t *>::iterator LI;
551
552 for (LI=active_lights.begin(); LI != active_lights.end() && (*LI) != elem; LI++)
553 index++;
554
555 if (LI == active_lights.end())
556 I_Error("LOADGAME: No such LightPtr: %p\n", elem);
557
558 return index;
559 }
560
SV_LightCreateElems(int num_elems)561 void SV_LightCreateElems(int num_elems)
562 {
563 P_DestroyAllLights();
564
565 for (; num_elems > 0; num_elems--)
566 {
567 light_t *cur = P_NewLight();
568
569 // initialise defaults
570 cur->type = §ortypes.Lookup(0)->l;
571 cur->sector = sectors + 0;
572 }
573 }
574
SV_LightFinaliseElems(void)575 void SV_LightFinaliseElems(void)
576 {
577 // nothing to do
578 }
579
580
581 //----------------------------------------------------------------------------
582
SV_TriggerCountElems(void)583 int SV_TriggerCountElems(void)
584 {
585 rad_trigger_t *cur;
586 int count;
587
588 for (cur=active_triggers, count=0; cur; cur=cur->next, count++)
589 { /* nothing here */ }
590
591 return count;
592 }
593
SV_TriggerGetElem(int index)594 void *SV_TriggerGetElem(int index)
595 {
596 rad_trigger_t *cur;
597
598 for (cur=active_triggers; cur && index > 0; cur=cur->next)
599 index--;
600
601 if (! cur)
602 I_Error("LOADGAME: Invalid Trigger: %d\n", index);
603
604 SYS_ASSERT(index == 0);
605 return cur;
606 }
607
SV_TriggerFindElem(rad_trigger_t * elem)608 int SV_TriggerFindElem(rad_trigger_t *elem)
609 {
610 rad_trigger_t *cur;
611 int index;
612
613 for (cur=active_triggers, index=0; cur && cur != elem; cur=cur->next)
614 index++;
615
616 if (! cur)
617 I_Error("LOADGAME: No such TriggerPtr: %p\n", elem);
618
619 return index;
620 }
621
SV_TriggerCreateElems(int num_elems)622 void SV_TriggerCreateElems(int num_elems)
623 {
624 RAD_ClearTriggers();
625
626 for (; num_elems > 0; num_elems--)
627 {
628 rad_trigger_t *cur = Z_New(rad_trigger_t, 1);
629
630 Z_Clear(cur, rad_trigger_t, 1);
631
632 // link it in
633 cur->next = active_triggers;
634 cur->prev = NULL;
635
636 if (active_triggers)
637 active_triggers->prev = cur;
638
639 active_triggers = cur;
640
641 // initialise defaults
642 cur->info = r_scripts;
643 cur->state = r_scripts ? r_scripts->first_state : NULL;
644 cur->disabled = true;
645 }
646 }
647
SV_TriggerFinaliseElems(void)648 void SV_TriggerFinaliseElems(void)
649 {
650 rad_trigger_t *cur;
651
652 for (cur=active_triggers; cur; cur=cur->next)
653 {
654 RAD_GroupTriggerTags(cur);
655 }
656 }
657
658
659 //----------------------------------------------------------------------------
660
SV_TipCountElems(void)661 int SV_TipCountElems(void)
662 {
663 return MAXTIPSLOT;
664 }
665
SV_TipGetElem(int index)666 void *SV_TipGetElem(int index)
667 {
668 if (index < 0 || index >= MAXTIPSLOT)
669 {
670 I_Warning("LOADGAME: Invalid Tip: %d\n", index);
671 index = MAXTIPSLOT-1;
672 }
673
674 return tip_slots + index;
675 }
676
SV_TipFindElem(drawtip_t * elem)677 int SV_TipFindElem(drawtip_t *elem)
678 {
679 SYS_ASSERT(tip_slots <= elem && elem < (tip_slots + MAXTIPSLOT));
680
681 return elem - tip_slots;
682 }
683
SV_TipCreateElems(int num_elems)684 void SV_TipCreateElems(int num_elems)
685 {
686 RAD_ResetTips();
687 }
688
SV_TipFinaliseElems(void)689 void SV_TipFinaliseElems(void)
690 {
691 int i;
692
693 // mark all active tip slots as dirty
694 for (i=0; i < MAXTIPSLOT; i++)
695 {
696 if (tip_slots[i].delay > 0)
697 tip_slots[i].dirty = true;
698 }
699 }
700
701
702 //----------------------------------------------------------------------------
703
704 extern std::vector<plane_move_t *> active_planes;
705
SV_PlaneMoveCountElems(void)706 int SV_PlaneMoveCountElems(void)
707 {
708 return (int)active_planes.size();
709 }
710
SV_PlaneMoveGetElem(int index)711 void *SV_PlaneMoveGetElem(int index)
712 {
713 // Note: the index value starts at 0.
714
715 if (index < 0 || index >= (int)active_planes.size())
716 I_Error("LOADGAME: Invalid PlaneMove: %d\n", index);
717
718 return active_planes[index];
719 }
720
SV_PlaneMoveFindElem(plane_move_t * elem)721 int SV_PlaneMoveFindElem(plane_move_t *elem)
722 {
723 // returns the index value (starts at 0).
724
725 int index = 0;
726
727 std::vector<plane_move_t *>::iterator PMI;
728
729 for (PMI = active_planes.begin();
730 PMI != active_planes.end() && (*PMI) != elem;
731 PMI++)
732 {
733 index++;
734 }
735
736 if (PMI == active_planes.end())
737 I_Error("LOADGAME: No such PlaneMove: %p\n", elem);
738
739 return index;
740 }
741
SV_PlaneMoveCreateElems(int num_elems)742 void SV_PlaneMoveCreateElems(int num_elems)
743 {
744 P_DestroyAllPlanes();
745
746 for (; num_elems > 0; num_elems--)
747 {
748 plane_move_t *pmov = new plane_move_t;
749
750 Z_Clear(pmov, plane_move_t, 1);
751
752 // link it in
753 P_AddActivePlane(pmov);
754 }
755 }
756
SV_PlaneMoveFinaliseElems(void)757 void SV_PlaneMoveFinaliseElems(void)
758 {
759 // nothing to do
760 }
761
762
763 //----------------------------------------------------------------------------
764
765 extern std::vector<slider_move_t *> active_sliders;
766
SV_SliderMoveCountElems(void)767 int SV_SliderMoveCountElems(void)
768 {
769 return (int)active_sliders.size();
770 }
771
SV_SliderMoveGetElem(int index)772 void *SV_SliderMoveGetElem(int index)
773 {
774 // Note: the index value starts at 0.
775
776 if (index < 0 || index >= (int)active_sliders.size())
777 I_Error("LOADGAME: Invalid SliderMove: %d\n", index);
778
779 return active_sliders[index];
780 }
781
SV_SliderMoveFindElem(slider_move_t * elem)782 int SV_SliderMoveFindElem(slider_move_t *elem)
783 {
784 // returns the index value (starts at 0).
785
786 int index = 0;
787
788 std::vector<slider_move_t *>::iterator SMI;
789
790 for (SMI = active_sliders.begin();
791 SMI != active_sliders.end() && (*SMI) != elem;
792 SMI++)
793 {
794 index++;
795 }
796
797 if (SMI == active_sliders.end())
798 I_Error("LOADGAME: No such SliderMove: %p\n", elem);
799
800 return index;
801 }
802
SV_SliderMoveCreateElems(int num_elems)803 void SV_SliderMoveCreateElems(int num_elems)
804 {
805 P_DestroyAllSliders();
806
807 for (; num_elems > 0; num_elems--)
808 {
809 slider_move_t *smov = new slider_move_t;
810
811 Z_Clear(smov, slider_move_t, 1);
812
813 // link it in
814 P_AddActiveSlider(smov);
815 }
816 }
817
SV_SliderMoveFinaliseElems(void)818 void SV_SliderMoveFinaliseElems(void)
819 {
820 std::vector<slider_move_t *>::iterator SMI;
821
822 for (SMI = active_sliders.begin();
823 SMI != active_sliders.end();
824 SMI++)
825 {
826 slider_move_t *smov = *SMI;
827
828 if (smov->line)
829 smov->line_len = R_PointToDist(0, 0, smov->line->dx, smov->line->dy);
830 }
831 }
832
833
834 //----------------------------------------------------------------------------
835
SR_LightGetType(void * storage,int index,void * extra)836 bool SR_LightGetType(void *storage, int index, void *extra)
837 {
838 const lightdef_c ** dest = (const lightdef_c **)storage + index;
839
840 int number;
841 const char *str;
842
843 str = SV_GetString();
844
845 if (! str)
846 {
847 (*dest) = NULL;
848 return true;
849 }
850
851 if (str[1] != ':')
852 I_Error("SR_LightGetType: invalid lighttype `%s'\n", str);
853
854 number = strtol(str + 2, NULL, 0);
855
856 if (str[0] == 'S')
857 {
858 const sectortype_c *special = P_LookupSectorType(number);
859 (*dest) = &special->l;
860 }
861 else if (str[0] == 'L')
862 {
863 const linetype_c *special = P_LookupLineType(number);
864 (*dest) = &special->l;
865 }
866 else
867 I_Error("SR_LightGetType: invalid lighttype `%s'\n", str);
868
869 SV_FreeString(str);
870 return true;
871 }
872
873 //
874 // SR_LightPutType
875 //
876 // Format of the string:
877 //
878 // <source char> `:' <source ref>
879 //
880 // The source char determines where the lighttype_t is found: `S' in a
881 // sector type or `L' in a linedef type. The source ref is the
882 // numeric ID of the sector/line type in DDF.
883 //
SR_LightPutType(void * storage,int index,void * extra)884 void SR_LightPutType(void *storage, int index, void *extra)
885 {
886 const lightdef_c *src = ((const lightdef_c **)storage)[index];
887 epi::array_iterator_c it;
888 linetype_c *ln;
889 sectortype_c *sec;
890
891 if (! src)
892 {
893 SV_PutString(NULL);
894 return;
895 }
896
897 // look for it in the line types
898 for (it=linetypes.GetBaseIterator(); it.IsValid(); it++)
899 {
900 ln = ITERATOR_TO_TYPE(it, linetype_c*);
901 if (src == &ln->l)
902 {
903 std::string s = epi::STR_Format("L:%d", ln->number);
904 SV_PutString(s.c_str());
905 return;
906 }
907 }
908
909 // look for it in the sector types
910 for (it=sectortypes.GetBaseIterator(); it.IsValid(); it++)
911 {
912 sec = ITERATOR_TO_TYPE(it, sectortype_c*);
913 if (src == &sec->l)
914 {
915 std::string s = epi::STR_Format("S:%d", sec->number);
916 SV_PutString(s.c_str());
917 return;
918 }
919 }
920
921 // not found !
922
923 I_Warning("SAVEGAME: could not find lightdef_c %p !\n", src);
924 SV_PutString("S:1");
925 }
926
927
SR_TriggerGetState(void * storage,int index,void * extra)928 bool SR_TriggerGetState(void *storage, int index, void *extra)
929 {
930 const rts_state_t ** dest = (const rts_state_t **)storage + index;
931 const rts_state_t *temp;
932
933 int value;
934 const rad_trigger_t *trig = (rad_trigger_t *) sv_current_elem;
935
936 value = SV_GetInt();
937
938 if (value == 0)
939 {
940 (*dest) = NULL;
941 return true;
942 }
943
944 for (temp=trig->info->first_state; temp;
945 temp=temp->next, value--)
946 {
947 if (value == 1)
948 break;
949 }
950
951 if (! temp)
952 {
953 I_Warning("LOADGAME: invalid RTS state !\n");
954 temp = trig->info->last_state;
955 }
956
957 (*dest) = temp;
958 return true;
959 }
960
SR_TriggerPutState(void * storage,int index,void * extra)961 void SR_TriggerPutState(void *storage, int index, void *extra)
962 {
963 const rts_state_t *src = ((const rts_state_t **)storage)[index];
964 const rts_state_t *temp;
965
966 int value;
967 const rad_trigger_t *trig = (rad_trigger_t *) sv_current_elem;
968
969 if (! src)
970 {
971 SV_PutInt(0);
972 return;
973 }
974
975 // determine index value
976 for (temp=trig->info->first_state, value=1; temp;
977 temp=temp->next, value++)
978 {
979 if (temp == src)
980 break;
981 }
982
983 if (! temp)
984 I_Error("INTERNAL ERROR: no such RTS state %p !\n", src);
985
986 SV_PutInt(value);
987 }
988
989
SR_TriggerGetScript(void * storage,int index,void * extra)990 bool SR_TriggerGetScript(void *storage, int index, void *extra)
991 {
992 const rad_script_t ** dest = (const rad_script_t **)storage + index;
993 const rad_script_t *temp;
994
995 const char *swizzle;
996 char buffer[256];
997 char *base_p, *use_p;
998 char *map_name;
999
1000 int idx_val;
1001 u32_t crc;
1002
1003 swizzle = SV_GetString();
1004
1005 if (! swizzle)
1006 {
1007 (*dest) = NULL;
1008 return true;
1009 }
1010
1011 Z_StrNCpy(buffer, swizzle, 256-1);
1012 SV_FreeString(swizzle);
1013
1014 if (buffer[0] != 'B' || buffer[1] != ':')
1015 I_Error("Corrupt savegame: bad script ref 1/4: `%s'\n", buffer);
1016
1017 // get map name
1018
1019 map_name = buffer + 2;
1020 base_p = strchr(map_name, ':');
1021
1022 if (base_p == NULL || base_p == map_name || base_p[0] == 0)
1023 I_Error("Corrupt savegame: bad script ref 2/4: `%s'\n", map_name);
1024
1025 // terminate the map name
1026 *base_p++ = 0;
1027
1028 // get index value
1029
1030 use_p = base_p;
1031 base_p = strchr(use_p, ':');
1032
1033 if (base_p == NULL || base_p == use_p || base_p[0] == 0)
1034 I_Error("Corrupt savegame: bad script ref 3/4: `%s'\n", use_p);
1035
1036 *base_p++ = 0;
1037
1038 idx_val = strtol(use_p, NULL, 0);
1039 SYS_ASSERT(idx_val >= 1);
1040
1041 // get CRC value
1042
1043 crc = (u32_t) strtoul(base_p, NULL, 16);
1044
1045 // now find the bugger !
1046 // FIXME: move into RTS code
1047
1048 for (temp=r_scripts; temp; temp=temp->next)
1049 {
1050 if (DDF_CompareName(temp->mapid, map_name) != 0)
1051 continue;
1052
1053 if (temp->crc.crc != crc)
1054 continue;
1055
1056 if (idx_val == 1)
1057 break;
1058
1059 idx_val--;
1060 }
1061
1062 if (! temp)
1063 {
1064 I_Warning("LOADGAME: No such RTS script !!\n");
1065 temp = r_scripts;
1066 }
1067
1068 (*dest) = temp;
1069 return true;
1070 }
1071
1072 //
1073 // SR_TriggerPutScript
1074 //
1075 // Format of the string:
1076 //
1077 // `B' `:' <map> `:' <index> `:' <crc>
1078 //
1079 // The `B' is a format descriptor -- future changes should use other
1080 // letters. The CRC is used to find the radius script. There may be
1081 // several in the same map with the same CRC, and the `index' part is
1082 // used to differentiate them. Index values begin at 1. The CRC
1083 // value is in hexadecimal.
1084 //
SR_TriggerPutScript(void * storage,int index,void * extra)1085 void SR_TriggerPutScript(void *storage, int index, void *extra)
1086 {
1087 const rad_script_t *src = ((const rad_script_t **)storage)[index];
1088 const rad_script_t *temp;
1089
1090 int idx_val;
1091 char buffer[256];
1092
1093 if (! src)
1094 {
1095 SV_PutString(NULL);
1096 return;
1097 }
1098
1099 // determine index idx_val
1100 // FIXME: move into RTS code
1101 for (temp=r_scripts, idx_val=1; temp; temp=temp->next)
1102 {
1103 if (DDF_CompareName(src->mapid, temp->mapid) != 0)
1104 continue;
1105
1106 if (temp == src)
1107 break;
1108
1109 if (temp->crc.crc == src->crc.crc)
1110 idx_val++;
1111 }
1112
1113 if (! temp)
1114 I_Error("SR_TriggerPutScript: invalid ScriptPtr %p\n", src);
1115
1116 sprintf(buffer, "B:%s:%d:%X", src->mapid, idx_val, src->crc.crc);
1117
1118 SV_PutString(buffer);
1119 }
1120
1121
1122
1123 //----------------------------------------------------------------------------
1124
SR_TipGetString(void * storage,int index,void * extra)1125 bool SR_TipGetString(void *storage, int index, void *extra)
1126 {
1127 const char ** dest = (const char **)storage + index;
1128
1129 SV_FreeString(*dest);
1130
1131 (*dest) = SV_GetString();
1132 return true;
1133 }
1134
SR_TipPutString(void * storage,int index,void * extra)1135 void SR_TipPutString(void *storage, int index, void *extra)
1136 {
1137 const char *src = ((const char **)storage)[index];
1138
1139 SV_PutString(src);
1140 }
1141
1142
SR_PlaneMoveGetType(void * storage,int index,void * extra)1143 bool SR_PlaneMoveGetType(void *storage, int index, void *extra)
1144 {
1145 const movplanedef_c ** dest = (const movplanedef_c **)storage + index;
1146
1147 int number;
1148 bool is_ceil;
1149 const char *str;
1150
1151 str = SV_GetString();
1152
1153 if (! str)
1154 {
1155 (*dest) = NULL;
1156 return true;
1157 }
1158
1159 if (str[1] != ':' || str[3] != ':')
1160 I_Error("SR_PlaneMoveGetType: invalid movestr `%s'\n", str);
1161
1162 is_ceil = false;
1163
1164 if (str[2] == 'F')
1165 ;
1166 else if (str[2] == 'C')
1167 is_ceil = true;
1168 else
1169 I_Error("SR_PlaneMoveGetType: invalid floortype `%s'\n", str);
1170
1171 number = strtol(str + 4, NULL, 0);
1172
1173 if (str[0] == 'S')
1174 {
1175 const sectortype_c *special = P_LookupSectorType(number);
1176 (*dest) = is_ceil ? &special->c : &special->f;
1177 }
1178 else if (str[0] == 'L')
1179 {
1180 const linetype_c *special = P_LookupLineType(number);
1181 (*dest) = is_ceil ? &special->c : &special->f;
1182 }
1183 else if (str[0] == 'D')
1184 {
1185 // FIXME: this ain't gonna work, freddy
1186 (*dest) = is_ceil ? &donut[number].c : &donut[number].f;
1187 }
1188 else
1189 I_Error("SR_PlaneMoveGetType: invalid srctype `%s'\n", str);
1190
1191 SV_FreeString(str);
1192 return true;
1193 }
1194
1195 //
1196 // Format of the string:
1197 //
1198 // <line/sec> `:' <floor/ceil> `:' <ddf num>
1199 //
1200 // The first field contains `L' if the movplanedef_c is within a
1201 // linetype_c, `S' for a sectortype_c, or `D' for the donut (which
1202 // prolly won't work yet). The second field is `F' for the floor
1203 // field in the line/sectortype, or `C' for the ceiling field. The
1204 // last value is the line/sector DDF number.
1205 //
SR_PlaneMovePutType(void * storage,int index,void * extra)1206 void SR_PlaneMovePutType(void *storage, int index, void *extra)
1207 {
1208 const movplanedef_c *src = ((const movplanedef_c **)storage)[index];
1209
1210 epi::array_iterator_c it;
1211 linetype_c *ln;
1212 sectortype_c *sec;
1213
1214 if (! src)
1215 {
1216 SV_PutString(NULL);
1217 return;
1218 }
1219
1220 // check for donut
1221 {
1222 int i;
1223 for (i=0; i < 2; i++)
1224 {
1225 if (src == &donut[i].f)
1226 {
1227 std::string s = epi::STR_Format("D:F:%d", i);
1228 SV_PutString(s.c_str());
1229 return;
1230 }
1231 else if (src == &donut[i].c)
1232 {
1233 std::string s = epi::STR_Format("D:C:%d", i);
1234 SV_PutString(s.c_str());
1235 return;
1236 }
1237 }
1238 }
1239
1240 // check all the line types
1241 for (it=linetypes.GetBaseIterator(); it.IsValid(); it++)
1242 {
1243 ln = ITERATOR_TO_TYPE(it, linetype_c*);
1244
1245 if (src == &ln->f)
1246 {
1247 std::string s = epi::STR_Format("L:F:%d", ln->number);
1248 SV_PutString(s.c_str());
1249 return;
1250 }
1251
1252 if (src == &ln->c)
1253 {
1254 std::string s = epi::STR_Format("L:C:%d", ln->number);
1255 SV_PutString(s.c_str());
1256 return;
1257 }
1258 }
1259
1260 // check all the sector types
1261 for (it=sectortypes.GetBaseIterator(); it.IsValid(); it++)
1262 {
1263 sec = ITERATOR_TO_TYPE(it, sectortype_c*);
1264
1265 if (src == &sec->f)
1266 {
1267 std::string s = epi::STR_Format("S:F:%d", sec->number);
1268 SV_PutString(s.c_str());
1269 return;
1270 }
1271
1272 if (src == &sec->c)
1273 {
1274 std::string s = epi::STR_Format("S:C:%d", sec->number);
1275 SV_PutString(s.c_str());
1276 return;
1277 }
1278 }
1279
1280 // not found !
1281
1282 I_Warning("SAVEGAME: could not find moving_plane %p !\n", src);
1283 SV_PutString("L:C:1");
1284 }
1285
1286
SR_SliderGetInfo(void * storage,int index,void * extra)1287 bool SR_SliderGetInfo(void *storage, int index, void *extra)
1288 {
1289 const sliding_door_c ** dest = (const sliding_door_c **)storage + index;
1290 const char *str;
1291
1292 str = SV_GetString();
1293
1294 if (! str)
1295 {
1296 (*dest) = NULL;
1297 return true;
1298 }
1299
1300 if (str[0] != ':')
1301 I_Error("SR_SliderGetInfo: invalid special `%s'\n", str);
1302
1303 const linetype_c *ld_type = P_LookupLineType(strtol(str+1, NULL, 0));
1304
1305 (*dest) = &ld_type->s;
1306
1307 SV_FreeString(str);
1308 return true;
1309 }
1310
1311 //
1312 // Format of the string will usually be a colon followed by the
1313 // linedef number (e.g. ":123").
1314 //
SR_SliderPutInfo(void * storage,int index,void * extra)1315 void SR_SliderPutInfo(void *storage, int index, void *extra)
1316 {
1317 const sliding_door_c *src = ((const sliding_door_c **)storage)[index];
1318
1319 if (! src)
1320 {
1321 SV_PutString(NULL);
1322 return;
1323 }
1324
1325 // check all the line types
1326 epi::array_iterator_c it;
1327
1328 for (it = linetypes.GetBaseIterator(); it.IsValid(); it++)
1329 {
1330 linetype_c *ld_type = ITERATOR_TO_TYPE(it, linetype_c*);
1331
1332 if (src == &ld_type->s)
1333 {
1334 std::string s = epi::STR_Format(":%d", ld_type->number);
1335 SV_PutString(s.c_str());
1336 return;
1337 }
1338 }
1339
1340 // not found !
1341
1342 I_Warning("SAVEGAME: could not find sliding door %p !\n", src);
1343 SV_PutString(":1");
1344 }
1345
1346
1347 //--- editor settings ---
1348 // vi:ts=4:sw=4:noexpandtab
1349