1 //----------------------------------------------------------------------------
2 // EDGE Data Definition File Code (Game settings)
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 // Overall Game Setup and Parser Code
20 //
21
22 #include "local.h"
23
24
25 #undef DF
26 #define DF DDF_FIELD
27
28 gamedef_container_c gamedefs;
29
30 static gamedef_c *dynamic_gamedef;
31
32 static wi_animdef_c buffer_animdef;
33 static wi_framedef_c buffer_framedef;
34
35 static void DDF_GameGetPic (const char *info, void *storage);
36 static void DDF_GameGetAnim(const char *info, void *storage);
37 static void DDF_GameGetMap (const char *info, void *storage);
38 static void DDF_GameGetLighting(const char *info, void *storage);
39
40 #define DDF_CMD_BASE dummy_gamedef
41 static gamedef_c dummy_gamedef;
42
43 static const commandlist_t gamedef_commands[] =
44 {
45 DF("INTERMISSION_GRAPHIC", background, DDF_MainGetLumpName),
46 DF("INTERMISSION_CAMERA", bg_camera, DDF_MainGetString),
47 DF("INTERMISSION_MUSIC", music, DDF_MainGetNumeric),
48 DF("SPLAT_GRAPHIC", splatpic, DDF_MainGetLumpName),
49 DF("YAH1_GRAPHIC", yah[0], DDF_MainGetLumpName),
50 DF("YAH2_GRAPHIC", yah[1], DDF_MainGetLumpName),
51 DF("PERCENT_SOUND", percent, DDF_MainLookupSound),
52 DF("DONE_SOUND", done, DDF_MainLookupSound),
53 DF("ENDMAP_SOUND", endmap, DDF_MainLookupSound),
54 DF("NEXTMAP_SOUND", nextmap, DDF_MainLookupSound),
55 DF("ACCEL_SOUND", accel_snd, DDF_MainLookupSound),
56 DF("FRAG_SOUND", frag_snd, DDF_MainLookupSound),
57 DF("FIRSTMAP", firstmap, DDF_MainGetLumpName),
58 DF("NAME_GRAPHIC", namegraphic, DDF_MainGetLumpName),
59 DF("TITLE_MUSIC", titlemusic, DDF_MainGetNumeric),
60 DF("TITLE_TIME", titletics, DDF_MainGetTime),
61 DF("SPECIAL_MUSIC", special_music, DDF_MainGetNumeric),
62 DF("LIGHTING", lighting, DDF_GameGetLighting),
63
64 DDF_CMD_END
65 };
66
67
68 //
69 // DDF PARSE ROUTINES
70 //
71
GameStartEntry(const char * name,bool extend)72 static void GameStartEntry(const char *name, bool extend)
73 {
74 if (!name || !name[0])
75 {
76 DDF_WarnError("New game entry is missing a name!");
77 name = "GAME_WITH_NO_NAME";
78 }
79
80 // instantiate the static entries
81 buffer_animdef.Default();
82 buffer_framedef.Default();
83
84 // replaces an existing entry?
85 dynamic_gamedef = gamedefs.Lookup(name);
86
87 if (extend)
88 {
89 if (! dynamic_gamedef)
90 DDF_Error("Unknown game to extend: %s\n", name);
91 return;
92 }
93
94 if (dynamic_gamedef)
95 {
96 dynamic_gamedef->Default();
97 return;
98 }
99
100 // not found, create a new one
101 dynamic_gamedef = new gamedef_c;
102 dynamic_gamedef->name = name;
103
104 gamedefs.Insert(dynamic_gamedef);
105 }
106
107
GameDoTemplate(const char * contents)108 static void GameDoTemplate(const char *contents)
109 {
110 gamedef_c *other = gamedefs.Lookup(contents);
111
112 if (!other || other == dynamic_gamedef)
113 DDF_Error("Unknown game template: '%s'\n", contents);
114
115 dynamic_gamedef->CopyDetail(*other);
116 }
117
118
GameParseField(const char * field,const char * contents,int index,bool is_last)119 static void GameParseField(const char *field, const char *contents,
120 int index, bool is_last)
121 {
122 #if (DEBUG_DDF)
123 I_Debugf ("GAME_PARSE: %s = %s;\n", field, contents);
124 #endif
125
126 if (DDF_CompareName(field, "TEMPLATE") == 0)
127 {
128 GameDoTemplate(contents);
129 return;
130 }
131
132 // handle some special fields...
133 if (DDF_CompareName(field, "TITLE_GRAPHIC") == 0)
134 {
135 DDF_GameGetPic(contents, NULL);
136 return;
137 }
138 else if (DDF_CompareName(field, "MAP") == 0)
139 {
140 DDF_GameGetMap(contents, NULL);
141 return;
142 }
143 else if (DDF_CompareName(field, "ANIM") == 0)
144 {
145 DDF_GameGetAnim(contents, &buffer_framedef);
146 return;
147 }
148
149 if (DDF_MainParseField(gamedef_commands, field, contents, (byte *)dynamic_gamedef))
150 return; // OK
151
152 DDF_WarnError("Unknown games.ddf command: %s\n", field);
153 }
154
155
GameFinishEntry(void)156 static void GameFinishEntry (void)
157 {
158 // TODO: check stuff...
159 }
160
161
GameClearAll(void)162 static void GameClearAll (void)
163 {
164 // 100% safe to delete all game entries
165 gamedefs.Clear();
166 }
167
168
DDF_ReadGames(void * data,int size)169 bool DDF_ReadGames (void *data, int size)
170 {
171 readinfo_t games;
172
173 games.memfile = (char *) data;
174 games.memsize = size;
175 games.tag = "GAMES";
176 games.entries_per_dot = 1;
177
178 if (games.memfile)
179 {
180 games.message = NULL;
181 games.filename = NULL;
182 games.lumpname = "DDFGAME";
183 }
184 else
185 {
186 games.message = "DDF_InitGames";
187 games.filename = "games.ddf";
188 games.lumpname = NULL;
189 }
190
191 games.start_entry = GameStartEntry;
192 games.parse_field = GameParseField;
193 games.finish_entry = GameFinishEntry;
194 games.clear_all = GameClearAll;
195
196 return DDF_MainReadFile (&games);
197 }
198
199
DDF_GameInit(void)200 void DDF_GameInit(void)
201 {
202 gamedefs.Clear(); // <-- Consistent with existing behaviour (-ACB- 2004/05/23)
203 }
204
205
DDF_GameCleanUp(void)206 void DDF_GameCleanUp(void)
207 {
208 if (gamedefs.GetSize() == 0)
209 I_Error("There are no games defined in DDF !\n");
210 }
211
212
DDF_GameAddFrame(void)213 static void DDF_GameAddFrame(void)
214 {
215 wi_framedef_c *f = new wi_framedef_c(buffer_framedef);
216
217 buffer_animdef.frames.Insert(f);
218
219 buffer_framedef.Default();
220 }
221
DDF_GameAddAnim(void)222 static void DDF_GameAddAnim(void)
223 {
224 wi_animdef_c *a = new wi_animdef_c(buffer_animdef);
225
226 if (a->level[0])
227 a->type = wi_animdef_c::WI_LEVEL;
228 else
229 a->type = wi_animdef_c::WI_NORMAL;
230
231 dynamic_gamedef->anims.Insert(a);
232
233 buffer_animdef.Default();
234 }
235
ParseFrame(const char * info,wi_framedef_c * f)236 static void ParseFrame(const char *info, wi_framedef_c *f)
237 {
238 const char *p = strchr(info, ':');
239 if (! p || p == info)
240 DDF_Error("Bad frame def: '%s' (missing pic name)\n", info);
241
242 std::string temp(info, p - info);
243
244 f->pic.Set(temp.c_str());
245
246 p++;
247
248 if (sscanf(p, " %d : %d : %d ", &f->tics, &f->x, &f->y) != 3)
249 DDF_Error("Bad frame definition: '%s'\n", info);
250 }
251
DDF_GameGetAnim(const char * info,void * storage)252 static void DDF_GameGetAnim(const char *info, void *storage)
253 {
254 wi_framedef_c *f = (wi_framedef_c *) storage;
255
256 if (DDF_CompareName(info, "#END") == 0)
257 {
258 DDF_GameAddAnim();
259 return;
260 }
261
262 const char *p = info;
263
264 if (info[0] == '#')
265 {
266 if (buffer_animdef.frames.GetSize() > 0)
267 DDF_Error("Invalid # command: '%s'\n", info);
268
269 p = strchr(info, ':');
270 if (! p || p <= info+1)
271 DDF_Error("Invalid # command: '%s'\n", info);
272
273 std::string temp(info+1, p - (info+1));
274
275 buffer_animdef.level.Set(temp.c_str());
276
277 p++;
278 }
279
280 ParseFrame(p, f);
281
282 // this assumes 'f' points to buffer_framedef
283 DDF_GameAddFrame();
284 }
285
286
ParseMap(const char * info,wi_mapposdef_c * mp)287 static void ParseMap(const char *info, wi_mapposdef_c *mp)
288 {
289 const char *p = strchr(info, ':');
290 if (! p || p == info)
291 DDF_Error("Bad map def: '%s' (missing level name)\n", info);
292
293 std::string temp(info, p - info);
294
295 mp->name.Set(temp.c_str());
296
297 p++;
298
299 if (sscanf(p, " %d : %d ", &mp->x, &mp->y) != 2)
300 DDF_Error("Bad map definition: '%s'\n", info);
301 }
302
DDF_GameGetMap(const char * info,void * storage)303 static void DDF_GameGetMap(const char *info, void *storage)
304 {
305 wi_mapposdef_c *mp = new wi_mapposdef_c();
306
307 ParseMap(info, mp);
308
309 dynamic_gamedef->mappos.Insert(mp);
310 }
311
DDF_GameGetPic(const char * info,void * storage)312 static void DDF_GameGetPic (const char *info, void *storage)
313 {
314 dynamic_gamedef->titlepics.Insert(info);
315 }
316
317
318 static specflags_t lighting_names[] =
319 {
320 {"DOOM", LMODEL_Doom, 0},
321 {"DOOMISH", LMODEL_Doomish, 0},
322 {"FLAT", LMODEL_Flat, 0},
323 {"VERTEX", LMODEL_Vertex, 0},
324 {NULL, 0, 0}
325 };
326
DDF_GameGetLighting(const char * info,void * storage)327 void DDF_GameGetLighting(const char *info, void *storage)
328 {
329 int flag_value;
330
331 if (CHKF_Positive != DDF_MainCheckSpecialFlag(info,
332 lighting_names, &flag_value, false, false))
333 {
334 DDF_WarnError("GAMES.DDF LIGHTING: Unknown model: %s", info);
335 return;
336 }
337
338 ((lighting_model_e *)storage)[0] = (lighting_model_e)flag_value;
339 }
340
341
342
343 // --> world intermission mappos class
344
345 //
346 // wi_mapposdef_c Constructor
347 //
wi_mapposdef_c()348 wi_mapposdef_c::wi_mapposdef_c()
349 {
350 }
351
352 //
353 // wi_mapposdef_c Copy constructor
354 //
wi_mapposdef_c(wi_mapposdef_c & rhs)355 wi_mapposdef_c::wi_mapposdef_c(wi_mapposdef_c &rhs)
356 {
357 Copy(rhs);
358 }
359
360 //
361 // wi_mapposdef_c Destructor
362 //
~wi_mapposdef_c()363 wi_mapposdef_c::~wi_mapposdef_c()
364 {
365 }
366
367 //
368 // wi_mapposdef_c::Copy()
369 //
Copy(wi_mapposdef_c & src)370 void wi_mapposdef_c::Copy(wi_mapposdef_c &src)
371 {
372 name = src.name;
373 x = src.x;
374 y = src.y;
375 }
376
377 //
378 // wi_mapposdef_c assignment operator
379 //
operator =(wi_mapposdef_c & rhs)380 wi_mapposdef_c& wi_mapposdef_c::operator=(wi_mapposdef_c &rhs)
381 {
382 if (&rhs != this)
383 Copy(rhs);
384
385 return *this;
386 }
387
388 // --> world intermission mappos container class
389
390 //
391 // wi_mapposdef_container_c Constructor
392 //
wi_mapposdef_container_c()393 wi_mapposdef_container_c::wi_mapposdef_container_c()
394 : epi::array_c(sizeof(wi_mapposdef_c*))
395 {
396 }
397
398 //
399 // wi_mapposdef_container_c Copy constructor
400 //
wi_mapposdef_container_c(wi_mapposdef_container_c & rhs)401 wi_mapposdef_container_c::wi_mapposdef_container_c(wi_mapposdef_container_c &rhs)
402 : epi::array_c(sizeof(wi_mapposdef_c*))
403 {
404 Copy(rhs);
405 }
406
407 //
408 // wi_mapposdef_container_c Destructor
409 //
~wi_mapposdef_container_c()410 wi_mapposdef_container_c::~wi_mapposdef_container_c()
411 {
412 Clear();
413 }
414
415 //
416 // wi_mapposdef_container_c::CleanupObject()
417 //
CleanupObject(void * obj)418 void wi_mapposdef_container_c::CleanupObject(void *obj)
419 {
420 wi_mapposdef_c *mp = *(wi_mapposdef_c**)obj;
421
422 if (mp)
423 delete mp;
424
425 return;
426 }
427
428 //
429 // wi_mapposdef_container_c::Copy()
430 //
Copy(wi_mapposdef_container_c & src)431 void wi_mapposdef_container_c::Copy(wi_mapposdef_container_c &src)
432 {
433 epi::array_iterator_c it;
434 wi_mapposdef_c *wi;
435 wi_mapposdef_c *wi2;
436
437 Size(src.GetSize());
438
439 for (it = src.GetBaseIterator(); it.IsValid(); it++)
440 {
441 wi = ITERATOR_TO_TYPE(it, wi_mapposdef_c*);
442 if (wi)
443 {
444 wi2 = new wi_mapposdef_c(*wi);
445 Insert(wi2);
446 }
447 }
448
449 Trim();
450 }
451
452 //
453 // wi_mapposdef_container_c assignment operator
454 //
operator =(wi_mapposdef_container_c & rhs)455 wi_mapposdef_container_c& wi_mapposdef_container_c::operator=(wi_mapposdef_container_c &rhs)
456 {
457 if (&rhs != this)
458 {
459 Clear();
460 Copy(rhs);
461 }
462
463 return *this;
464 }
465
466 // --> world intermission framedef class
467
468 //
469 // wi_framedef_c Constructor
470 //
wi_framedef_c()471 wi_framedef_c::wi_framedef_c()
472 {
473 Default();
474 }
475
476 //
477 // wi_framedef_c Copy constructor
478 //
wi_framedef_c(wi_framedef_c & rhs)479 wi_framedef_c::wi_framedef_c(wi_framedef_c &rhs)
480 {
481 Copy(rhs);
482 }
483
484 //
485 // wi_framedef_c Destructor
486 //
~wi_framedef_c()487 wi_framedef_c::~wi_framedef_c()
488 {
489 }
490
491 //
492 // wi_framedef_c::Copy()
493 //
Copy(wi_framedef_c & src)494 void wi_framedef_c::Copy(wi_framedef_c &src)
495 {
496 pic = src.pic;
497 tics = src.tics;
498 x = src.x;
499 y = src.y;
500 }
501
502 //
503 // wi_framedef_c::Default()
504 //
Default()505 void wi_framedef_c::Default()
506 {
507 pic.clear();
508 tics = 0;
509 x = y = 0;
510 }
511
512 //
513 // wi_framedef_c assignment operator
514 //
operator =(wi_framedef_c & rhs)515 wi_framedef_c& wi_framedef_c::operator=(wi_framedef_c &rhs)
516 {
517 if (&rhs != this)
518 Copy(rhs);
519
520 return *this;
521 }
522
523 // --> world intermission framedef container class
524
525 //
526 // wi_framedef_container_c Constructor
527 //
wi_framedef_container_c()528 wi_framedef_container_c::wi_framedef_container_c()
529 : epi::array_c(sizeof(wi_framedef_c*))
530 {
531 }
532
533 //
534 // wi_framedef_container_c Copy constructor
535 //
wi_framedef_container_c(wi_framedef_container_c & rhs)536 wi_framedef_container_c::wi_framedef_container_c(wi_framedef_container_c &rhs)
537 : epi::array_c(sizeof(wi_framedef_c*))
538 {
539 Copy(rhs);
540 }
541
542 //
543 // wi_framedef_container_c Destructor
544 //
~wi_framedef_container_c()545 wi_framedef_container_c::~wi_framedef_container_c()
546 {
547 Clear();
548 }
549
550 //
551 // wi_framedef_container_c::CleanupObject()
552 //
CleanupObject(void * obj)553 void wi_framedef_container_c::CleanupObject(void *obj)
554 {
555 wi_framedef_c *f = *(wi_framedef_c**)obj;
556
557 if (f)
558 delete f;
559
560 return;
561 }
562
563 //
564 // wi_framedef_container_c::Copy()
565 //
Copy(wi_framedef_container_c & src)566 void wi_framedef_container_c::Copy(wi_framedef_container_c &src)
567 {
568 epi::array_iterator_c it;
569 wi_framedef_c *f;
570 wi_framedef_c *f2;
571
572 Size(src.GetSize());
573
574 for (it = src.GetBaseIterator(); it.IsValid(); it++)
575 {
576 f = ITERATOR_TO_TYPE(it, wi_framedef_c*);
577 if (f)
578 {
579 f2 = new wi_framedef_c(*f);
580 Insert(f2);
581 }
582 }
583
584 Trim();
585 }
586
587 //
588 // wi_framedef_container_c assignment operator
589 //
operator =(wi_framedef_container_c & rhs)590 wi_framedef_container_c& wi_framedef_container_c::operator=(wi_framedef_container_c& rhs)
591 {
592 if (&rhs != this)
593 {
594 Clear();
595 Copy(rhs);
596 }
597
598 return *this;
599 }
600
601 // --> world intermission animdef class
602
603 //
604 // wi_animdef_c Constructor
605 //
wi_animdef_c()606 wi_animdef_c::wi_animdef_c()
607 {
608 Default();
609 }
610
611 //
612 // wi_animdef_c Copy constructor
613 //
wi_animdef_c(wi_animdef_c & rhs)614 wi_animdef_c::wi_animdef_c(wi_animdef_c &rhs)
615 {
616 Copy(rhs);
617 }
618
619 //
620 // wi_animdef_c Destructor
621 //
~wi_animdef_c()622 wi_animdef_c::~wi_animdef_c()
623 {
624 }
625
626 //
627 // void Copy()
628 //
Copy(wi_animdef_c & src)629 void wi_animdef_c::Copy(wi_animdef_c &src)
630 {
631 type = src.type;
632 level = src.level;
633 frames = src.frames;
634 }
635
636 //
637 // wi_animdef_c::Default()
638 //
Default()639 void wi_animdef_c::Default()
640 {
641 type = WI_NORMAL;
642 level.clear();
643
644 frames.Clear();
645 }
646
647
648 //
649 // wi_animdef_c assignment operator
650 //
operator =(wi_animdef_c & rhs)651 wi_animdef_c& wi_animdef_c::operator=(wi_animdef_c &rhs)
652 {
653 if (&rhs != this)
654 Copy(rhs);
655
656 return *this;
657 }
658
659 // --> world intermission anim container class
660
661 //
662 // wi_animdef_container_c Constructor
663 //
wi_animdef_container_c()664 wi_animdef_container_c::wi_animdef_container_c() : epi::array_c(sizeof(wi_animdef_c*))
665 {
666 }
667
668 //
669 // wi_animdef_container_c Copy constructor
670 //
wi_animdef_container_c(wi_animdef_container_c & rhs)671 wi_animdef_container_c::wi_animdef_container_c(wi_animdef_container_c &rhs)
672 : epi::array_c(sizeof(wi_animdef_c*))
673 {
674 Copy(rhs);
675 }
676
677 //
678 // wi_animdef_container_c Destructor
679 //
~wi_animdef_container_c()680 wi_animdef_container_c::~wi_animdef_container_c()
681 {
682 Clear();
683 }
684
685 //
686 // wi_animdef_container_c::CleanupObject()
687 //
CleanupObject(void * obj)688 void wi_animdef_container_c::CleanupObject(void *obj)
689 {
690 wi_animdef_c *a = *(wi_animdef_c**)obj;
691
692 if (a)
693 delete a;
694
695 return;
696 }
697
698 //
699 // wi_animdef_container_c::Copy()
700 //
Copy(wi_animdef_container_c & src)701 void wi_animdef_container_c::Copy(wi_animdef_container_c &src)
702 {
703 epi::array_iterator_c it;
704 wi_animdef_c *a;
705 wi_animdef_c *a2;
706
707 Size(src.GetSize());
708
709 for (it = src.GetBaseIterator(); it.IsValid(); it++)
710 {
711 a = ITERATOR_TO_TYPE(it, wi_animdef_c*);
712 if (a)
713 {
714 a2 = new wi_animdef_c(*a);
715 Insert(a2);
716 }
717 }
718
719 Trim();
720 }
721
722
723 //
724 // wi_animdef_container_c assignment operator
725 //
operator =(wi_animdef_container_c & rhs)726 wi_animdef_container_c& wi_animdef_container_c::operator=(wi_animdef_container_c &rhs)
727 {
728 if (&rhs != this)
729 {
730 Clear();
731 Copy(rhs);
732 }
733
734 return *this;
735 }
736
737
738 // --> game definition class
739
740 //
741 // gamedef_c Constructor
742 //
gamedef_c()743 gamedef_c::gamedef_c() : name()
744 {
745 Default();
746 }
747
748 //
749 // gamedef_c Destructor
750 //
~gamedef_c()751 gamedef_c::~gamedef_c()
752 {
753 }
754
755
756 //
757 // gamedef_c::CopyDetail()
758 //
CopyDetail(gamedef_c & src)759 void gamedef_c::CopyDetail(gamedef_c &src)
760 {
761 anims = src.anims;
762 mappos = src.mappos;
763
764 background = src.background;
765 splatpic = src.splatpic;
766
767 yah[0] = src.yah[0];
768 yah[1] = src.yah[1];
769
770 bg_camera = src.bg_camera;
771 music = src.music;
772
773 percent = src.percent;
774 done = src.done;
775 endmap = src.endmap;
776 nextmap = src.nextmap;
777 accel_snd = src.accel_snd;
778 frag_snd = src.frag_snd;
779
780 firstmap = src.firstmap;
781 namegraphic = src.namegraphic;
782
783 titlepics = src.titlepics;
784 titlemusic = src.titlemusic;
785 titletics = src.titletics;
786
787 special_music = src.special_music;
788 lighting = src.lighting;
789 }
790
791 //
792 // gamedef_c::Default()
793 //
Default()794 void gamedef_c::Default()
795 {
796 anims.Clear();
797 mappos.Clear();
798
799 background.clear();
800 splatpic.clear();
801
802 yah[0].clear();
803 yah[1].clear();
804
805 bg_camera.clear();
806 music = 0;
807
808 percent = sfx_None;
809 done = sfx_None;
810 endmap = sfx_None;
811 nextmap = sfx_None;
812 accel_snd = sfx_None;
813 frag_snd = sfx_None;
814
815 firstmap.clear();
816 namegraphic.clear();
817
818 titlepics.Clear();
819
820 titlemusic = 0;
821 titletics = TICRATE * 4;
822
823 special_music = 0;
824 lighting = LMODEL_Doom;
825 }
826
827
828 // --> game definition container class
829
830 //
831 // gamedef_container_c Constructor
832 //
gamedef_container_c()833 gamedef_container_c::gamedef_container_c() : epi::array_c(sizeof(gamedef_c*))
834 {
835 }
836
837 //
838 // gamedef_container_c Destructor
839 //
~gamedef_container_c()840 gamedef_container_c::~gamedef_container_c()
841 {
842 Clear();
843 }
844
845 //
846 // gamedef_container_c::CleanupObject()
847 //
CleanupObject(void * obj)848 void gamedef_container_c::CleanupObject(void *obj)
849 {
850 gamedef_c *g = *(gamedef_c**)obj;
851
852 if (g)
853 delete g;
854
855 return;
856 }
857
858 //
859 // gamedef_c* gamedef_container_c::Lookup()
860 //
861 // Looks an gamedef by name, returns a fatal error if it does not exist.
862 //
Lookup(const char * refname)863 gamedef_c* gamedef_container_c::Lookup(const char *refname)
864 {
865 epi::array_iterator_c it;
866 gamedef_c *g;
867
868 if (!refname || !refname[0])
869 return NULL;
870
871 for (it = GetBaseIterator(); it.IsValid(); it++)
872 {
873 g = ITERATOR_TO_TYPE(it, gamedef_c*);
874 if (DDF_CompareName(g->name.c_str(), refname) == 0)
875 return g;
876 }
877
878 return NULL;
879 }
880
881 //--- editor settings ---
882 // vi:ts=4:sw=4:noexpandtab
883