1 /*
2  * func.c - function pointers for special extras
3  *
4  * $Id: func.c,v 1.22 2006/03/29 21:46:27 alfie Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "xblast.h"
25 
26 /*
27  * global variables
28  */
29 void (*specialExtraFunc) (BMPlayer *);
30 void (*specialKeyFunc) (BMPlayer *);
31 
32 /*
33  * local types
34  */
35 typedef void (*SpecialExtraFunc) (BMPlayer *);
36 typedef void (*SpecialKeyFunc) (BMPlayer *);
37 static char *seVoidName = N_("No Special Extra");
38 static char *skVoidName = N_("No Special Key");
39 
40 /*
41  * void functions
42  */
43 void
SpecialExtraVoid(BMPlayer * ps)44 SpecialExtraVoid (BMPlayer * ps)
45 {
46 }
47 
48 void
SpecialKeyVoid(BMPlayer * ps)49 SpecialKeyVoid (BMPlayer * ps)
50 {
51 }
52 
53 /*
54  * Invincible
55  */
56 static void
SpecialExtraInvincible(BMPlayer * ps)57 SpecialExtraInvincible (BMPlayer * ps)
58 {
59 	SND_Play (SND_INVINC, ps->x / (PIXW / MAX_SOUND_POSITION));
60 	ps->illtime = 0;
61 	ps->illness = ps->health;
62 	ps->invincible += EXTRA_INVINCIBLE;
63 }								/* SpecialExtraInvincible */
64 
65 /*
66  * Kicking
67  */
68 static void
SpecialExtraKick(BMPlayer * ps)69 SpecialExtraKick (BMPlayer * ps)
70 {
71 	SND_Play (SND_NEWKICK, ps->x / (PIXW / MAX_SOUND_POSITION));
72 	ps->kick = XBTrue;
73 }								/* SpecialExtraKick */
74 
75 /*
76  * Remote Control
77  */
78 static void
SpecialExtraRC(BMPlayer * ps)79 SpecialExtraRC (BMPlayer * ps)
80 {
81 	SND_Play (SND_NEWRC, ps->x / (PIXW / MAX_SOUND_POSITION));
82 	ps->remote_control = XBTrue;
83 }								/* SpecialExtraRC */
84 
85 static void
SpecialKeyRC(BMPlayer * ps)86 SpecialKeyRC (BMPlayer * ps)
87 {
88 	if (ps->remote_control > 0) {
89 		if (IgnitePlayersBombs (ps)) {
90 			SND_Play (SND_SHOOT, ps->x / (PIXW / MAX_SOUND_POSITION));
91 		}
92 	}
93 }								/* SpecialKeyRC */
94 
95 /*
96  * bombs choice extra
97  */
98 static void
SpecialExtraChoice(BMPlayer * ps)99 SpecialExtraChoice (BMPlayer * ps)
100 {
101 	char tutu[40];
102 	if (ps->choice_bomb_type == NUM_BMT) {
103 		int i;
104 		for (i = ChoiceDefaultBomb; bomb_name_choice[i] == NULL; i = ((i + 1) % NUM_BMT)) ;
105 		ps->choice_bomb_type = i;
106 		if (ps->local) {
107 			sprintf (tutu, "%s : ", p_string[ps->id].name);
108 			strcat (tutu, bomb_name_choice[(ps->choice_bomb_type)]);
109 			SetMessage (tutu, XBTrue);
110 		}
111 	}
112 }
113 
114 static void
SpecialKeyChoice(BMPlayer * ps)115 SpecialKeyChoice (BMPlayer * ps)
116 {
117 
118 	if (ps->choice_bomb_type != NUM_BMT) {
119 		char tutu[40];
120 		int i;
121 		i = ps->choice_bomb_type;
122 		for (i = ((i + 1) % NUM_BMT); bomb_name_choice[i] == NULL; i = ((i + 1) % NUM_BMT)) ;
123 		ps->choice_bomb_type = i;
124 		if (ps->local) {
125 			sprintf (tutu, "%s : ", p_string[ps->id].name);
126 			strcat (tutu, bomb_name_choice[(ps->choice_bomb_type)]);
127 			SetMessage (tutu, XBTrue);
128 
129 		}
130 	}
131 }
132 
133 /* Written by VVL */
134 static void
SpecialKeyThrough(BMPlayer * ps)135 SpecialKeyThrough (BMPlayer * ps)
136 {
137 	if ((ps->throughCount > 0) && (ps->lives > 0)) {
138 		if (ps->through) {
139 			ps->through = 0;
140 		}
141 		else {
142 			ps->through = EXTRA_THROUGH_TIME;
143 			ps->throughCount--;
144 		}
145 	}
146 }
147 
148  /**/
149 /* Walk through bomb Mode */
150 	 /**/ static void
SpecialExtraThrough(BMPlayer * ps)151 SpecialExtraThrough (BMPlayer * ps)
152 {
153 	ps->throughCount += 1;
154 }
155 
156 /*
157  * Teleport
158  */
159 static void
SpecialExtraTeleport(BMPlayer * ps)160 SpecialExtraTeleport (BMPlayer * ps)
161 {
162 	SND_Play (SND_NEWTELE, ps->x / (PIXW / MAX_SOUND_POSITION));
163 	if (ps->teleport == 0) {
164 		ps->teleport = 1;
165 	}
166 }								/* SpecialExtraTeleport */
167 
168 static void
SpecialKeyTeleport(BMPlayer * ps)169 SpecialKeyTeleport (BMPlayer * ps)
170 {
171 	if (ps->teleport == 1) {
172 		ps->teleport = TELEPORT_TIME;
173 	}
174 }								/* SpecialKeyTeleport */
175 
176 /*
177  * Frogger  extra (galatius(skywalker))
178  */
179 static void
SpecialExtraFrogger(BMPlayer * ps)180 SpecialExtraFrogger (BMPlayer * ps)
181 {
182 	// SND_Play (SND_NEWTELE, ps->x / (PIXW / MAX_SOUND_POSITION));
183 
184 	ps->frogger++;
185 }								/* SpecialExtraFrogger */
186 
187 static void
SpecialKeyFrogger(BMPlayer * ps)188 SpecialKeyFrogger (BMPlayer * ps)
189 {
190 	if ((ps->lives > 0) && (ps->frogger) && (!ps->dying)) {
191 		/* do_bell(); */
192 		DoFrog (ps);
193 	}
194 }								/* SpecialKeyFrogger */
195 
196 /*
197  * Daleif Illness  (galatius(skywalker))
198  * Note that picking up this extra gets you *rid* of the daleif illness *
199  */
200 static void
SpecialExtraDaleif(BMPlayer * ps)201 SpecialExtraDaleif (BMPlayer * ps)
202 {
203 	ps->daleif = 0;
204 }								/* SpecialExtraDalif */
205 
206 /*
207  * Extra Ignite All
208  */
209 static void
SpecialExtraIgniteAll(BMPlayer * ps)210 SpecialExtraIgniteAll (BMPlayer * ps)
211 {
212 	SND_Play (SND_BUTT, ps->x / (PIXW / MAX_SOUND_POSITION));
213 	IgniteAllBombs (ps);
214 }								/* SpecialExtraIgniteAll */
215 
216 static void
SpecialKeySpecialBomb(BMPlayer * ps)217 SpecialKeySpecialBomb (BMPlayer * ps)
218 {
219 	DropBomb (ps, BMTspecial);
220 }								/* SpecialKeySpecialBomb */
221 
222 static void
SpecialExtraSpecialBomb(BMPlayer * ps)223 SpecialExtraSpecialBomb (BMPlayer * ps)
224 {
225 	SND_Play (SND_SPBOMB, ps->x / (PIXW / MAX_SOUND_POSITION));
226 	ps->special_bombs += 3;
227 }								/* SpecialextraSpecialBomb */
228 
229 /*
230  * Junkie (Garth again)
231  */
232 void
SpecialExtraJunkie(BMPlayer * ps)233 SpecialExtraJunkie (BMPlayer * ps)
234 {
235 	SND_Play (SND_INJ, ps->x / (PIXW / MAX_SOUND_POSITION));
236 	ps->junkie = MAX_JUNKIE_TIME;
237 }								/* SpecialExtraJunkie */
238 
239 /*
240  * Air Pump (Garth Denley)
241  */
242 static void
SpecialExtraAir(BMPlayer * ps)243 SpecialExtraAir (BMPlayer * ps)
244 {
245 	SND_Play (SND_NEWPUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
246 	ps->air_button = XBTrue;
247 }								/* SpecialExtraAir */
248 
249 static void
SpecialKeyAir(BMPlayer * ps)250 SpecialKeyAir (BMPlayer * ps)
251 {
252 	if ((ps->air_button > 0) && (ps->lives > 0)) {
253 		SND_Play (SND_PUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
254 		DoAir (ps);
255 	}
256 }								/* SpecialKeyAir */
257 
258 /*
259  * Sucker (Stephan Natschlaeger)
260  */
261 static void
SpecialExtraSuck(BMPlayer * ps)262 SpecialExtraSuck (BMPlayer * ps)
263 {
264 	SND_Play (SND_NEWPUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
265 	ps->suck_button = XBTrue;
266 }								/* SpecialExtraSuck */
267 
268 /*
269  * Ghost (Belgium Guys)
270  */
271 void
SpecialExtraGhost(BMPlayer * ps)272 SpecialExtraGhost (BMPlayer * ps)
273 {
274 	SND_Play (SND_NEWPUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
275 	ps->ghost = EXTRA_GHOST_TIME;
276 
277 }								/* SpecialExtraGhost */
278 
279 static void
SpecialKeySuck(BMPlayer * ps)280 SpecialKeySuck (BMPlayer * ps)
281 {
282 	if ((ps->suck_button > 0) && (ps->lives > 0)) {
283 		SND_Play (SND_PUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
284 		DoSuck (ps);
285 	}
286 }								/* SpecialKeySuck */
287 
288 /*
289  * poison extra
290  */
291 void
SpecialExtraPoison(BMPlayer * ps)292 SpecialExtraPoison (BMPlayer * ps)
293 {
294 	if (!ps->invincible) {
295 		ps->dying = DEAD_TIME;
296 	}
297 }								/* SpecialExtraPoison */
298 
299 /*
300  * spinner extra (long stunned )
301  */
302 static void
SpecialExtraLongStunned(BMPlayer * ps)303 SpecialExtraLongStunned (BMPlayer * ps)
304 {
305 	SND_Play (SND_STUN, ps->x / (PIXW / MAX_SOUND_POSITION));
306 	ps->stunned = STUN_TIME * 4;
307 }								/* SpecialExtraLongStunned */
308 
309 /*
310  * speed extra
311  */
312 static void
SpecialExtraSpeed(BMPlayer * ps)313 SpecialExtraSpeed (BMPlayer * ps)
314 {
315 	SND_Play (SND_FAST, ps->x / (PIXW / MAX_SOUND_POSITION));
316 	ps->illness = IllRun;
317 	ps->health = IllRun;
318 	ps->illtime = 0;
319 }								/* SpecialExtraSpeed */
320 
321 /*
322  * speed extra
323  */
324 static void
SpecialExtraSpeed2(BMPlayer * ps)325 SpecialExtraSpeed2 (BMPlayer * ps)
326 {
327 	SND_Play (SND_FAST, ps->x / (PIXW / MAX_SOUND_POSITION));
328 	ps->illness = IllRun;
329 	ps->health = IllRun;
330 	ps->illtime = 0;
331 	ps->speed++;
332 }								/* SpecialExtraSpeed */
333 
334 /*
335  * slow extra
336  */
337 void
SpecialExtraSlow(BMPlayer * ps)338 SpecialExtraSlow (BMPlayer * ps)
339 {
340 	SND_Play (SND_SLOW, ps->x / (PIXW / MAX_SOUND_POSITION));
341 	ps->illness = IllSlow;
342 	ps->health = IllSlow;
343 	ps->illtime = 0;
344 }								/* SpecialExtraSlow */
345 
346 /*
347  * mayhem extra
348  */
349 static void
SpecialExtraMayhem(BMPlayer * ps)350 SpecialExtraMayhem (BMPlayer * ps)
351 {
352 	SND_Play (SND_SLAY, ps->x / (PIXW / MAX_SOUND_POSITION));
353 	ps->kick = XBTrue;
354 	ps->illness = IllRun;
355 	ps->health = IllRun;
356 	ps->illtime = 0;
357 }								/* SpecialExtraMayhem */
358 
359 /*
360  * holy grail extra
361  */
362 static void
SpecialExtraHolyGrail(BMPlayer * ps)363 SpecialExtraHolyGrail (BMPlayer * ps)
364 {
365 	SND_Play (SND_HOLY, ps->x / (PIXW / MAX_SOUND_POSITION));
366 	ps->lives += KillOtherPlayers (ps->team);
367 	if (ps->lives > 9) {
368 		ps->lives = 9;
369 	}
370 	ps->invincible = NEW_INVINCIBLE;
371 	ps->dying = DEAD_TIME;
372 }								/* SpecialExtraHolyGrail */
373 
374 /* Added by "Belgium Guys" */
375 /* steal extra */
376  /**/ static void
SpecialExtraSteal(BMPlayer * ps)377 SpecialExtraSteal (BMPlayer * ps)
378 {
379 
380 	ps->bombs += StealBombsOtherPlayers (ps->team);
381 	ps->range += StealRangeOtherPlayers (ps->team);
382 }
383 
384 /*
385  * multiple extra
386  */
387 static void
SpecialExtraLife(BMPlayer * ps)388 SpecialExtraLife (BMPlayer * ps)
389 {
390 	SND_Play (SND_LIFE, ps->x / (PIXW / MAX_SOUND_POSITION));
391 	if (ps->lives < 9) {
392 		ps->lives++;
393 	}
394 }								/* SpecialExtraLife */
395 
396 /*
397  * multiple extra
398  */
399 static void
SpecialExtraMultiple(BMPlayer * ps)400 SpecialExtraMultiple (BMPlayer * ps)
401 {
402 	switch (GameRandomNumber (11)) {
403 	case 0:
404 	case 1:
405 		SpecialExtraSpeed (ps);
406 		break;
407 	case 2:
408 	case 3:
409 		SpecialExtraPoison (ps);
410 		break;
411 	case 4:
412 	case 5:
413 		SpecialExtraInvincible (ps);
414 		break;
415 	case 6:
416 	case 7:
417 		SpecialExtraLongStunned (ps);
418 		break;
419 	case 8:
420 	case 9:
421 		SpecialExtraAir (ps);
422 		break;
423 	case 10:
424 		SpecialExtraLife (ps);
425 		break;
426 	}
427 }								/* SpecialExtraMultiple */
428 
429 /*Skywalker epfl */
430 
431 /* Written by VVL */
432 /* Electrify */
433 static void
SpecialExtraElectrify(BMPlayer * ps)434 SpecialExtraElectrify (BMPlayer * ps)
435 {
436 	ps->electrify = EXTRA_ELECTRIFY_COUNT;
437 }
438 
439 static void
SpecialKeyElectrify(BMPlayer * ps)440 SpecialKeyElectrify (BMPlayer * ps)
441 {
442 	if ((ps->lives > 0) && (ps->electrify)) {
443 		if (ElectrifyOtherPlayers (ps->id)) {
444 			/* Success ... another player is hit! :-) */
445 			ps->electrify = 0;
446 		}
447 		else {
448 			/* Failure ... just try again! :-( */
449 			ps->electrify--;
450 		}
451 	}
452 }
453 
454 static void
SpecialExtraFarter(BMPlayer * ps)455 SpecialExtraFarter (BMPlayer * ps)
456 {
457 	ps->farter = 1;
458 }
459 
460 static void
SpecialKeyFarter(BMPlayer * ps)461 SpecialKeyFarter (BMPlayer * ps)
462 {
463 	if (ps != NULL) {
464 		if ((ps->lives > 0) && (ps->farter)) {
465 			/*     do_bell(); */
466 			FartOnOtherPlayers (ps);
467 		}
468 	}
469 }
470 
471 /* Fart on players and bombs (galatius) */
472 
473 static void
SpecialExtraBfarter(BMPlayer * ps)474 SpecialExtraBfarter (BMPlayer * ps)
475 {
476 	if (ps != NULL) {
477 		ps->bfarter = 1;
478 	}
479 }
480 
481 /* Fart on players and bombs (galatius) */
482 static void
SpecialKeyBfarter(BMPlayer * ps)483 SpecialKeyBfarter (BMPlayer * ps)
484 {
485 	if ((ps->lives > 0) && (ps->bfarter) && ps != NULL) {
486 		/*     do_bell(); */
487 		FartOnOtherPlayers (ps);
488 		DoAir (ps);
489 	}
490 }
491 
492 static void
SpecialExtraSwapColor(BMPlayer * ps)493 SpecialExtraSwapColor (BMPlayer * ps)
494 {
495 	SwapColorOtherPlayers (ps->team);
496 }
497 
498 static void
SpecialExtraSwapPosition(BMPlayer * ps)499 SpecialExtraSwapPosition (BMPlayer * ps)
500 {
501 	SwapPositionOtherPlayers (ps->team);
502 }
503 
504 /* */
505 
506 /*
507  * cloaking device
508  */
509 static void
SpecialExtraCloak(BMPlayer * ps)510 SpecialExtraCloak (BMPlayer * ps)
511 {
512 	int w = 1;
513 	if (ps->cloaking < 0) {
514 		ps->cloaking *= -1;
515 		w = -1;
516 	}
517 	ps->cloaking += 2 * EXTRA_INVINCIBLE;
518 	ps->cloaking *= w;
519 	SND_Play (SND_NEWCLOAK, ps->x / (PIXW / MAX_SOUND_POSITION));
520 }								/* SpecialExtraCloak */
521 
522 static void
SpecialKeyCloak(BMPlayer * ps)523 SpecialKeyCloak (BMPlayer * ps)
524 {
525 	ps->cloaking *= -1;
526 	if (ps->cloaking > 0) {
527 		SND_Play (SND_DECLOAK, ps->x / (PIXW / MAX_SOUND_POSITION));
528 	}
529 	else if (ps->cloaking < 0) {
530 		SND_Play (SND_ENCLOAK, ps->x / (PIXW / MAX_SOUND_POSITION));
531 	}
532 }								/* SpecialKeyCloak */
533 
534 /*
535  * pow extra (stun others)
536  */
537 void
SpecialExtraStunOthers(BMPlayer * ps)538 SpecialExtraStunOthers (BMPlayer * ps)
539 {
540 	StunOtherPlayers (ps->team, STUN_TIME * 4);
541 }
542 
543 /*
544  * morphing extra (player becomes a bomb)
545  */
546 static void
SpecialExtraMorph(BMPlayer * ps)547 SpecialExtraMorph (BMPlayer * ps)
548 {
549 	ps->num_morph++;
550 }
551 
552 static void
SpecialKeyMorph(BMPlayer * ps)553 SpecialKeyMorph (BMPlayer * ps)
554 {
555 	if ((0 < ps->num_morph) && (0 < ps->bombs) && (!ps->morphed)) {
556 #ifdef DEBUG
557 		fprintf (stderr, "Player %d morphs", ps->id);
558 #endif
559 		ps->morphed = 1;
560 		DropBomb (ps, BMTdefault);
561 	}
562 }								/* SpecialKeyMorph */
563 
564 static void
SpecialExtraStop(BMPlayer * ps)565 SpecialExtraStop (BMPlayer * ps)
566 {
567 
568 	ps->stop = XBTrue;
569 }
570 
571 static void
SpecialKeyStop(BMPlayer * ps)572 SpecialKeyStop (BMPlayer * ps)
573 {
574 	if (ps->stop > 0) {
575 
576 		StopPlayersBombs (ps);
577 	}
578 }
579 
580 /* Written by Amilhastre */
581 static void
SpecialExtraEvilGrail(BMPlayer * ps)582 SpecialExtraEvilGrail (BMPlayer * ps)
583 {
584 	ps->evilill = ILLDEATHTIME;
585 }
586 
587 /* phantom extra */
588 /* Written by Amilhastre */
589 static void
SpecialExtraPhantom(BMPlayer * ps)590 SpecialExtraPhantom (BMPlayer * ps)
591 {
592 	if (!ps->phantom)
593 		ps->phantom = 3 * EXTRA_INVISIBLE;
594 	else
595 		ps->phantom += EXTRA_INVISIBLE;
596 }
597 
598 /* revive extra */
599 /* Written by Amilhastre */
600 static void
SpecialExtraRevive(BMPlayer * ps)601 SpecialExtraRevive (BMPlayer * ps)
602 {
603 	ps->revive++;
604 }
605 
606 /* ** Skywalker **
607  * sniping extra (player moves the bomb)
608  */
609 static void
SpecialExtraSnipe(BMPlayer * ps)610 SpecialExtraSnipe (BMPlayer * ps)
611 {
612 	ps->num_snipe++;
613 }
614 
615 static void
SpecialKeySnipe(BMPlayer * ps)616 SpecialKeySnipe (BMPlayer * ps)
617 {
618 	if ((0 < ps->num_snipe) && (0 < ps->bombs) && (ps->sniping == 0)) {
619 
620 		ps->sniping = 2;
621 		DropBomb (ps, BMTdefault);
622 		ps->sniping = 1;
623 	}
624 	else {
625 		if (ps->sniping == 1) {
626 			if (IgnitePlayersBombs (ps)) {
627 				ps->sniping = 1;
628 				ps->d_soll = GoStop;
629 			}
630 		}
631 	}
632 
633 }								/* SpecialKeySnipe */
634 
635 /* EPFL */
636 
637 static void
SpecialExtraJump(BMPlayer * ps)638 SpecialExtraJump (BMPlayer * ps)
639 {
640 	SND_Play (SND_NEWPUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
641 	ps->jump_button += 1;
642 }
643 
644 static void
SpecialKeyJump(BMPlayer * ps)645 SpecialKeyJump (BMPlayer * ps)
646 {
647 	if ((ps->jump_button > 0) && (ps->lives > 0)) {
648 		SND_Play (SND_PUMP, ps->x / (PIXW / MAX_SOUND_POSITION));
649 		DoJump (ps);
650 	}
651 }
652 
653 /* END EPFL */
654 
655 /*
656  * conversion tables
657  */
658 /* extra pickup functions */
659 static DBToData extraTable[] = {
660 	{"air", (void *)SpecialExtraAir},
661 	{"bfarter", (void *)SpecialExtraBfarter},	/* skywalker */
662 	{"choicebombtype", (void *)SpecialExtraChoice},	/* skywalker */
663 	{"cloak", (void *)SpecialExtraCloak},
664 	{"daleif", (void *)SpecialExtraDaleif},
665 	{"electrify", (void *)SpecialExtraElectrify},
666 	{"evilgrail", (void *)SpecialExtraEvilGrail},
667 	{"farter", (void *)SpecialExtraFarter},	/* skywalker */
668 	{"frogger", (void *)SpecialExtraFrogger},	/* skywalker */
669 	{"ghost", (void *)SpecialExtraGhost},	/* skywalker */
670 	{"holyGrail", (void *)SpecialExtraHolyGrail},
671 	{"igniteAll", (void *)SpecialExtraIgniteAll},
672 	{"invincible", (void *)SpecialExtraInvincible},
673 	{"jump", (void *)SpecialExtraJump},	/* skywalker */
674 	{"junkie", (void *)SpecialExtraJunkie},
675 	{"kick", (void *)SpecialExtraKick},
676 	{"life", (void *)SpecialExtraLife},
677 	{"longStunned", (void *)SpecialExtraLongStunned},
678 	{"mayhem", (void *)SpecialExtraMayhem},
679 	{"morph", (void *)SpecialExtraMorph},
680 	{"multiple", (void *)SpecialExtraMultiple},
681 	{"phantom", (void *)SpecialExtraPhantom},
682 	{"poison", (void *)SpecialExtraPoison},
683 	{"rc", (void *)SpecialExtraRC},
684 	{"revive", (void *)SpecialExtraRevive},
685 	{"slow", (void *)SpecialExtraSlow},
686 	{"snipe", (void *)SpecialExtraSnipe},	/* skywalker */
687 	{"specialBomb", (void *)SpecialExtraSpecialBomb},
688 	{"speed", (void *)SpecialExtraSpeed},
689 	{"speed2", (void *)SpecialExtraSpeed2},
690 	{"steal", (void *)SpecialExtraSteal},
691 	{"stop", (void *)SpecialExtraStop},
692 	{"stunOthers", (void *)SpecialExtraStunOthers},
693 	{"sucker", (void *)SpecialExtraSuck},
694 	{"swapcolor", (void *)SpecialExtraSwapColor},	/* skywalker */
695 	{"swapposition", (void *)SpecialExtraSwapPosition},	/* skywalker */
696 	{"teleport", (void *)SpecialExtraTeleport},
697 	{"through", (void *)SpecialExtraThrough},
698 	{"void", (void *)SpecialExtraVoid},
699 	{NULL, NULL}
700 };
701 
702 /* extra key functions */
703 static DBToData keyTable[] = {
704 	{"air", (void *)SpecialKeyAir},
705 	{"bfarter", (void *)SpecialKeyBfarter},
706 	{"choicebombtype", (void *)SpecialKeyChoice},	/* skywalker */
707 	{"cloak", (void *)SpecialKeyCloak},
708 	{"electrify", (void *)SpecialKeyElectrify},
709 	{"farter", (void *)SpecialKeyFarter},	/* skywalker */
710 	{"frogger", (void *)SpecialKeyFrogger},	/* skywalker */
711 	{"jump", (void *)SpecialKeyJump},	/* skywalker */
712 	{"morph", (void *)SpecialKeyMorph},
713 	{"rc", (void *)SpecialKeyRC},
714 	{"snipe", (void *)SpecialKeySnipe},	/* skywalker */
715 	{"specialBomb", (void *)SpecialKeySpecialBomb},
716 	{"stop", (void *)SpecialKeyStop},
717 	{"sucker", (void *)SpecialKeySuck},
718 	{"teleport", (void *)SpecialKeyTeleport},
719 	{"through", (void *)SpecialKeyThrough},
720 	{"void", (void *)SpecialKeyVoid},
721 	{NULL, NULL}
722 };
723 
724 /*
725  * parse func section of level data
726  */
727 XBBool
ParseLevelFunc(const DBSection * section,DBSection * warn)728 ParseLevelFunc (const DBSection * section, DBSection * warn)
729 {
730 	void *ptr;
731 	/* check if section exists */
732 	if (NULL == section) {
733 		Dbg_Out ("LEVEL: func section is missing!\n");
734 		DB_CreateEntryString (warn, atomMissing, "true");
735 		return XBFalse;
736 	}
737 	/* Extra has default */
738 	switch (DB_ConvertEntryData (section, atomExtra, &ptr, extraTable)) {
739 	case DCR_NoSuchEntry:
740 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomExtra));
741 		specialExtraFunc = SpecialExtraVoid;
742 		break;
743 	case DCR_Failure:
744 		Dbg_Out ("LEVEL: warning for %s\n", DB_SectionEntryString (section, atomExtra));
745 		specialExtraFunc = SpecialExtraVoid;
746 		DB_CreateEntryString (warn, atomExtra, DB_DataToString (extraTable, specialExtraFunc));
747 		break;
748 	default:
749 		assert (ptr != NULL);
750 		specialExtraFunc = (SpecialExtraFunc) ptr;
751 		break;
752 	}
753 	/* check for swap extras, buggy for < 2.10.2 */
754 	if (!Version_AtLeast (VERSION_JOINT, &Ver_2_10_2)) {
755 		if (specialExtraFunc == SpecialExtraSwapColor) {
756 			/* add warning and reject level */
757 			DB_CreateEntryString (warn, atomExtra, DB_DataToString (extraTable, specialExtraFunc));
758 			return XBFalse;
759 		}
760 	}
761 	/* Key has default */
762 	switch (DB_ConvertEntryData (section, atomKey, &ptr, keyTable)) {
763 	case DCR_NoSuchEntry:
764 		Dbg_Level ("default for %s\n", DB_SectionEntryString (section, atomKey));
765 		specialKeyFunc = SpecialKeyVoid;
766 		break;
767 	case DCR_Failure:
768 		Dbg_Out ("LEVEL: warning for %s\n", DB_SectionEntryString (section, atomKey));
769 		specialKeyFunc = SpecialKeyVoid;
770 		DB_CreateEntryString (warn, atomExtra, DB_DataToString (keyTable, specialKeyFunc));
771 		break;
772 	default:
773 		assert (ptr != NULL);
774 		specialKeyFunc = (SpecialKeyFunc) ptr;
775 		break;
776 	}
777 	return XBTrue;
778 }
779 
780 /*
781  * config section [FUNC]
782  */
783 void
ConfigLevelFunc(const DBSection * section)784 ConfigLevelFunc (const DBSection * section)
785 {
786 	/* set extra info */
787 	if (specialExtraFunc == SpecialExtraAir) {
788 		AddExtraInfo (N_("Airpump as an extra"));
789 	}
790 	else if (specialExtraFunc == SpecialExtraBfarter) {	/* skywalker */
791 		AddExtraInfo (N_("Bfarter as an extra"));
792 	}
793 	else if (specialExtraFunc == SpecialExtraChoice) {	/* skywalker */
794 		AddExtraInfo (N_("Choice as an extra"));
795 	}
796 	else if (specialExtraFunc == SpecialExtraCloak) {
797 		AddExtraInfo (N_("Cloak as an extra"));
798 	}
799 	else if (specialExtraFunc == SpecialExtraDaleif) {
800 		AddExtraInfo (N_("Daleif as an extra"));
801 	}
802 	else if (specialExtraFunc == SpecialExtraElectrify) {
803 		AddExtraInfo (N_("Electrify as an extra"));
804 	}
805 	else if (specialExtraFunc == SpecialExtraFarter) {	/* skywalker */
806 		AddExtraInfo (N_("Farter as an extra"));
807 	}
808 	else if (specialExtraFunc == SpecialExtraFrogger) {	/* skywalker */
809 		AddExtraInfo (N_("Frogger as an extra"));
810 	}
811 	else if (specialExtraFunc == SpecialExtraGhost) {	/* skywalker */
812 		AddExtraInfo (N_("Ghost as an extra"));
813 	}
814 	else if (specialExtraFunc == SpecialExtraHolyGrail) {
815 		AddExtraInfo (N_("The Holy Grail as an extra"));
816 	}
817 	else if (specialExtraFunc == SpecialExtraIgniteAll) {
818 		AddExtraInfo (N_("Button as an extra"));
819 	}
820 	else if (specialExtraFunc == SpecialExtraInvincible) {
821 		AddExtraInfo (N_("Invincibility as an extra"));
822 	}
823 	else if (specialExtraFunc == SpecialExtraJump) {
824 		AddExtraInfo (N_("Jump as an extra"));
825 	}
826 	else if (specialExtraFunc == SpecialExtraJunkie) {
827 		AddExtraInfo (N_("Junkie virus as an extra"));
828 	}
829 	else if (specialExtraFunc == SpecialExtraKick) {
830 		AddExtraInfo (N_("Kick as an extra"));
831 	}
832 	else if (specialExtraFunc == SpecialExtraLife) {
833 		AddExtraInfo (N_("Free life as an extra"));
834 	}
835 	else if (specialExtraFunc == SpecialExtraLongStunned) {
836 		AddExtraInfo (N_("Spinner as an extra"));
837 	}
838 	else if (specialExtraFunc == SpecialExtraMayhem) {
839 		AddExtraInfo (N_("Mayhem (Kick & Run) as an extra"));
840 	}
841 	else if (specialExtraFunc == SpecialExtraMorph) {
842 		AddExtraInfo (N_("Morphing as an extra"));
843 	}
844 	else if (specialExtraFunc == SpecialExtraMultiple) {
845 		AddExtraInfo (N_("Random special extra"));
846 	}
847 	else if (specialExtraFunc == SpecialExtraPhantom) {
848 		AddExtraInfo (N_("Phantom as an extra"));
849 	}
850 	else if (specialExtraFunc == SpecialExtraPoison) {
851 		AddExtraInfo (N_("Poison as an extra"));
852 	}
853 	else if (specialExtraFunc == SpecialExtraRC) {
854 		AddExtraInfo (N_("Remote control as an extra"));
855 	}
856 	else if (specialExtraFunc == SpecialExtraRevive) {
857 		AddExtraInfo (N_("Revive control as an extra"));
858 	}
859 	else if (specialExtraFunc == SpecialExtraSnipe) {	/* skywalker */
860 		AddExtraInfo (N_("Snipe as an extra"));
861 	}
862 	else if (specialExtraFunc == SpecialExtraStop) {	/* skywalker */
863 		AddExtraInfo (N_("Stop as an extra"));
864 	}
865 	else if (specialExtraFunc == SpecialExtraSuck) {	/* skywalker */
866 		AddExtraInfo (N_("Sucker as an extra"));
867 	}
868 	else if (specialExtraFunc == SpecialExtraSwapColor) {	/* skywalker */
869 		AddExtraInfo (N_("Swapcolor as an extra"));
870 	}
871 	else if (specialExtraFunc == SpecialExtraSwapPosition) {	/* skywalker */
872 		AddExtraInfo (N_("Swapposition as an extra"));
873 	}
874 	else if (specialExtraFunc == SpecialExtraSlow) {
875 		AddExtraInfo (N_("Slowdown as an extra"));
876 	}
877 	else if (specialExtraFunc == SpecialExtraSpeed) {
878 		AddExtraInfo (N_("Speed as an extra"));
879 	}
880 	else if (specialExtraFunc == SpecialExtraSpeed2) {
881 		AddExtraInfo (N_("SpeedII as an extra"));
882 	}
883 	else if (specialExtraFunc == SpecialExtraStop) {
884 		AddExtraInfo (N_("Stop as an extra"));
885 	}
886 	else if (specialExtraFunc == SpecialExtraStunOthers) {
887 		AddExtraInfo (N_("Stunner as an extra"));
888 	}
889 	else if (specialExtraFunc == SpecialExtraTeleport) {
890 		AddExtraInfo (N_("Teleporter as an extra"));
891 	}
892 	else if (specialExtraFunc == SpecialExtraThrough) {
893 		AddExtraInfo (N_("Through as an extra"));
894 	}
895 }								/* ConfigLevelFunc */
896 
897 /*
898  *
899  */
900 XBBool
HasSpecialBombs(void)901 HasSpecialBombs (void)
902 {
903 	return (specialExtraFunc == SpecialExtraSpecialBomb);
904 }								/* HasSpecialBombs */
905 
906 /*
907  * return the name of the extra type
908  */
909 const char *
GetExtraNameFunc(void * type)910 GetExtraNameFunc (void *type)
911 {
912 	int i;
913 	if (type == SpecialExtraVoid)
914 		return seVoidName;
915 	for (i = 0; extraTable[i].value != NULL; ++i)
916 		if (extraTable[i].value == type)
917 			return extraTable[i].key;
918 	return seVoidName;
919 }
920 const char *
GetExtraNameInt(int type)921 GetExtraNameInt (int type)
922 {
923 	int i;
924 	for (i = 0; extraTable[i].value != NULL; ++i)
925 		if (i == type)
926 			return extraTable[i].key;
927 	return seVoidName;
928 }
929 
930 /*
931  * return the name of the key type
932  */
933 const char *
GetKeyNameFunc(void * type)934 GetKeyNameFunc (void *type)
935 {
936 	int i;
937 	if (type == SpecialKeyVoid)
938 		return skVoidName;
939 	for (i = 0; keyTable[i].value != NULL; ++i)
940 		if (keyTable[i].value == type)
941 			return keyTable[i].key;
942 	return skVoidName;
943 }
944 const char *
GetKeyNameInt(int type)945 GetKeyNameInt (int type)
946 {
947 	int i;
948 	for (i = 0; keyTable[i].value != NULL; ++i)
949 		if (i == type)
950 			return keyTable[i].key;
951 	return skVoidName;
952 }
953 
954 /*
955  * return the number of the key type
956  */
957 int
GetNumberOfKeys(void)958 GetNumberOfKeys (void)
959 {
960 	int i;
961 	for (i = 0; keyTable[i].value != NULL; ++i) ;
962 	return i;
963 }
964 
965 /*
966  * return the number of the extra type
967  */
968 int
GetNumberOfExtras(void)969 GetNumberOfExtras (void)
970 {
971 	int i;
972 	for (i = 0; extraTable[i].value != NULL; ++i) ;
973 	return i;
974 }
975 
976 /*
977  * end of file func.c
978  */
979