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 = &sectortypes.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